video: Initial support for multiple framebuffers
This commit is contained in:
parent
9b68f081cf
commit
d39baeaa80
@ -50,11 +50,7 @@ success:
|
||||
|
||||
#include <efi.h>
|
||||
|
||||
struct edid_info_struct *get_edid_info(void) {
|
||||
if (!gop_ready) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
struct edid_info_struct *get_edid_info(EFI_HANDLE gop_handle) {
|
||||
struct edid_info_struct *buf = ext_mem_alloc(sizeof(struct edid_info_struct));
|
||||
|
||||
EFI_STATUS status;
|
||||
|
@ -30,6 +30,14 @@ struct edid_info_struct {
|
||||
uint8_t checksum;
|
||||
} __attribute__((packed));
|
||||
|
||||
#if defined (UEFI)
|
||||
#include <efi.h>
|
||||
|
||||
struct edid_info_struct *get_edid_info(EFI_HANDLE gop_handle);
|
||||
#endif
|
||||
|
||||
#if defined (BIOS)
|
||||
struct edid_info_struct *get_edid_info(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -37,7 +37,7 @@ static void linear_mask_to_mask_shift(
|
||||
|
||||
// Most of this code taken from https://wiki.osdev.org/GOP
|
||||
|
||||
static bool mode_to_fb_info(struct fb_info *ret, size_t mode) {
|
||||
static bool mode_to_fb_info(struct fb_info *ret, EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, size_t mode) {
|
||||
EFI_STATUS status;
|
||||
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
|
||||
@ -98,10 +98,12 @@ static bool mode_to_fb_info(struct fb_info *ret, size_t mode) {
|
||||
|
||||
bool gop_force_16 = false;
|
||||
|
||||
static bool try_mode(struct fb_info *ret, size_t mode, uint64_t width, uint64_t height, int bpp) {
|
||||
static bool try_mode(struct fb_info *ret, EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
|
||||
size_t mode, uint64_t width, uint64_t height, int bpp,
|
||||
struct fb_info *fbs, size_t fbs_count) {
|
||||
EFI_STATUS status;
|
||||
|
||||
if (!mode_to_fb_info(ret, mode)) {
|
||||
if (!mode_to_fb_info(ret, gop, mode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -121,22 +123,25 @@ static bool try_mode(struct fb_info *ret, size_t mode, uint64_t width, uint64_t
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < fbs_count; i++) {
|
||||
if (gop->Mode->FrameBufferBase == fbs[i].framebuffer_addr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
printv("gop: Found matching mode %x, attempting to set...\n", mode);
|
||||
|
||||
if ((int)mode == current_video_mode) {
|
||||
if (mode == gop->Mode->Mode) {
|
||||
printv("gop: Mode was already set, perfect!\n");
|
||||
} else {
|
||||
status = gop->SetMode(gop, mode);
|
||||
|
||||
if (status) {
|
||||
current_video_mode = -1;
|
||||
printv("gop: Failed to set video mode %x, moving on...\n", mode);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
current_video_mode = mode;
|
||||
|
||||
ret->framebuffer_addr = gop->Mode->FrameBufferBase;
|
||||
|
||||
fb_clear(ret);
|
||||
@ -144,18 +149,14 @@ static bool try_mode(struct fb_info *ret, size_t mode, uint64_t width, uint64_t
|
||||
return true;
|
||||
}
|
||||
|
||||
struct fb_info *gop_get_mode_list(size_t *count) {
|
||||
if (!gop_ready) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct fb_info *get_mode_list(size_t *count, EFI_GRAPHICS_OUTPUT_PROTOCOL *gop) {
|
||||
UINTN modes_count = gop->Mode->MaxMode;
|
||||
|
||||
struct fb_info *ret = ext_mem_alloc(modes_count * sizeof(struct fb_info));
|
||||
|
||||
size_t actual_count = 0;
|
||||
for (size_t i = 0; i < modes_count; i++) {
|
||||
if (mode_to_fb_info(&ret[actual_count], i)) {
|
||||
if (mode_to_fb_info(&ret[actual_count], gop, i)) {
|
||||
actual_count++;
|
||||
}
|
||||
}
|
||||
@ -170,21 +171,8 @@ struct fb_info *gop_get_mode_list(size_t *count) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define INVALID_PRESET_MODE 0xffffffff
|
||||
|
||||
static no_unwind size_t preset_mode = INVALID_PRESET_MODE;
|
||||
static no_unwind EFI_GRAPHICS_OUTPUT_MODE_INFORMATION preset_mode_info;
|
||||
|
||||
bool gop_ready = false;
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
|
||||
EFI_HANDLE gop_handle;
|
||||
|
||||
bool init_gop(struct fb_info *ret,
|
||||
void init_gop(struct fb_info **ret, size_t *_fbs_count,
|
||||
uint64_t target_width, uint64_t target_height, uint16_t target_bpp) {
|
||||
gop_ready = false;
|
||||
|
||||
ret->default_res = false;
|
||||
|
||||
EFI_STATUS status;
|
||||
|
||||
EFI_HANDLE tmp_handles[1];
|
||||
@ -196,7 +184,8 @@ bool init_gop(struct fb_info *ret,
|
||||
status = gBS->LocateHandle(ByProtocol, &gop_guid, NULL, &handles_size, handles);
|
||||
|
||||
if (status != EFI_SUCCESS && status != EFI_BUFFER_TOO_SMALL) {
|
||||
return false;
|
||||
*_fbs_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
handles = ext_mem_alloc(handles_size);
|
||||
@ -204,45 +193,15 @@ bool init_gop(struct fb_info *ret,
|
||||
status = gBS->LocateHandle(ByProtocol, &gop_guid, NULL, &handles_size, handles);
|
||||
if (status != EFI_SUCCESS) {
|
||||
pmm_free(handles, handles_size);
|
||||
return false;
|
||||
*_fbs_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
gop_handle = handles[0];
|
||||
pmm_free(handles, handles_size);
|
||||
size_t handles_count = handles_size / sizeof(EFI_HANDLE);
|
||||
|
||||
status = gBS->HandleProtocol(gop_handle, &gop_guid, (void **)&gop);
|
||||
if (status != EFI_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
*ret = ext_mem_alloc(handles_count * sizeof(struct fb_info));
|
||||
|
||||
gop_ready = true;
|
||||
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
|
||||
UINTN mode_info_size;
|
||||
|
||||
status = gop->QueryMode(gop, gop->Mode == NULL ? 0 : gop->Mode->Mode,
|
||||
&mode_info_size, &mode_info);
|
||||
|
||||
if (status == EFI_NOT_STARTED) {
|
||||
status = gop->SetMode(gop, 0);
|
||||
if (status) {
|
||||
panic(false, "gop: Initialisation failed");
|
||||
}
|
||||
status = gop->QueryMode(gop, gop->Mode == NULL ? 0 : gop->Mode->Mode,
|
||||
&mode_info_size, &mode_info);
|
||||
}
|
||||
|
||||
if (status) {
|
||||
panic(false, "gop: Initialisation failed");
|
||||
}
|
||||
|
||||
if (preset_mode == INVALID_PRESET_MODE) {
|
||||
preset_mode = gop->Mode->Mode;
|
||||
memcpy(&preset_mode_info, mode_info, mode_info_size);
|
||||
current_video_mode = preset_mode;
|
||||
}
|
||||
|
||||
struct resolution fallback_resolutions[] = {
|
||||
const struct resolution fallback_resolutions[] = {
|
||||
{ 0, 0, 0 }, // Overridden by EDID
|
||||
{ 0, 0, 0 }, // Overridden by preset
|
||||
{ 1024, 768, 32 },
|
||||
@ -256,67 +215,111 @@ bool init_gop(struct fb_info *ret,
|
||||
{ 640, 480, 16 }
|
||||
};
|
||||
|
||||
UINTN modes_count = gop->Mode->MaxMode;
|
||||
size_t fbs_count = 0;
|
||||
for (size_t i = 0; i < handles_count; i++) {
|
||||
struct fb_info *fb = &(*ret)[fbs_count];
|
||||
|
||||
size_t current_fallback = 0;
|
||||
uint64_t _target_width = target_width;
|
||||
uint64_t _target_height = target_height;
|
||||
uint64_t _target_bpp = target_bpp;
|
||||
|
||||
if (!target_width || !target_height || !target_bpp) {
|
||||
goto fallback;
|
||||
} else {
|
||||
printv("gop: Requested resolution of %ux%ux%u\n",
|
||||
target_width, target_height, target_bpp);
|
||||
}
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
|
||||
|
||||
status = gBS->HandleProtocol(handles[i], &gop_guid, (void **)&gop);
|
||||
if (status != EFI_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
|
||||
UINTN mode_info_size;
|
||||
|
||||
status = gop->QueryMode(gop, gop->Mode == NULL ? 0 : gop->Mode->Mode,
|
||||
&mode_info_size, &mode_info);
|
||||
|
||||
if (status == EFI_NOT_STARTED) {
|
||||
status = gop->SetMode(gop, 0);
|
||||
if (status) {
|
||||
continue;
|
||||
}
|
||||
status = gop->QueryMode(gop, gop->Mode == NULL ? 0 : gop->Mode->Mode,
|
||||
&mode_info_size, &mode_info);
|
||||
}
|
||||
|
||||
if (status) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int preset_mode = gop->Mode->Mode;
|
||||
|
||||
fb->edid = get_edid_info(handles[i]);
|
||||
|
||||
UINTN modes_count = gop->Mode->MaxMode;
|
||||
|
||||
size_t current_fallback = 0;
|
||||
|
||||
if (!_target_width || !_target_height || !_target_bpp) {
|
||||
goto fallback;
|
||||
} else {
|
||||
printv("gop: Requested resolution of %ux%ux%u\n",
|
||||
_target_width, _target_height, _target_bpp);
|
||||
}
|
||||
|
||||
retry:
|
||||
for (size_t i = 0; i < modes_count; i++) {
|
||||
if (try_mode(ret, i, target_width, target_height, target_bpp)) {
|
||||
gop_force_16 = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
fallback:
|
||||
ret->default_res = true;
|
||||
|
||||
if (current_fallback == 0) {
|
||||
current_fallback++;
|
||||
|
||||
struct edid_info_struct *edid_info = get_edid_info();
|
||||
if (edid_info != NULL) {
|
||||
uint64_t edid_width = (uint64_t)edid_info->det_timing_desc1[2];
|
||||
edid_width += ((uint64_t)edid_info->det_timing_desc1[4] & 0xf0) << 4;
|
||||
uint64_t edid_height = (uint64_t)edid_info->det_timing_desc1[5];
|
||||
edid_height += ((uint64_t)edid_info->det_timing_desc1[7] & 0xf0) << 4;
|
||||
if (edid_width >= preset_mode_info.HorizontalResolution
|
||||
&& edid_height >= preset_mode_info.VerticalResolution) {
|
||||
target_width = edid_width;
|
||||
target_height = edid_height;
|
||||
target_bpp = 32;
|
||||
goto retry;
|
||||
for (size_t j = 0; j < modes_count; j++) {
|
||||
if (try_mode(fb, gop, j, _target_width, _target_height, _target_bpp, *ret, fbs_count)) {
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (current_fallback == 1) {
|
||||
current_fallback++;
|
||||
fallback:
|
||||
if (current_fallback == 0) {
|
||||
current_fallback++;
|
||||
|
||||
if (try_mode(ret, preset_mode, 0, 0, 0)) {
|
||||
gop_force_16 = false;
|
||||
return true;
|
||||
if (fb->edid != NULL) {
|
||||
uint64_t edid_width = (uint64_t)fb->edid->det_timing_desc1[2];
|
||||
edid_width += ((uint64_t)fb->edid->det_timing_desc1[4] & 0xf0) << 4;
|
||||
uint64_t edid_height = (uint64_t)fb->edid->det_timing_desc1[5];
|
||||
edid_height += ((uint64_t)fb->edid->det_timing_desc1[7] & 0xf0) << 4;
|
||||
if (edid_width >= mode_info->HorizontalResolution
|
||||
&& edid_height >= mode_info->VerticalResolution) {
|
||||
_target_width = edid_width;
|
||||
_target_height = edid_height;
|
||||
_target_bpp = 32;
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (current_fallback == 1) {
|
||||
current_fallback++;
|
||||
|
||||
if (try_mode(fb, gop, preset_mode, 0, 0, 0, *ret, fbs_count)) {
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
|
||||
if (current_fallback < SIZEOF_ARRAY(fallback_resolutions)) {
|
||||
current_fallback++;
|
||||
|
||||
_target_width = fallback_resolutions[current_fallback].width;
|
||||
_target_height = fallback_resolutions[current_fallback].height;
|
||||
_target_bpp = fallback_resolutions[current_fallback].bpp;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
success:
|
||||
fb->mode_list = get_mode_list(&fb->mode_count, gop);
|
||||
|
||||
fbs_count++;
|
||||
}
|
||||
|
||||
if (current_fallback < SIZEOF_ARRAY(fallback_resolutions)) {
|
||||
current_fallback++;
|
||||
|
||||
target_width = fallback_resolutions[current_fallback].width;
|
||||
target_height = fallback_resolutions[current_fallback].height;
|
||||
target_bpp = fallback_resolutions[current_fallback].bpp;
|
||||
goto retry;
|
||||
}
|
||||
pmm_free(handles, handles_size);
|
||||
|
||||
gop_force_16 = false;
|
||||
return false;
|
||||
|
||||
*_fbs_count = fbs_count;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -6,20 +6,13 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <efi.h>
|
||||
#include <lib/fb.h>
|
||||
|
||||
bool init_gop(struct fb_info *ret,
|
||||
void init_gop(struct fb_info **ret, size_t *_fbs_count,
|
||||
uint64_t target_width, uint64_t target_height, uint16_t target_bpp);
|
||||
|
||||
struct fb_info *gop_get_mode_list(size_t *count);
|
||||
|
||||
extern bool gop_force_16;
|
||||
|
||||
extern bool gop_ready;
|
||||
extern EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
|
||||
extern EFI_HANDLE gop_handle;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -187,8 +187,6 @@ bool init_vbe(struct fb_info *ret,
|
||||
uint16_t target_width, uint16_t target_height, uint16_t target_bpp) {
|
||||
printv("vbe: Initialising...\n");
|
||||
|
||||
ret->default_res = false;
|
||||
|
||||
size_t current_fallback = 0;
|
||||
|
||||
struct vbe_info_struct vbe_info;
|
||||
@ -216,8 +214,6 @@ bool init_vbe(struct fb_info *ret,
|
||||
};
|
||||
|
||||
if (!target_width || !target_height || !target_bpp) {
|
||||
ret->default_res = true;
|
||||
|
||||
struct edid_info_struct *edid_info = get_edid_info();
|
||||
if (edid_info != NULL) {
|
||||
int edid_width = (int)edid_info->det_timing_desc1[2];
|
||||
@ -293,8 +289,6 @@ retry:
|
||||
}
|
||||
|
||||
fallback:
|
||||
ret->default_res = true;
|
||||
|
||||
if (current_fallback < SIZEOF_ARRAY(fallback_resolutions)) {
|
||||
target_width = fallback_resolutions[current_fallback].width;
|
||||
target_height = fallback_resolutions[current_fallback].height;
|
||||
|
@ -253,10 +253,7 @@ static void text_deinit(struct term_context *_ctx, void (*_free)(void *, size_t)
|
||||
static struct textmode_context term_local_struct;
|
||||
|
||||
void vga_textmode_init(bool managed) {
|
||||
if (term != NULL) {
|
||||
term->deinit(term, pmm_free);
|
||||
term = NULL;
|
||||
}
|
||||
term_notready();
|
||||
|
||||
if (quiet) {
|
||||
return;
|
||||
@ -270,6 +267,13 @@ void vga_textmode_init(bool managed) {
|
||||
current_video_mode = 0x3;
|
||||
}
|
||||
|
||||
terms = ext_mem_alloc(sizeof(void *));
|
||||
terms_i = 1;
|
||||
|
||||
terms[0] = ext_mem_alloc(sizeof(struct term_context));
|
||||
|
||||
struct term_context *term = terms[0];
|
||||
|
||||
struct textmode_context *ctx = &term_local_struct;
|
||||
term = &term_local_struct.term;
|
||||
|
||||
|
@ -38,6 +38,8 @@ noreturn void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
|
||||
|
||||
gST->ConOut->EnableCursor(gST->ConOut, false);
|
||||
|
||||
init_memmap();
|
||||
|
||||
term_fallback();
|
||||
|
||||
status = gBS->SetWatchdogTimer(0, 0x10000, 0, NULL);
|
||||
@ -45,8 +47,6 @@ noreturn void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
|
||||
print("WARNING: Failed to disable watchdog timer!\n");
|
||||
}
|
||||
|
||||
init_memmap();
|
||||
|
||||
#if defined (__x86_64__) || defined (__i386__)
|
||||
init_gdt();
|
||||
#endif
|
||||
|
@ -6,24 +6,23 @@
|
||||
#include <drivers/gop.h>
|
||||
#include <mm/pmm.h>
|
||||
|
||||
bool fb_init(struct fb_info *ret,
|
||||
void fb_init(struct fb_info **ret, size_t *_fbs_count,
|
||||
uint64_t target_width, uint64_t target_height, uint16_t target_bpp) {
|
||||
bool r;
|
||||
|
||||
#if defined (BIOS)
|
||||
r = init_vbe(ret, target_width, target_height, target_bpp);
|
||||
#elif defined (UEFI)
|
||||
r = init_gop(ret, target_width, target_height, target_bpp);
|
||||
#endif
|
||||
*ret = ext_mem_alloc(sizeof(struct fb_info));
|
||||
if (init_vbe(*ret, target_width, target_height, target_bpp)) {
|
||||
*_fbs_count = 1;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
struct fb_info *fb_get_mode_list(size_t *count) {
|
||||
#if defined (BIOS)
|
||||
return vbe_get_mode_list(count);
|
||||
(*ret)->edid = get_edid_info();
|
||||
size_t mode_count;
|
||||
(*ret)->mode_list = vbe_get_mode_list(&mode_count);
|
||||
(*ret)->mode_count = mode_count;
|
||||
} else {
|
||||
*_fbs_count = 0;
|
||||
pmm_free(*ret, sizeof(struct fb_info));
|
||||
}
|
||||
#elif defined (UEFI)
|
||||
return gop_get_mode_list(count);
|
||||
init_gop(ret, _fbs_count, target_width, target_height, target_bpp);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <drivers/edid.h>
|
||||
|
||||
struct resolution {
|
||||
uint64_t width;
|
||||
@ -15,23 +16,25 @@ struct fb_info {
|
||||
uint64_t framebuffer_width;
|
||||
uint64_t framebuffer_height;
|
||||
uint16_t framebuffer_bpp;
|
||||
uint8_t memory_model;
|
||||
uint8_t red_mask_size;
|
||||
uint8_t red_mask_shift;
|
||||
uint8_t green_mask_size;
|
||||
uint8_t green_mask_shift;
|
||||
uint8_t blue_mask_size;
|
||||
uint8_t blue_mask_shift;
|
||||
uint8_t memory_model;
|
||||
uint8_t red_mask_size;
|
||||
uint8_t red_mask_shift;
|
||||
uint8_t green_mask_size;
|
||||
uint8_t green_mask_shift;
|
||||
uint8_t blue_mask_size;
|
||||
uint8_t blue_mask_shift;
|
||||
|
||||
bool default_res;
|
||||
uint64_t framebuffer_addr;
|
||||
|
||||
struct edid_info_struct *edid;
|
||||
|
||||
uint64_t mode_count;
|
||||
struct fb_info *mode_list;
|
||||
};
|
||||
|
||||
bool fb_init(struct fb_info *ret,
|
||||
void fb_init(struct fb_info **ret, size_t *_fbs_count,
|
||||
uint64_t target_width, uint64_t target_height, uint16_t target_bpp);
|
||||
|
||||
struct fb_info *fb_get_mode_list(size_t *count);
|
||||
|
||||
void fb_clear(struct fb_info *fb);
|
||||
|
||||
#endif
|
||||
|
@ -360,8 +360,6 @@ static const uint8_t builtin_font[] = {
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
struct fb_info fbinfo;
|
||||
|
||||
static struct image *background;
|
||||
|
||||
static size_t margin = 64;
|
||||
@ -389,10 +387,10 @@ static inline uint32_t colour_blend(uint32_t fg, uint32_t bg) {
|
||||
return ARGB(0, r, g, b);
|
||||
}
|
||||
|
||||
static uint32_t blend_gradient_from_box(size_t x, size_t y, uint32_t bg_px, uint32_t hex) {
|
||||
static uint32_t blend_gradient_from_box(struct fb_info *fb, size_t x, size_t y, uint32_t bg_px, uint32_t hex) {
|
||||
size_t distance, x_distance, y_distance;
|
||||
size_t gradient_stop_x = fbinfo.framebuffer_width - margin;
|
||||
size_t gradient_stop_y = fbinfo.framebuffer_height - margin;
|
||||
size_t gradient_stop_x = fb->framebuffer_width - margin;
|
||||
size_t gradient_stop_y = fb->framebuffer_height - margin;
|
||||
|
||||
if (x < margin)
|
||||
x_distance = margin - x;
|
||||
@ -427,7 +425,7 @@ static size_t fixedp6_to_int(fixedp6 value) { return value / 64; }
|
||||
static fixedp6 int_to_fixedp6(size_t value) { return value * 64; }
|
||||
|
||||
// Draw rect at coordinates, copying from the image to the fb and canvas, applying fn on every pixel
|
||||
__attribute__((always_inline)) static inline void genloop(size_t xstart, size_t xend, size_t ystart, size_t yend, uint32_t (*blend)(size_t x, size_t y, uint32_t orig)) {
|
||||
__attribute__((always_inline)) static inline void genloop(struct fb_info *fb, size_t xstart, size_t xend, size_t ystart, size_t yend, uint32_t (*blend)(struct fb_info *fb, size_t x, size_t y, uint32_t orig)) {
|
||||
uint8_t *img = background->img;
|
||||
const size_t img_width = background->img_width, img_height = background->img_height, img_pitch = background->pitch, colsize = background->bpp / 8;
|
||||
|
||||
@ -436,10 +434,10 @@ __attribute__((always_inline)) static inline void genloop(size_t xstart, size_t
|
||||
for (size_t y = ystart; y < yend; y++) {
|
||||
size_t image_y = y % img_height, image_x = xstart % img_width;
|
||||
const size_t off = img_pitch * (img_height - 1 - image_y);
|
||||
size_t canvas_off = fbinfo.framebuffer_width * y;
|
||||
size_t canvas_off = fb->framebuffer_width * y;
|
||||
for (size_t x = xstart; x < xend; x++) {
|
||||
uint32_t img_pixel = *(uint32_t*)(img + image_x * colsize + off);
|
||||
uint32_t i = blend(x, y, img_pixel);
|
||||
uint32_t i = blend(fb, x, y, img_pixel);
|
||||
bg_canvas[canvas_off + x] = i;
|
||||
if (image_x++ == img_width) image_x = 0; // image_x = x % img_width, but modulo is too expensive
|
||||
}
|
||||
@ -450,10 +448,10 @@ __attribute__((always_inline)) static inline void genloop(size_t xstart, size_t
|
||||
for (size_t y = ystart; y < yend; y++) {
|
||||
size_t image_y = y - background->y_displacement;
|
||||
const size_t off = img_pitch * (img_height - 1 - image_y);
|
||||
size_t canvas_off = fbinfo.framebuffer_width * y;
|
||||
size_t canvas_off = fb->framebuffer_width * y;
|
||||
if (image_y >= background->y_size) { /* external part */
|
||||
for (size_t x = xstart; x < xend; x++) {
|
||||
uint32_t i = blend(x, y, background->back_colour);
|
||||
uint32_t i = blend(fb, x, y, background->back_colour);
|
||||
bg_canvas[canvas_off + x] = i;
|
||||
}
|
||||
}
|
||||
@ -462,7 +460,7 @@ __attribute__((always_inline)) static inline void genloop(size_t xstart, size_t
|
||||
size_t image_x = (x - background->x_displacement);
|
||||
bool x_external = image_x >= background->x_size;
|
||||
uint32_t img_pixel = *(uint32_t*)(img + image_x * colsize + off);
|
||||
uint32_t i = blend(x, y, x_external ? background->back_colour : img_pixel);
|
||||
uint32_t i = blend(fb, x, y, x_external ? background->back_colour : img_pixel);
|
||||
bg_canvas[canvas_off + x] = i;
|
||||
}
|
||||
}
|
||||
@ -473,15 +471,15 @@ __attribute__((always_inline)) static inline void genloop(size_t xstart, size_t
|
||||
// so you can set x = xstart * ratio, and increment by ratio at each iteration
|
||||
case IMAGE_STRETCHED:
|
||||
for (size_t y = ystart; y < yend; y++) {
|
||||
size_t img_y = (y * img_height) / fbinfo.framebuffer_height; // calculate Y with full precision
|
||||
size_t img_y = (y * img_height) / fb->framebuffer_height; // calculate Y with full precision
|
||||
size_t off = img_pitch * (img_height - 1 - img_y);
|
||||
size_t canvas_off = fbinfo.framebuffer_width * y;
|
||||
size_t canvas_off = fb->framebuffer_width * y;
|
||||
|
||||
size_t ratio = int_to_fixedp6(img_width) / fbinfo.framebuffer_width;
|
||||
size_t ratio = int_to_fixedp6(img_width) / fb->framebuffer_width;
|
||||
fixedp6 img_x = ratio * xstart;
|
||||
for (size_t x = xstart; x < xend; x++) {
|
||||
uint32_t img_pixel = *(uint32_t*)(img + fixedp6_to_int(img_x) * colsize + off);
|
||||
uint32_t i = blend(x, y, img_pixel);
|
||||
uint32_t i = blend(fb, x, y, img_pixel);
|
||||
bg_canvas[canvas_off + x] = i;
|
||||
img_x += ratio;
|
||||
}
|
||||
@ -490,17 +488,17 @@ __attribute__((always_inline)) static inline void genloop(size_t xstart, size_t
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t blend_external(size_t x, size_t y, uint32_t orig) { (void)x; (void)y; return orig; }
|
||||
static uint32_t blend_internal(size_t x, size_t y, uint32_t orig) { (void)x; (void)y; return colour_blend(default_bg, orig); }
|
||||
static uint32_t blend_margin(size_t x, size_t y, uint32_t orig) { return blend_gradient_from_box(x, y, orig, default_bg); }
|
||||
static uint32_t blend_external(struct fb_info *fb, size_t x, size_t y, uint32_t orig) { (void)fb; (void)x; (void)y; return orig; }
|
||||
static uint32_t blend_internal(struct fb_info *fb, size_t x, size_t y, uint32_t orig) { (void)fb; (void)x; (void)y; return colour_blend(default_bg, orig); }
|
||||
static uint32_t blend_margin(struct fb_info *fb, size_t x, size_t y, uint32_t orig) { return blend_gradient_from_box(fb, x, y, orig, default_bg); }
|
||||
|
||||
static void loop_external(size_t xstart, size_t xend, size_t ystart, size_t yend) { genloop(xstart, xend, ystart, yend, blend_external); }
|
||||
static void loop_margin(size_t xstart, size_t xend, size_t ystart, size_t yend) { genloop(xstart, xend, ystart, yend, blend_margin); }
|
||||
static void loop_internal(size_t xstart, size_t xend, size_t ystart, size_t yend) { genloop(xstart, xend, ystart, yend, blend_internal); }
|
||||
static void loop_external(struct fb_info *fb, size_t xstart, size_t xend, size_t ystart, size_t yend) { genloop(fb, xstart, xend, ystart, yend, blend_external); }
|
||||
static void loop_margin(struct fb_info *fb, size_t xstart, size_t xend, size_t ystart, size_t yend) { genloop(fb, xstart, xend, ystart, yend, blend_margin); }
|
||||
static void loop_internal(struct fb_info *fb, size_t xstart, size_t xend, size_t ystart, size_t yend) { genloop(fb, xstart, xend, ystart, yend, blend_internal); }
|
||||
|
||||
static void generate_canvas(void) {
|
||||
static void generate_canvas(struct fb_info *fb) {
|
||||
if (background) {
|
||||
bg_canvas_size = fbinfo.framebuffer_width * fbinfo.framebuffer_height * sizeof(uint32_t);
|
||||
bg_canvas_size = fb->framebuffer_width * fb->framebuffer_height * sizeof(uint32_t);
|
||||
bg_canvas = ext_mem_alloc(bg_canvas_size);
|
||||
|
||||
int64_t margin_no_gradient = (int64_t)margin - margin_gradient;
|
||||
@ -509,99 +507,76 @@ static void generate_canvas(void) {
|
||||
margin_no_gradient = 0;
|
||||
}
|
||||
|
||||
size_t scan_stop_x = fbinfo.framebuffer_width - margin_no_gradient;
|
||||
size_t scan_stop_y = fbinfo.framebuffer_height - margin_no_gradient;
|
||||
size_t scan_stop_x = fb->framebuffer_width - margin_no_gradient;
|
||||
size_t scan_stop_y = fb->framebuffer_height - margin_no_gradient;
|
||||
|
||||
loop_external(0, fbinfo.framebuffer_width, 0, margin_no_gradient);
|
||||
loop_external(0, fbinfo.framebuffer_width, scan_stop_y, fbinfo.framebuffer_height);
|
||||
loop_external(0, margin_no_gradient, margin_no_gradient, scan_stop_y);
|
||||
loop_external(scan_stop_x, fbinfo.framebuffer_width, margin_no_gradient, scan_stop_y);
|
||||
loop_external(fb, 0, fb->framebuffer_width, 0, margin_no_gradient);
|
||||
loop_external(fb, 0, fb->framebuffer_width, scan_stop_y, fb->framebuffer_height);
|
||||
loop_external(fb, 0, margin_no_gradient, margin_no_gradient, scan_stop_y);
|
||||
loop_external(fb, scan_stop_x, fb->framebuffer_width, margin_no_gradient, scan_stop_y);
|
||||
|
||||
size_t gradient_stop_x = fbinfo.framebuffer_width - margin;
|
||||
size_t gradient_stop_y = fbinfo.framebuffer_height - margin;
|
||||
size_t gradient_stop_x = fb->framebuffer_width - margin;
|
||||
size_t gradient_stop_y = fb->framebuffer_height - margin;
|
||||
|
||||
if (margin_gradient) {
|
||||
loop_margin(margin_no_gradient, scan_stop_x, margin_no_gradient, margin);
|
||||
loop_margin(margin_no_gradient, scan_stop_x, gradient_stop_y, scan_stop_y);
|
||||
loop_margin(margin_no_gradient, margin, margin, gradient_stop_y);
|
||||
loop_margin(gradient_stop_x, scan_stop_x, margin, gradient_stop_y);
|
||||
loop_margin(fb, margin_no_gradient, scan_stop_x, margin_no_gradient, margin);
|
||||
loop_margin(fb, margin_no_gradient, scan_stop_x, gradient_stop_y, scan_stop_y);
|
||||
loop_margin(fb, margin_no_gradient, margin, margin, gradient_stop_y);
|
||||
loop_margin(fb, gradient_stop_x, scan_stop_x, margin, gradient_stop_y);
|
||||
}
|
||||
|
||||
loop_internal(margin, gradient_stop_x, margin, gradient_stop_y);
|
||||
loop_internal(fb, margin, gradient_stop_x, margin, gradient_stop_y);
|
||||
} else {
|
||||
bg_canvas = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static bool last_serial = false;
|
||||
static char *last_config = NULL;
|
||||
bool gterm_init(struct fb_info **_fbs, size_t *_fbs_count,
|
||||
char *config, size_t width, size_t height) {
|
||||
static struct fb_info *fbs;
|
||||
static size_t fbs_count;
|
||||
|
||||
static bool prev_valid = false;
|
||||
static char *prev_config;
|
||||
static size_t prev_width, prev_height;
|
||||
|
||||
if (prev_valid && config == prev_config && width == prev_width && height == prev_height) {
|
||||
*_fbs = fbs;
|
||||
*_fbs_count = fbs_count;
|
||||
reset_term();
|
||||
return true;
|
||||
}
|
||||
|
||||
prev_valid = false;
|
||||
|
||||
bool gterm_init(char *config, size_t width, size_t height) {
|
||||
if (quiet) {
|
||||
if (term != NULL) {
|
||||
term->deinit(term, pmm_free);
|
||||
term = NULL;
|
||||
}
|
||||
term_notready();
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined (UEFI)
|
||||
if (serial || COM_OUTPUT) {
|
||||
if (term != NULL) {
|
||||
term->deinit(term, pmm_free);
|
||||
term = NULL;
|
||||
}
|
||||
term_fallback();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (term != NULL
|
||||
&& term_backend == GTERM
|
||||
&& fbinfo.default_res == true
|
||||
&& width == 0
|
||||
&& height == 0
|
||||
&& fbinfo.framebuffer_bpp == 32
|
||||
&& serial == last_serial
|
||||
&& config == last_config) {
|
||||
term->clear(term, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (term != NULL
|
||||
&& term_backend == GTERM
|
||||
&& fbinfo.framebuffer_width == width
|
||||
&& fbinfo.framebuffer_height == height
|
||||
&& fbinfo.framebuffer_bpp == 32
|
||||
&& serial == last_serial
|
||||
&& config == last_config) {
|
||||
term->clear(term, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (term != NULL) {
|
||||
term->deinit(term, pmm_free);
|
||||
term = NULL;
|
||||
}
|
||||
term_notready();
|
||||
|
||||
// We force bpp to 32
|
||||
if (!fb_init(&fbinfo, width, height, 32)) {
|
||||
return false;
|
||||
fb_init(&fbs, &fbs_count, width, height, 32);
|
||||
|
||||
if (_fbs != NULL) {
|
||||
*_fbs = fbs;
|
||||
}
|
||||
if (_fbs_count != NULL) {
|
||||
*_fbs_count = fbs_count;
|
||||
}
|
||||
|
||||
// Ensure this is xRGB8888, we only support that for the menu
|
||||
if (fbinfo.red_mask_size != 8
|
||||
|| fbinfo.red_mask_shift != 16
|
||||
|| fbinfo.green_mask_size != 8
|
||||
|| fbinfo.green_mask_shift != 8
|
||||
|| fbinfo.blue_mask_size != 8
|
||||
|| fbinfo.blue_mask_shift != 0) {
|
||||
if (fbs_count == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
last_serial = serial;
|
||||
last_config = config;
|
||||
|
||||
// default scheme
|
||||
margin = 64;
|
||||
margin_gradient = 4;
|
||||
@ -702,20 +677,6 @@ bool gterm_init(char *config, size_t width, size_t height) {
|
||||
margin_gradient = strtoui(theme_margin_gradient, NULL, 10);
|
||||
}
|
||||
|
||||
if (background != NULL) {
|
||||
char *background_layout = config_get_value(config, 0, "TERM_WALLPAPER_STYLE");
|
||||
if (background_layout != NULL && strcmp(background_layout, "centered") == 0) {
|
||||
char *background_colour = config_get_value(config, 0, "TERM_BACKDROP");
|
||||
if (background_colour == NULL)
|
||||
background_colour = "0";
|
||||
uint32_t bg_col = strtoui(background_colour, NULL, 16);
|
||||
image_make_centered(background, fbinfo.framebuffer_width, fbinfo.framebuffer_height, bg_col);
|
||||
} else if (background_layout != NULL && strcmp(background_layout, "tiled") == 0) {
|
||||
} else {
|
||||
image_make_stretched(background, fbinfo.framebuffer_width, fbinfo.framebuffer_height);
|
||||
}
|
||||
}
|
||||
|
||||
size_t font_width = 8;
|
||||
size_t font_height = 16;
|
||||
size_t font_size = (font_width * font_height * FBTERM_FONT_GLYPHS) / 8;
|
||||
@ -775,38 +736,105 @@ no_load_font:;
|
||||
}
|
||||
}
|
||||
|
||||
generate_canvas();
|
||||
terms_i = 0;
|
||||
terms = ext_mem_alloc(fbs_count * sizeof(void *));
|
||||
|
||||
term = fbterm_init(ext_mem_alloc,
|
||||
(void *)(uintptr_t)fbinfo.framebuffer_addr,
|
||||
fbinfo.framebuffer_width, fbinfo.framebuffer_height, fbinfo.framebuffer_pitch,
|
||||
bg_canvas,
|
||||
ansi_colours, ansi_bright_colours,
|
||||
&default_bg, &default_fg,
|
||||
font, font_width, font_height, font_spacing,
|
||||
font_scale_x, font_scale_y,
|
||||
margin);
|
||||
for (size_t i = 0; i < fbs_count; i++) {
|
||||
struct fb_info *fb = &fbs[i];
|
||||
|
||||
pmm_free(font, FONT_MAX);
|
||||
if (bg_canvas != NULL) {
|
||||
pmm_free(bg_canvas, bg_canvas_size);
|
||||
// Ensure this is xRGB8888, we only support that for the menu
|
||||
if (fb->red_mask_size != 8
|
||||
|| fb->red_mask_shift != 16
|
||||
|| fb->green_mask_size != 8
|
||||
|| fb->green_mask_shift != 8
|
||||
|| fb->blue_mask_size != 8
|
||||
|| fb->blue_mask_shift != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (background != NULL) {
|
||||
char *background_layout = config_get_value(config, 0, "TERM_WALLPAPER_STYLE");
|
||||
if (background_layout != NULL && strcmp(background_layout, "centered") == 0) {
|
||||
char *background_colour = config_get_value(config, 0, "TERM_BACKDROP");
|
||||
if (background_colour == NULL)
|
||||
background_colour = "0";
|
||||
uint32_t bg_col = strtoui(background_colour, NULL, 16);
|
||||
image_make_centered(background, fb->framebuffer_width, fb->framebuffer_height, bg_col);
|
||||
} else if (background_layout != NULL && strcmp(background_layout, "tiled") == 0) {
|
||||
} else {
|
||||
image_make_stretched(background, fb->framebuffer_width, fb->framebuffer_height);
|
||||
}
|
||||
}
|
||||
|
||||
generate_canvas(fb);
|
||||
|
||||
terms[terms_i] = fbterm_init(ext_mem_alloc,
|
||||
(void *)(uintptr_t)fb->framebuffer_addr,
|
||||
fb->framebuffer_width, fb->framebuffer_height, fb->framebuffer_pitch,
|
||||
bg_canvas,
|
||||
ansi_colours, ansi_bright_colours,
|
||||
&default_bg, &default_fg,
|
||||
font, font_width, font_height, font_spacing,
|
||||
font_scale_x, font_scale_y,
|
||||
margin);
|
||||
|
||||
if (terms[terms_i] != NULL) {
|
||||
terms_i++;
|
||||
}
|
||||
|
||||
if (bg_canvas != NULL) {
|
||||
pmm_free(bg_canvas, bg_canvas_size);
|
||||
}
|
||||
}
|
||||
|
||||
if (term == NULL) {
|
||||
pmm_free(font, FONT_MAX);
|
||||
|
||||
if (terms_i == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (serial) {
|
||||
term->cols = term->cols > 80 ? 80 : term->cols;
|
||||
term->rows = term->rows > 24 ? 24 : term->rows;
|
||||
for (size_t i = 0; i < terms_i; i++) {
|
||||
struct term_context *term = terms[i];
|
||||
|
||||
if (serial) {
|
||||
term->cols = term->cols > 80 ? 80 : term->cols;
|
||||
term->rows = term->rows > 24 ? 24 : term->rows;
|
||||
}
|
||||
}
|
||||
|
||||
term->in_bootloader = true;
|
||||
size_t min_cols = (size_t)-1;
|
||||
size_t min_rows = (size_t)-1;
|
||||
|
||||
term_context_reinit(term);
|
||||
term->full_refresh(term);
|
||||
for (size_t i = 0; i < terms_i; i++) {
|
||||
struct term_context *term = terms[i];
|
||||
|
||||
if (term->cols < min_cols) {
|
||||
min_cols = term->cols;
|
||||
}
|
||||
|
||||
if (term->rows < min_rows) {
|
||||
min_rows = term->rows;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < terms_i; i++) {
|
||||
struct term_context *term = terms[i];
|
||||
|
||||
term->cols = min_cols;
|
||||
term->rows = min_rows;
|
||||
|
||||
term->in_bootloader = true;
|
||||
|
||||
term_context_reinit(term);
|
||||
term->full_refresh(term);
|
||||
}
|
||||
|
||||
term_backend = GTERM;
|
||||
|
||||
prev_config = config;
|
||||
prev_height = height;
|
||||
prev_width = width;
|
||||
prev_valid = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -5,8 +5,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <lib/fb.h>
|
||||
|
||||
extern struct fb_info fbinfo;
|
||||
|
||||
bool gterm_init(char *config, size_t width, size_t height);
|
||||
bool gterm_init(struct fb_info **ret, size_t *_fbs_count,
|
||||
char *config, size_t width, size_t height);
|
||||
|
||||
#endif
|
||||
|
@ -222,9 +222,7 @@ out:
|
||||
#if defined (BIOS)
|
||||
if (stage3_loaded) {
|
||||
#endif
|
||||
if (term != NULL) {
|
||||
term_write(term, print_buf, print_buf_i);
|
||||
}
|
||||
FOR_TERM(term_write(TERM, print_buf, print_buf_i));
|
||||
#if defined (BIOS)
|
||||
} else {
|
||||
s2_print(print_buf, print_buf_i);
|
||||
|
@ -352,34 +352,34 @@ again:
|
||||
|
||||
static void reprint_string(int x, int y, const char *s) {
|
||||
size_t orig_x, orig_y;
|
||||
term->disable_cursor(term);
|
||||
term->get_cursor_pos(term, &orig_x, &orig_y);
|
||||
FOR_TERM(TERM->disable_cursor(TERM));
|
||||
terms[0]->get_cursor_pos(terms[0], &orig_x, &orig_y);
|
||||
set_cursor_pos_helper(x, y);
|
||||
print("%s", s);
|
||||
set_cursor_pos_helper(orig_x, orig_y);
|
||||
term->enable_cursor(term);
|
||||
FOR_TERM(TERM->enable_cursor(TERM));
|
||||
}
|
||||
|
||||
static void cursor_back(void) {
|
||||
size_t x, y;
|
||||
term->get_cursor_pos(term, &x, &y);
|
||||
terms[0]->get_cursor_pos(terms[0], &x, &y);
|
||||
if (x) {
|
||||
x--;
|
||||
} else if (y) {
|
||||
y--;
|
||||
x = term->cols - 1;
|
||||
x = terms[0]->cols - 1;
|
||||
}
|
||||
set_cursor_pos_helper(x, y);
|
||||
}
|
||||
|
||||
static void cursor_fwd(void) {
|
||||
size_t x, y;
|
||||
term->get_cursor_pos(term, &x, &y);
|
||||
if (x < term->cols - 1) {
|
||||
terms[0]->get_cursor_pos(terms[0], &x, &y);
|
||||
if (x < terms[0]->cols - 1) {
|
||||
x++;
|
||||
} else {
|
||||
x = 0;
|
||||
if (y < term->rows - 1) {
|
||||
if (y < terms[0]->rows - 1) {
|
||||
y++;
|
||||
}
|
||||
}
|
||||
@ -387,20 +387,20 @@ static void cursor_fwd(void) {
|
||||
}
|
||||
|
||||
void readline(const char *orig_str, char *buf, size_t limit) {
|
||||
bool prev_autoflush = term->autoflush;
|
||||
term->autoflush = false;
|
||||
bool prev_autoflush = terms[0]->autoflush;
|
||||
FOR_TERM(TERM->autoflush = false);
|
||||
|
||||
size_t orig_str_len = strlen(orig_str);
|
||||
memmove(buf, orig_str, orig_str_len);
|
||||
buf[orig_str_len] = 0;
|
||||
|
||||
size_t orig_x, orig_y;
|
||||
term->get_cursor_pos(term, &orig_x, &orig_y);
|
||||
terms[0]->get_cursor_pos(terms[0], &orig_x, &orig_y);
|
||||
|
||||
print("%s", orig_str);
|
||||
|
||||
for (size_t i = orig_str_len; ; ) {
|
||||
term->double_buffer_flush(term);
|
||||
FOR_TERM(TERM->double_buffer_flush(TERM));
|
||||
int c = getchar();
|
||||
switch (c) {
|
||||
case GETCHAR_CURSOR_LEFT:
|
||||
@ -460,11 +460,11 @@ void readline(const char *orig_str, char *buf, size_t limit) {
|
||||
buf[i] = c;
|
||||
i++;
|
||||
size_t prev_x, prev_y;
|
||||
term->get_cursor_pos(term, &prev_x, &prev_y);
|
||||
terms[0]->get_cursor_pos(terms[0], &prev_x, &prev_y);
|
||||
cursor_fwd();
|
||||
reprint_string(orig_x, orig_y, buf);
|
||||
// If cursor has wrapped around, move the line start position up one row
|
||||
if (prev_x == term->cols - 1 && prev_y == term->rows - 1) {
|
||||
if (prev_x == terms[0]->cols - 1 && prev_y == terms[0]->rows - 1) {
|
||||
orig_y--;
|
||||
print("\e[J"); // Clear the bottom line
|
||||
}
|
||||
@ -474,6 +474,6 @@ void readline(const char *orig_str, char *buf, size_t limit) {
|
||||
}
|
||||
|
||||
out:
|
||||
term->double_buffer_flush(term);
|
||||
term->autoflush = prev_autoflush;
|
||||
FOR_TERM(TERM->double_buffer_flush(TERM));
|
||||
FOR_TERM(TERM->autoflush = prev_autoflush);
|
||||
}
|
||||
|
@ -8,95 +8,28 @@
|
||||
#include <drivers/vga_textmode.h>
|
||||
#include <term/backends/framebuffer.h>
|
||||
|
||||
#if defined (BIOS)
|
||||
int current_video_mode = -1;
|
||||
#endif
|
||||
|
||||
struct term_context **terms = NULL;
|
||||
size_t terms_i = 0;
|
||||
|
||||
int term_backend = _NOT_READY;
|
||||
|
||||
struct term_context *term;
|
||||
void term_notready(void) {
|
||||
for (size_t i = 0; i < terms_i; i++) {
|
||||
struct term_context *term = terms[i];
|
||||
|
||||
static struct term_context term_local_struct;
|
||||
|
||||
// --- notready ---
|
||||
|
||||
static void notready_raw_putchar(struct term_context *ctx, uint8_t c) {
|
||||
(void)ctx;
|
||||
(void)c;
|
||||
}
|
||||
static void notready_clear(struct term_context *ctx, bool move) {
|
||||
(void)ctx;
|
||||
(void)move;
|
||||
}
|
||||
static void notready_void(struct term_context *ctx) {
|
||||
(void)ctx;
|
||||
}
|
||||
static void notready_set_cursor_pos(struct term_context *ctx, size_t x, size_t y) {
|
||||
(void)ctx;
|
||||
(void)x; (void)y;
|
||||
}
|
||||
static void notready_get_cursor_pos(struct term_context *ctx, size_t *x, size_t *y) {
|
||||
(void)ctx;
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
}
|
||||
static void notready_size_t(struct term_context *ctx, size_t n) {
|
||||
(void)ctx;
|
||||
(void)n;
|
||||
}
|
||||
static bool notready_disable(struct term_context *ctx) {
|
||||
(void)ctx;
|
||||
return false;
|
||||
}
|
||||
static void notready_move_character(struct term_context *ctx, size_t a, size_t b, size_t c, size_t d) {
|
||||
(void)ctx;
|
||||
(void)a; (void)b; (void)c; (void)d;
|
||||
}
|
||||
static void notready_uint32_t(struct term_context *ctx, uint32_t n) {
|
||||
(void)ctx;
|
||||
(void)n;
|
||||
}
|
||||
static void notready_deinit(struct term_context *ctx, void (*_free)(void *, size_t)) {
|
||||
(void)ctx;
|
||||
(void)_free;
|
||||
}
|
||||
|
||||
static void term_notready(void) {
|
||||
if (term != NULL) {
|
||||
term->deinit(term, pmm_free);
|
||||
term = NULL;
|
||||
}
|
||||
|
||||
term = &term_local_struct;
|
||||
pmm_free(terms, terms_i * sizeof(void *));
|
||||
|
||||
term->raw_putchar = notready_raw_putchar;
|
||||
term->clear = notready_clear;
|
||||
term->enable_cursor = notready_void;
|
||||
term->disable_cursor = notready_disable;
|
||||
term->set_cursor_pos = notready_set_cursor_pos;
|
||||
term->get_cursor_pos = notready_get_cursor_pos;
|
||||
term->set_text_fg = notready_size_t;
|
||||
term->set_text_bg = notready_size_t;
|
||||
term->set_text_fg_bright = notready_size_t;
|
||||
term->set_text_bg_bright = notready_size_t;
|
||||
term->set_text_fg_rgb = notready_uint32_t;
|
||||
term->set_text_bg_rgb = notready_uint32_t;
|
||||
term->set_text_fg_default = notready_void;
|
||||
term->set_text_bg_default = notready_void;
|
||||
term->move_character = notready_move_character;
|
||||
term->scroll = notready_void;
|
||||
term->revscroll = notready_void;
|
||||
term->swap_palette = notready_void;
|
||||
term->save_state = notready_void;
|
||||
term->restore_state = notready_void;
|
||||
term->double_buffer_flush = notready_void;
|
||||
term->full_refresh = notready_void;
|
||||
term->deinit = notready_deinit;
|
||||
|
||||
term->cols = 80;
|
||||
term->rows = 24;
|
||||
terms_i = 0;
|
||||
terms = NULL;
|
||||
|
||||
term_backend = _NOT_READY;
|
||||
term_context_reinit(term);
|
||||
|
||||
term->in_bootloader = true;
|
||||
}
|
||||
|
||||
// --- fallback ---
|
||||
@ -162,7 +95,7 @@ static void fallback_scroll(struct term_context *ctx) {
|
||||
(void)ctx;
|
||||
size_t x, y;
|
||||
fallback_get_cursor_pos(NULL, &x, &y);
|
||||
fallback_set_cursor_pos(NULL, term->cols - 1, term->rows - 1);
|
||||
fallback_set_cursor_pos(NULL, ctx->cols - 1, ctx->rows - 1);
|
||||
fallback_raw_putchar(NULL, ' ');
|
||||
fallback_set_cursor_pos(NULL, x, y);
|
||||
}
|
||||
@ -173,7 +106,7 @@ static size_t cursor_x = 0, cursor_y = 0;
|
||||
|
||||
static void fallback_scroll(struct term_context *ctx) {
|
||||
(void)ctx;
|
||||
gST->ConOut->SetCursorPosition(gST->ConOut, term->cols - 1, term->rows - 1);
|
||||
gST->ConOut->SetCursorPosition(gST->ConOut, ctx->cols - 1, ctx->rows - 1);
|
||||
CHAR16 string[2];
|
||||
string[0] = ' ';
|
||||
string[1] = 0;
|
||||
@ -182,7 +115,7 @@ static void fallback_scroll(struct term_context *ctx) {
|
||||
}
|
||||
|
||||
static void fallback_raw_putchar(struct term_context *ctx, uint8_t c) {
|
||||
if (!ctx->scroll_enabled && cursor_x == term->cols - 1 && cursor_y == term->rows - 1) {
|
||||
if (!ctx->scroll_enabled && cursor_x == ctx->cols - 1 && cursor_y == ctx->rows - 1) {
|
||||
return;
|
||||
}
|
||||
gST->ConOut->EnableCursor(gST->ConOut, true);
|
||||
@ -190,9 +123,9 @@ static void fallback_raw_putchar(struct term_context *ctx, uint8_t c) {
|
||||
string[0] = c;
|
||||
string[1] = 0;
|
||||
gST->ConOut->OutputString(gST->ConOut, string);
|
||||
if (++cursor_x >= term->cols) {
|
||||
if (++cursor_x >= ctx->cols) {
|
||||
cursor_x = 0;
|
||||
if (++cursor_y >= term->rows) {
|
||||
if (++cursor_y >= ctx->rows) {
|
||||
cursor_y--;
|
||||
}
|
||||
}
|
||||
@ -210,7 +143,7 @@ static void fallback_clear(struct term_context *ctx, bool move) {
|
||||
|
||||
static void fallback_set_cursor_pos(struct term_context *ctx, size_t x, size_t y) {
|
||||
(void)ctx;
|
||||
if (x >= term->cols || y >= term->rows) {
|
||||
if (x >= ctx->cols || y >= ctx->rows) {
|
||||
return;
|
||||
}
|
||||
gST->ConOut->SetCursorPosition(gST->ConOut, x, y);
|
||||
@ -225,13 +158,45 @@ static void fallback_get_cursor_pos(struct term_context *ctx, size_t *x, size_t
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool dummy_handle(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void term_fallback(void) {
|
||||
term_notready();
|
||||
|
||||
#if defined (UEFI)
|
||||
if (!efi_boot_services_exited) {
|
||||
#endif
|
||||
|
||||
terms = ext_mem_alloc(sizeof(void *));
|
||||
terms_i = 1;
|
||||
|
||||
terms[0] = ext_mem_alloc(sizeof(struct term_context));
|
||||
|
||||
struct term_context *term = terms[0];
|
||||
|
||||
fallback_clear(NULL, true);
|
||||
|
||||
term->enable_cursor = (void *)dummy_handle;
|
||||
term->disable_cursor = (void *)dummy_handle;
|
||||
term->set_text_fg = (void *)dummy_handle;
|
||||
term->set_text_bg = (void *)dummy_handle;
|
||||
term->set_text_fg_bright = (void *)dummy_handle;
|
||||
term->set_text_bg_bright = (void *)dummy_handle;
|
||||
term->set_text_fg_rgb = (void *)dummy_handle;
|
||||
term->set_text_bg_rgb = (void *)dummy_handle;
|
||||
term->set_text_fg_default = (void *)dummy_handle;
|
||||
term->set_text_bg_default = (void *)dummy_handle;
|
||||
term->move_character = (void *)dummy_handle;
|
||||
term->revscroll = (void *)dummy_handle;
|
||||
term->swap_palette = (void *)dummy_handle;
|
||||
term->save_state = (void *)dummy_handle;
|
||||
term->restore_state = (void *)dummy_handle;
|
||||
term->double_buffer_flush = (void *)dummy_handle;
|
||||
term->full_refresh = (void *)dummy_handle;
|
||||
term->deinit = (void *)dummy_handle;
|
||||
|
||||
term->raw_putchar = fallback_raw_putchar;
|
||||
term->clear = fallback_clear;
|
||||
term->set_cursor_pos = fallback_set_cursor_pos;
|
||||
@ -264,7 +229,7 @@ extern void set_cursor_pos_helper(size_t x, size_t y);
|
||||
static uint8_t xfer_buf[TERM_XFER_CHUNK];
|
||||
#endif
|
||||
|
||||
static uint64_t context_size(void) {
|
||||
static uint64_t context_size(struct term_context *term) {
|
||||
switch (term_backend) {
|
||||
#if defined (BIOS)
|
||||
case TEXTMODE:
|
||||
@ -285,7 +250,7 @@ static uint64_t context_size(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static void context_save(uint64_t buf) {
|
||||
static void context_save(struct term_context *term, uint64_t buf) {
|
||||
switch (term_backend) {
|
||||
#if defined (BIOS)
|
||||
case TEXTMODE: {
|
||||
@ -320,7 +285,7 @@ static void context_save(uint64_t buf) {
|
||||
}
|
||||
}
|
||||
|
||||
static void context_restore(uint64_t buf) {
|
||||
static void context_restore(struct term_context *term, uint64_t buf) {
|
||||
switch (term_backend) {
|
||||
#if defined (BIOS)
|
||||
case TEXTMODE: {
|
||||
@ -355,19 +320,19 @@ static void context_restore(uint64_t buf) {
|
||||
}
|
||||
}
|
||||
|
||||
void _term_write(uint64_t buf, uint64_t count) {
|
||||
void _term_write(struct term_context *term, uint64_t buf, uint64_t count) {
|
||||
switch (count) {
|
||||
case TERM_CTX_SIZE: {
|
||||
uint64_t ret = context_size();
|
||||
uint64_t ret = context_size(term);
|
||||
memcpy32to64(buf, (uint64_t)(uintptr_t)&ret, sizeof(uint64_t));
|
||||
return;
|
||||
}
|
||||
case TERM_CTX_SAVE: {
|
||||
context_save(buf);
|
||||
context_save(term, buf);
|
||||
return;
|
||||
}
|
||||
case TERM_CTX_RESTORE: {
|
||||
context_restore(buf);
|
||||
context_restore(term, buf);
|
||||
return;
|
||||
}
|
||||
case TERM_FULL_REFRESH: {
|
||||
|
@ -13,28 +13,46 @@ enum {
|
||||
FALLBACK
|
||||
};
|
||||
|
||||
#if defined (BIOS)
|
||||
extern int current_video_mode;
|
||||
extern int term_backend;
|
||||
#endif
|
||||
|
||||
extern struct term_context *term;
|
||||
extern struct term_context **terms;
|
||||
extern size_t terms_i;
|
||||
|
||||
extern int term_backend;
|
||||
|
||||
#define TERM_CTX_SIZE ((uint64_t)(-1))
|
||||
#define TERM_CTX_SAVE ((uint64_t)(-2))
|
||||
#define TERM_CTX_RESTORE ((uint64_t)(-3))
|
||||
#define TERM_FULL_REFRESH ((uint64_t)(-4))
|
||||
|
||||
#define FOR_TERM(...) do { \
|
||||
for (size_t FOR_TERM_i = 0; FOR_TERM_i < terms_i; FOR_TERM_i++) { \
|
||||
struct term_context *TERM = terms[FOR_TERM_i]; \
|
||||
__VA_ARGS__ \
|
||||
; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
inline void reset_term(void) {
|
||||
term->autoflush = true;
|
||||
term->enable_cursor(term);
|
||||
print("\e[2J\e[H");
|
||||
term->double_buffer_flush(term);
|
||||
for (size_t i = 0; i < terms_i; i++) {
|
||||
struct term_context *term = terms[i];
|
||||
|
||||
print("\e[2J\e[H");
|
||||
term_context_reinit(term);
|
||||
term->in_bootloader = true;
|
||||
term->enable_cursor(term);
|
||||
term->double_buffer_flush(term);
|
||||
}
|
||||
}
|
||||
|
||||
inline void set_cursor_pos_helper(size_t x, size_t y) {
|
||||
print("\e[%u;%uH", (int)y + 1, (int)x + 1);
|
||||
}
|
||||
|
||||
void term_notready(void);
|
||||
void term_fallback(void);
|
||||
void _term_write(uint64_t buf, uint64_t count);
|
||||
void _term_write(struct term_context *term, uint64_t buf, uint64_t count);
|
||||
|
||||
#endif
|
||||
|
@ -43,7 +43,8 @@ SECTIONS
|
||||
term_write = .;
|
||||
term_backend = .;
|
||||
term_fallback = .;
|
||||
term = .;
|
||||
terms = .;
|
||||
terms_i = .;
|
||||
stage3_addr = .;
|
||||
#else
|
||||
#ifdef LINKER_NOS2MAP
|
||||
|
126
common/menu.c
126
common/menu.c
@ -168,17 +168,17 @@ static void putchar_tokencol(int type, char c) {
|
||||
static bool editor_no_term_reset = false;
|
||||
|
||||
char *config_entry_editor(const char *title, const char *orig_entry) {
|
||||
term->autoflush = false;
|
||||
FOR_TERM(TERM->autoflush = false);
|
||||
|
||||
term->enable_cursor(term);
|
||||
FOR_TERM(TERM->enable_cursor(TERM));
|
||||
|
||||
print("\e[2J\e[H");
|
||||
|
||||
size_t cursor_offset = 0;
|
||||
size_t entry_size = strlen(orig_entry);
|
||||
size_t _window_size = term->rows - 8;
|
||||
size_t _window_size = terms[0]->rows - 8;
|
||||
size_t window_offset = 0;
|
||||
size_t line_size = term->cols - 2;
|
||||
size_t line_size = terms[0]->cols - 2;
|
||||
|
||||
bool display_overflow_error = false;
|
||||
|
||||
@ -214,12 +214,12 @@ refresh:
|
||||
invalid_syntax = false;
|
||||
|
||||
print("\e[2J\e[H");
|
||||
term->disable_cursor(term);
|
||||
FOR_TERM(TERM->disable_cursor(TERM));
|
||||
{
|
||||
size_t x, y;
|
||||
print("\n");
|
||||
term->get_cursor_pos(term, &x, &y);
|
||||
set_cursor_pos_helper(term->cols / 2 - DIV_ROUNDUP(strlen(menu_branding), 2), y);
|
||||
terms[0]->get_cursor_pos(terms[0], &x, &y);
|
||||
set_cursor_pos_helper(terms[0]->cols / 2 - DIV_ROUNDUP(strlen(menu_branding), 2), y);
|
||||
print("\e[3%sm%s\e[37m", menu_branding_colour, menu_branding);
|
||||
print("\n\n");
|
||||
}
|
||||
@ -227,7 +227,7 @@ refresh:
|
||||
print(" \e[32mESC\e[0m Discard and Exit \e[32mF10\e[0m Boot\n\n");
|
||||
|
||||
print(serial ? "/" : "\xda");
|
||||
for (size_t i = 0; i < term->cols - 2; i++) {
|
||||
for (size_t i = 0; i < terms[0]->cols - 2; i++) {
|
||||
switch (i) {
|
||||
case 1: case 2: case 3:
|
||||
if (window_offset > 0) {
|
||||
@ -237,7 +237,7 @@ refresh:
|
||||
// FALLTHRU
|
||||
default: {
|
||||
size_t title_length = strlen(title);
|
||||
if (i == (term->cols / 2) - DIV_ROUNDUP(title_length, 2) - 1) {
|
||||
if (i == (terms[0]->cols / 2) - DIV_ROUNDUP(title_length, 2) - 1) {
|
||||
print("%s", title);
|
||||
i += title_length - 1;
|
||||
} else {
|
||||
@ -248,7 +248,7 @@ refresh:
|
||||
}
|
||||
size_t tmpx, tmpy;
|
||||
|
||||
term->get_cursor_pos(term, &tmpx, &tmpy);
|
||||
terms[0]->get_cursor_pos(terms[0], &tmpx, &tmpy);
|
||||
print(serial ? "\\" : "\xbf");
|
||||
set_cursor_pos_helper(0, tmpy + 1);
|
||||
print(serial ? "|" : "\xb3");
|
||||
@ -264,20 +264,20 @@ refresh:
|
||||
&& current_line < window_offset + window_size
|
||||
&& current_line >= window_offset) {
|
||||
size_t x, y;
|
||||
term->get_cursor_pos(term, &x, &y);
|
||||
terms[0]->get_cursor_pos(terms[0], &x, &y);
|
||||
if (i == cursor_offset) {
|
||||
cursor_x = x;
|
||||
cursor_y = y;
|
||||
printed_cursor = true;
|
||||
}
|
||||
set_cursor_pos_helper(term->cols - 1, y);
|
||||
set_cursor_pos_helper(terms[0]->cols - 1, y);
|
||||
if (current_line == window_offset + window_size - 1) {
|
||||
term->get_cursor_pos(term, &tmpx, &tmpy);
|
||||
terms[0]->get_cursor_pos(terms[0], &tmpx, &tmpy);
|
||||
print(serial ? "|" : "\xb3");
|
||||
set_cursor_pos_helper(0, tmpy + 1);
|
||||
print(serial ? "\\" : "\xc0");
|
||||
} else {
|
||||
term->get_cursor_pos(term, &tmpx, &tmpy);
|
||||
terms[0]->get_cursor_pos(terms[0], &tmpx, &tmpy);
|
||||
print(serial ? "|" : "\xb3");
|
||||
set_cursor_pos_helper(0, tmpy + 1);
|
||||
print(serial ? "|" : "\xb3");
|
||||
@ -295,7 +295,7 @@ refresh:
|
||||
if (current_line < window_offset + window_size
|
||||
&& current_line >= window_offset) {
|
||||
if (i == cursor_offset) {
|
||||
term->get_cursor_pos(term, &cursor_x, &cursor_y);
|
||||
terms[0]->get_cursor_pos(terms[0], &cursor_x, &cursor_y);
|
||||
printed_cursor = true;
|
||||
}
|
||||
if (syntax_highlighting_enabled) {
|
||||
@ -305,8 +305,8 @@ refresh:
|
||||
}
|
||||
printed_early = true;
|
||||
size_t x, y;
|
||||
term->get_cursor_pos(term, &x, &y);
|
||||
if (y == term->rows - 3) {
|
||||
terms[0]->get_cursor_pos(terms[0], &x, &y);
|
||||
if (y == terms[0]->rows - 3) {
|
||||
print(serial ? ">" : "\x1a");
|
||||
set_cursor_pos_helper(0, y + 1);
|
||||
print(serial ? "\\" : "\xc0");
|
||||
@ -323,7 +323,7 @@ refresh:
|
||||
&& current_line < window_offset + window_size
|
||||
&& current_line >= window_offset
|
||||
&& !printed_cursor) {
|
||||
term->get_cursor_pos(term, &cursor_x, &cursor_y);
|
||||
terms[0]->get_cursor_pos(terms[0], &cursor_x, &cursor_y);
|
||||
printed_cursor = true;
|
||||
}
|
||||
|
||||
@ -370,35 +370,35 @@ refresh:
|
||||
// syntax error alert
|
||||
if (validation_enabled) {
|
||||
size_t x, y;
|
||||
term->get_cursor_pos(term, &x, &y);
|
||||
set_cursor_pos_helper(0, term->rows - 1);
|
||||
term->scroll_enabled = false;
|
||||
terms[0]->get_cursor_pos(terms[0], &x, &y);
|
||||
set_cursor_pos_helper(0, terms[0]->rows - 1);
|
||||
FOR_TERM(TERM->scroll_enabled = false);
|
||||
if (invalid_syntax) {
|
||||
print("\e[31mConfiguration is INVALID.\e[0m");
|
||||
} else {
|
||||
print("\e[32mConfiguration is valid.\e[0m");
|
||||
}
|
||||
term->scroll_enabled = true;
|
||||
FOR_TERM(TERM->scroll_enabled = true);
|
||||
set_cursor_pos_helper(x, y);
|
||||
}
|
||||
|
||||
if (current_line - window_offset < window_size) {
|
||||
size_t x, y;
|
||||
for (size_t i = 0; i < (window_size - (current_line - window_offset)) - 1; i++) {
|
||||
term->get_cursor_pos(term, &x, &y);
|
||||
set_cursor_pos_helper(term->cols - 1, y);
|
||||
terms[0]->get_cursor_pos(terms[0], &x, &y);
|
||||
set_cursor_pos_helper(terms[0]->cols - 1, y);
|
||||
print(serial ? "|" : "\xb3");
|
||||
set_cursor_pos_helper(0, y + 1);
|
||||
print(serial ? "|" : "\xb3");
|
||||
}
|
||||
term->get_cursor_pos(term, &x, &y);
|
||||
set_cursor_pos_helper(term->cols - 1, y);
|
||||
terms[0]->get_cursor_pos(terms[0], &x, &y);
|
||||
set_cursor_pos_helper(terms[0]->cols - 1, y);
|
||||
print(serial ? "|" : "\xb3");
|
||||
set_cursor_pos_helper(0, y + 1);
|
||||
print(serial ? "\\" : "\xc0");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < term->cols - 2; i++) {
|
||||
for (size_t i = 0; i < terms[0]->cols - 2; i++) {
|
||||
switch (i) {
|
||||
case 1: case 2: case 3:
|
||||
if (current_line - window_offset >= window_size) {
|
||||
@ -410,22 +410,22 @@ refresh:
|
||||
print(serial ? "-" : "\xc4");
|
||||
}
|
||||
}
|
||||
term->get_cursor_pos(term, &tmpx, &tmpy);
|
||||
terms[0]->get_cursor_pos(terms[0], &tmpx, &tmpy);
|
||||
print(serial ? "/" : "\xd9");
|
||||
set_cursor_pos_helper(0, tmpy + 1);
|
||||
|
||||
if (display_overflow_error) {
|
||||
term->scroll_enabled = false;
|
||||
FOR_TERM(TERM->scroll_enabled = false);
|
||||
print("\e[31mText buffer not big enough, delete something instead.");
|
||||
term->scroll_enabled = true;
|
||||
FOR_TERM(TERM->scroll_enabled = true);
|
||||
display_overflow_error = false;
|
||||
}
|
||||
|
||||
// Hack to redraw the cursor
|
||||
set_cursor_pos_helper(cursor_x, cursor_y);
|
||||
term->enable_cursor(term);
|
||||
FOR_TERM(TERM->enable_cursor(TERM));
|
||||
|
||||
term->double_buffer_flush(term);
|
||||
FOR_TERM(TERM->double_buffer_flush(TERM));
|
||||
|
||||
int c = getchar();
|
||||
size_t buffer_len = strlen(buffer);
|
||||
@ -584,7 +584,7 @@ static void menu_init_term(void) {
|
||||
if (menu_resolution != NULL)
|
||||
parse_resolution(&req_width, &req_height, &req_bpp, menu_resolution);
|
||||
|
||||
if (!quiet && !gterm_init(NULL, req_width, req_height)) {
|
||||
if (!quiet && !gterm_init(NULL, NULL, NULL, req_width, req_height)) {
|
||||
#if defined (BIOS)
|
||||
vga_textmode_init(true);
|
||||
#elif defined (UEFI)
|
||||
@ -721,23 +721,23 @@ noreturn void _menu(bool first_run) {
|
||||
size_t tree_offset = 0;
|
||||
|
||||
refresh:
|
||||
if (selected_entry >= tree_offset + term->rows - 10) {
|
||||
tree_offset = selected_entry - (term->rows - 11);
|
||||
if (selected_entry >= tree_offset + terms[0]->rows - 10) {
|
||||
tree_offset = selected_entry - (terms[0]->rows - 11);
|
||||
}
|
||||
if (selected_entry < tree_offset) {
|
||||
tree_offset = selected_entry;
|
||||
}
|
||||
|
||||
term->autoflush = false;
|
||||
FOR_TERM(TERM->autoflush = false);
|
||||
|
||||
term->disable_cursor(term);
|
||||
FOR_TERM(TERM->disable_cursor(TERM));
|
||||
|
||||
print("\e[2J\e[H");
|
||||
{
|
||||
size_t x, y;
|
||||
print("\n");
|
||||
term->get_cursor_pos(term, &x, &y);
|
||||
set_cursor_pos_helper(term->cols / 2 - DIV_ROUNDUP(strlen(menu_branding), 2), y);
|
||||
terms[0]->get_cursor_pos(terms[0], &x, &y);
|
||||
set_cursor_pos_helper(terms[0]->cols / 2 - DIV_ROUNDUP(strlen(menu_branding), 2), y);
|
||||
print("\e[3%sm%s\e[37m", menu_branding_colour, menu_branding);
|
||||
print("\n\n\n\n");
|
||||
}
|
||||
@ -746,14 +746,14 @@ refresh:
|
||||
if (quiet) {
|
||||
quiet = false;
|
||||
menu_init_term();
|
||||
term->autoflush = false;
|
||||
term->disable_cursor(term);
|
||||
FOR_TERM(TERM->autoflush = false);
|
||||
FOR_TERM(TERM->disable_cursor(TERM));
|
||||
}
|
||||
print("Config file %s.\n\n", config_ready ? "contains no valid entries" : "not found");
|
||||
print("For information on the format of Limine config entries, consult CONFIG.md in\n");
|
||||
print("the root of the Limine source repository.\n\n");
|
||||
print("Press a key to enter the Limine console...");
|
||||
term->double_buffer_flush(term);
|
||||
FOR_TERM(TERM->double_buffer_flush(TERM));
|
||||
getchar();
|
||||
reset_term();
|
||||
console();
|
||||
@ -761,10 +761,10 @@ refresh:
|
||||
|
||||
{ // Draw box around boot menu
|
||||
size_t x, y;
|
||||
term->get_cursor_pos(term, &x, &y);
|
||||
terms[0]->get_cursor_pos(terms[0], &x, &y);
|
||||
|
||||
print(serial ? "/" : "\xda");
|
||||
for (size_t i = 0; i < term->cols - 2; i++) {
|
||||
for (size_t i = 0; i < terms[0]->cols - 2; i++) {
|
||||
switch (i) {
|
||||
case 1: case 2: case 3:
|
||||
if (tree_offset > 0) {
|
||||
@ -777,16 +777,16 @@ refresh:
|
||||
}
|
||||
print(serial ? "\\" : "\xbf");
|
||||
|
||||
for (size_t i = y + 1; i < term->rows - 2; i++) {
|
||||
for (size_t i = y + 1; i < terms[0]->rows - 2; i++) {
|
||||
set_cursor_pos_helper(0, i);
|
||||
print(serial ? "|" : "\xb3");
|
||||
set_cursor_pos_helper(term->cols - 1, i);
|
||||
set_cursor_pos_helper(terms[0]->cols - 1, i);
|
||||
print(serial ? "|" : "\xb3");
|
||||
}
|
||||
set_cursor_pos_helper(0, term->rows - 2);
|
||||
set_cursor_pos_helper(0, terms[0]->rows - 2);
|
||||
|
||||
print(serial ? "\\" : "\xc0");
|
||||
for (size_t i = 0; i < term->cols - 2; i++) {
|
||||
for (size_t i = 0; i < terms[0]->cols - 2; i++) {
|
||||
print(serial ? "-" : "\xc4");
|
||||
}
|
||||
print(serial ? "/" : "\xd9");
|
||||
@ -794,15 +794,15 @@ refresh:
|
||||
set_cursor_pos_helper(x, y + 2);
|
||||
}
|
||||
|
||||
size_t max_entries = print_tree(tree_offset, term->rows - 10, serial ? "| " : "\xb3 ", 0, 0, selected_entry, menu_tree,
|
||||
size_t max_entries = print_tree(tree_offset, terms[0]->rows - 10, serial ? "| " : "\xb3 ", 0, 0, selected_entry, menu_tree,
|
||||
&selected_menu_entry);
|
||||
|
||||
{
|
||||
size_t x, y;
|
||||
term->get_cursor_pos(term, &x, &y);
|
||||
terms[0]->get_cursor_pos(terms[0], &x, &y);
|
||||
|
||||
if (tree_offset + (term->rows - 10) < max_entries) {
|
||||
set_cursor_pos_helper(2, term->rows - 2);
|
||||
if (tree_offset + (terms[0]->rows - 10) < max_entries) {
|
||||
set_cursor_pos_helper(2, terms[0]->rows - 2);
|
||||
print(serial ? "vvv" : "\x19\x19\x19");
|
||||
}
|
||||
|
||||
@ -813,7 +813,7 @@ refresh:
|
||||
print(" \e[32mARROWS\e[0m Select \e[32mENTER\e[0m %s",
|
||||
selected_menu_entry->expanded ? "Collapse" : "Expand");
|
||||
}
|
||||
set_cursor_pos_helper(term->cols - 13, 3);
|
||||
set_cursor_pos_helper(terms[0]->cols - 13, 3);
|
||||
print("\e[32mC\e[0m Console");
|
||||
set_cursor_pos_helper(x, y);
|
||||
}
|
||||
@ -826,11 +826,11 @@ refresh:
|
||||
if (skip_timeout == false) {
|
||||
print("\n\n");
|
||||
for (size_t i = timeout; i; i--) {
|
||||
set_cursor_pos_helper(0, term->rows - 1);
|
||||
term->scroll_enabled = false;
|
||||
set_cursor_pos_helper(0, terms[0]->rows - 1);
|
||||
FOR_TERM(TERM->scroll_enabled = false);
|
||||
print("\e[2K\e[32mBooting automatically in \e[92m%u\e[32m, press any key to stop the countdown...\e[0m", i);
|
||||
term->scroll_enabled = true;
|
||||
term->double_buffer_flush(term);
|
||||
FOR_TERM(TERM->scroll_enabled = true);
|
||||
FOR_TERM(TERM->double_buffer_flush(TERM));
|
||||
if ((c = pit_sleep_and_quit_on_keypress(1))) {
|
||||
skip_timeout = true;
|
||||
if (quiet) {
|
||||
@ -839,21 +839,21 @@ refresh:
|
||||
goto timeout_aborted;
|
||||
}
|
||||
print("\e[2K");
|
||||
term->double_buffer_flush(term);
|
||||
FOR_TERM(TERM->double_buffer_flush(TERM));
|
||||
goto timeout_aborted;
|
||||
}
|
||||
}
|
||||
goto autoboot;
|
||||
}
|
||||
|
||||
set_cursor_pos_helper(0, term->rows - 1);
|
||||
set_cursor_pos_helper(0, terms[0]->rows - 1);
|
||||
if (selected_menu_entry->comment != NULL) {
|
||||
term->scroll_enabled = false;
|
||||
FOR_TERM(TERM->scroll_enabled = false);
|
||||
print("\e[36m%s\e[0m", selected_menu_entry->comment);
|
||||
term->scroll_enabled = true;
|
||||
FOR_TERM(TERM->scroll_enabled = true);
|
||||
}
|
||||
|
||||
term->double_buffer_flush(term);
|
||||
FOR_TERM(TERM->double_buffer_flush(TERM));
|
||||
|
||||
for (;;) {
|
||||
c = getchar();
|
||||
@ -896,7 +896,7 @@ timeout_aborted:
|
||||
}
|
||||
if (!quiet) {
|
||||
if (term_backend == FALLBACK) {
|
||||
if (!gterm_init(NULL, 0, 0)) {
|
||||
if (!gterm_init(NULL, NULL, NULL, 0, 0)) {
|
||||
#if defined (BIOS)
|
||||
vga_textmode_init(true);
|
||||
#elif defined (UEFI)
|
||||
|
@ -216,10 +216,7 @@ noreturn void efi_chainload_file(char *config, struct file_handle *image) {
|
||||
pmm_free(_ptr, image->size);
|
||||
fclose(image);
|
||||
|
||||
if (term != NULL) {
|
||||
term->deinit(term, pmm_free);
|
||||
term = NULL;
|
||||
}
|
||||
term_notready();
|
||||
|
||||
size_t req_width = 0, req_height = 0, req_bpp = 0;
|
||||
|
||||
@ -227,9 +224,9 @@ noreturn void efi_chainload_file(char *config, struct file_handle *image) {
|
||||
if (resolution != NULL)
|
||||
parse_resolution(&req_width, &req_height, &req_bpp, resolution);
|
||||
|
||||
struct fb_info fbinfo;
|
||||
if (!fb_init(&fbinfo, req_width, req_height, req_bpp))
|
||||
panic(true, "chainload: Unable to set video mode");
|
||||
struct fb_info *fbinfo;
|
||||
size_t fb_count;
|
||||
fb_init(&fbinfo, &fb_count, req_width, req_height, req_bpp);
|
||||
|
||||
pmm_release_uefi_mem();
|
||||
|
||||
|
@ -275,9 +275,10 @@ static void callback_shim(struct term_context *ctx, uint64_t a, uint64_t b, uint
|
||||
actual_callback(term_arg, a, b, c, d);
|
||||
}
|
||||
|
||||
// TODO pair with specific terminal
|
||||
static void term_write_shim(uint64_t context, uint64_t buf, uint64_t count) {
|
||||
(void)context;
|
||||
_term_write(buf, count);
|
||||
_term_write(terms[0], buf, count);
|
||||
}
|
||||
|
||||
noreturn void limine_load(char *config, char *cmdline) {
|
||||
@ -670,10 +671,11 @@ FEAT_END
|
||||
parse_resolution(&req_width, &req_height, &req_bpp, resolution);
|
||||
}
|
||||
|
||||
struct fb_info fb;
|
||||
|
||||
uint64_t *term_fb_ptr = NULL;
|
||||
|
||||
struct fb_info *fbs;
|
||||
size_t fbs_count;
|
||||
|
||||
// Terminal feature
|
||||
FEAT_START
|
||||
struct limine_terminal_request *terminal_request = get_request(LIMINE_TERMINAL_REQUEST);
|
||||
@ -691,11 +693,11 @@ FEAT_START
|
||||
|
||||
char *term_conf_override_s = config_get_value(config, 0, "TERM_CONFIG_OVERRIDE");
|
||||
if (term_conf_override_s != NULL && strcmp(term_conf_override_s, "yes") == 0) {
|
||||
if (!gterm_init(config, req_width, req_height)) {
|
||||
if (!gterm_init(&fbs, &fbs_count, config, req_width, req_height)) {
|
||||
goto term_fail;
|
||||
}
|
||||
} else {
|
||||
if (!gterm_init(NULL, req_width, req_height)) {
|
||||
if (!gterm_init(&fbs, &fbs_count, NULL, req_width, req_height)) {
|
||||
goto term_fail;
|
||||
}
|
||||
}
|
||||
@ -707,10 +709,8 @@ term_fail:
|
||||
break; // next feature
|
||||
}
|
||||
|
||||
fb = fbinfo;
|
||||
|
||||
if (terminal_request->callback != 0) {
|
||||
term->callback = callback_shim;
|
||||
terms[0]->callback = callback_shim;
|
||||
|
||||
#if defined (__i386__)
|
||||
actual_callback = (void *)limine_term_callback;
|
||||
@ -739,8 +739,8 @@ term_fail:
|
||||
|
||||
term_fb_ptr = &terminal->framebuffer;
|
||||
|
||||
terminal->columns = term->cols;
|
||||
terminal->rows = term->rows;
|
||||
terminal->columns = terms[0]->cols;
|
||||
terminal->rows = terms[0]->rows;
|
||||
|
||||
uint64_t *term_list = ext_mem_alloc(1 * sizeof(uint64_t));
|
||||
term_list[0] = reported_addr(terminal);
|
||||
@ -753,27 +753,26 @@ term_fail:
|
||||
goto skip_fb_init;
|
||||
FEAT_END
|
||||
|
||||
if (term != NULL) {
|
||||
term->deinit(term, pmm_free);
|
||||
term = NULL;
|
||||
}
|
||||
term_notready();
|
||||
|
||||
if (!fb_init(&fb, req_width, req_height, req_bpp)) {
|
||||
fb_init(&fbs, &fbs_count, req_width, req_height, req_bpp);
|
||||
if (fbs_count == 0) {
|
||||
goto no_fb;
|
||||
}
|
||||
|
||||
skip_fb_init:
|
||||
memmap_alloc_range(fb.framebuffer_addr,
|
||||
(uint64_t)fb.framebuffer_pitch * fb.framebuffer_height,
|
||||
MEMMAP_FRAMEBUFFER, 0, false, false, true);
|
||||
for (size_t i = 0; i < fbs_count; i++) {
|
||||
memmap_alloc_range(fbs[i].framebuffer_addr,
|
||||
(uint64_t)fbs[i].framebuffer_pitch * fbs[i].framebuffer_height,
|
||||
MEMMAP_FRAMEBUFFER, 0, false, false, true);
|
||||
}
|
||||
|
||||
// Framebuffer feature
|
||||
FEAT_START
|
||||
// For now we only support 1 framebuffer
|
||||
struct limine_framebuffer *fbp = ext_mem_alloc(sizeof(struct limine_framebuffer));
|
||||
struct limine_framebuffer *fbp = ext_mem_alloc(fbs_count * sizeof(struct limine_framebuffer));
|
||||
|
||||
if (term_fb_ptr != NULL) {
|
||||
*term_fb_ptr = reported_addr(fbp);
|
||||
*term_fb_ptr = reported_addr(&fbp[0]);
|
||||
}
|
||||
|
||||
struct limine_framebuffer_request *framebuffer_request = get_request(LIMINE_FRAMEBUFFER_REQUEST);
|
||||
@ -784,43 +783,41 @@ FEAT_START
|
||||
struct limine_framebuffer_response *framebuffer_response =
|
||||
ext_mem_alloc(sizeof(struct limine_framebuffer_response));
|
||||
|
||||
struct edid_info_struct *edid_info = get_edid_info();
|
||||
if (edid_info != NULL) {
|
||||
fbp->edid_size = sizeof(struct edid_info_struct);
|
||||
fbp->edid = reported_addr(edid_info);
|
||||
}
|
||||
|
||||
framebuffer_response->revision = 1;
|
||||
|
||||
size_t modes_count;
|
||||
struct fb_info *modes = fb_get_mode_list(&modes_count);
|
||||
if (modes != NULL) {
|
||||
uint64_t *modes_list = ext_mem_alloc(modes_count * sizeof(uint64_t));
|
||||
for (size_t i = 0; i < modes_count; i++) {
|
||||
modes[i].memory_model = LIMINE_FRAMEBUFFER_RGB;
|
||||
modes_list[i] = reported_addr(&modes[i]);
|
||||
uint64_t *fb_list = ext_mem_alloc(fbs_count * sizeof(uint64_t));
|
||||
|
||||
for (size_t i = 0; i < fbs_count; i++) {
|
||||
uint64_t *modes_list = ext_mem_alloc(fbs[i].mode_count * sizeof(uint64_t));
|
||||
for (size_t j = 0; j < fbs[i].mode_count; j++) {
|
||||
fbs[i].mode_list[j].memory_model = LIMINE_FRAMEBUFFER_RGB;
|
||||
modes_list[j] = reported_addr(&fbs[i].mode_list[j]);
|
||||
}
|
||||
fbp->modes = reported_addr(modes_list);
|
||||
fbp->mode_count = modes_count;
|
||||
fbp[i].modes = reported_addr(modes_list);
|
||||
fbp[i].mode_count = fbs[i].mode_count;
|
||||
|
||||
if (fbs[i].edid != NULL) {
|
||||
fbp[i].edid_size = sizeof(struct edid_info_struct);
|
||||
fbp[i].edid = reported_addr(fbs[i].edid);
|
||||
}
|
||||
|
||||
fbp[i].memory_model = LIMINE_FRAMEBUFFER_RGB;
|
||||
fbp[i].address = reported_addr((void *)(uintptr_t)fbs[i].framebuffer_addr);
|
||||
fbp[i].width = fbs[i].framebuffer_width;
|
||||
fbp[i].height = fbs[i].framebuffer_height;
|
||||
fbp[i].bpp = fbs[i].framebuffer_bpp;
|
||||
fbp[i].pitch = fbs[i].framebuffer_pitch;
|
||||
fbp[i].red_mask_size = fbs[i].red_mask_size;
|
||||
fbp[i].red_mask_shift = fbs[i].red_mask_shift;
|
||||
fbp[i].green_mask_size = fbs[i].green_mask_size;
|
||||
fbp[i].green_mask_shift = fbs[i].green_mask_shift;
|
||||
fbp[i].blue_mask_size = fbs[i].blue_mask_size;
|
||||
fbp[i].blue_mask_shift = fbs[i].blue_mask_shift;
|
||||
|
||||
fb_list[i] = reported_addr(&fbp[i]);
|
||||
}
|
||||
|
||||
fbp->memory_model = LIMINE_FRAMEBUFFER_RGB;
|
||||
fbp->address = reported_addr((void *)(uintptr_t)fb.framebuffer_addr);
|
||||
fbp->width = fb.framebuffer_width;
|
||||
fbp->height = fb.framebuffer_height;
|
||||
fbp->bpp = fb.framebuffer_bpp;
|
||||
fbp->pitch = fb.framebuffer_pitch;
|
||||
fbp->red_mask_size = fb.red_mask_size;
|
||||
fbp->red_mask_shift = fb.red_mask_shift;
|
||||
fbp->green_mask_size = fb.green_mask_size;
|
||||
fbp->green_mask_shift = fb.green_mask_shift;
|
||||
fbp->blue_mask_size = fb.blue_mask_size;
|
||||
fbp->blue_mask_shift = fb.blue_mask_shift;
|
||||
|
||||
uint64_t *fb_list = ext_mem_alloc(1 * sizeof(uint64_t));
|
||||
fb_list[0] = reported_addr(fbp);
|
||||
|
||||
framebuffer_response->framebuffer_count = 1;
|
||||
framebuffer_response->framebuffer_count = fbs_count;
|
||||
framebuffer_response->framebuffers = reported_addr(fb_list);
|
||||
|
||||
framebuffer_request->response = reported_addr(framebuffer_response);
|
||||
@ -1029,10 +1026,8 @@ FEAT_START
|
||||
FEAT_END
|
||||
|
||||
// Clear terminal for kernels that will use the Limine terminal
|
||||
if (term != NULL) {
|
||||
term_write(term, "\e[2J\e[H", 7);
|
||||
term->in_bootloader = false;
|
||||
}
|
||||
FOR_TERM(term_write(TERM, "\e[2J\e[H", 7));
|
||||
FOR_TERM(TERM->in_bootloader = false);
|
||||
|
||||
#if defined (__x86_64__) || defined (__i386__)
|
||||
#if defined (BIOS)
|
||||
|
@ -495,10 +495,7 @@ noreturn void linux_load(char *config, char *cmdline) {
|
||||
// Video
|
||||
///////////////////////////////////////
|
||||
|
||||
if (term != NULL) {
|
||||
term->deinit(term, pmm_free);
|
||||
term = NULL;
|
||||
}
|
||||
term_notready();
|
||||
|
||||
struct screen_info *screen_info = &boot_params->screen_info;
|
||||
|
||||
@ -518,11 +515,13 @@ noreturn void linux_load(char *config, char *cmdline) {
|
||||
if (resolution != NULL)
|
||||
parse_resolution(&req_width, &req_height, &req_bpp, resolution);
|
||||
|
||||
struct fb_info fbinfo;
|
||||
struct fb_info *fbs;
|
||||
size_t fbs_count;
|
||||
#if defined (UEFI)
|
||||
gop_force_16 = true;
|
||||
#endif
|
||||
if (!fb_init(&fbinfo, req_width, req_height, req_bpp)) {
|
||||
fb_init(&fbs, &fbs_count, req_width, req_height, req_bpp);
|
||||
if (fbs_count == 0) {
|
||||
#if defined (UEFI)
|
||||
goto no_fb;
|
||||
#elif defined (BIOS)
|
||||
@ -531,8 +530,8 @@ set_textmode:;
|
||||
|
||||
screen_info->orig_video_mode = 3;
|
||||
screen_info->orig_video_ega_bx = 3;
|
||||
screen_info->orig_video_lines = term->rows;
|
||||
screen_info->orig_video_cols = term->cols;
|
||||
screen_info->orig_video_lines = 25;
|
||||
screen_info->orig_video_cols = 80;
|
||||
screen_info->orig_video_points = 16;
|
||||
|
||||
screen_info->orig_video_isVGA = VIDEO_TYPE_VGAC;
|
||||
@ -540,19 +539,23 @@ set_textmode:;
|
||||
} else {
|
||||
screen_info->capabilities = VIDEO_CAPABILITY_64BIT_BASE | VIDEO_CAPABILITY_SKIP_QUIRKS;
|
||||
screen_info->flags = VIDEO_FLAGS_NOCURSOR;
|
||||
screen_info->lfb_base = (uint32_t)fbinfo.framebuffer_addr;
|
||||
screen_info->ext_lfb_base = (uint32_t)(fbinfo.framebuffer_addr >> 32);
|
||||
screen_info->lfb_size = fbinfo.framebuffer_pitch * fbinfo.framebuffer_height;
|
||||
screen_info->lfb_width = fbinfo.framebuffer_width;
|
||||
screen_info->lfb_height = fbinfo.framebuffer_height;
|
||||
screen_info->lfb_depth = fbinfo.framebuffer_bpp;
|
||||
screen_info->lfb_linelength = fbinfo.framebuffer_pitch;
|
||||
screen_info->red_size = fbinfo.red_mask_size;
|
||||
screen_info->red_pos = fbinfo.red_mask_shift;
|
||||
screen_info->green_size = fbinfo.green_mask_size;
|
||||
screen_info->green_pos = fbinfo.green_mask_shift;
|
||||
screen_info->blue_size = fbinfo.blue_mask_size;
|
||||
screen_info->blue_pos = fbinfo.blue_mask_shift;
|
||||
screen_info->lfb_base = (uint32_t)fbs[0].framebuffer_addr;
|
||||
screen_info->ext_lfb_base = (uint32_t)(fbs[0].framebuffer_addr >> 32);
|
||||
screen_info->lfb_size = fbs[0].framebuffer_pitch * fbs[0].framebuffer_height;
|
||||
screen_info->lfb_width = fbs[0].framebuffer_width;
|
||||
screen_info->lfb_height = fbs[0].framebuffer_height;
|
||||
screen_info->lfb_depth = fbs[0].framebuffer_bpp;
|
||||
screen_info->lfb_linelength = fbs[0].framebuffer_pitch;
|
||||
screen_info->red_size = fbs[0].red_mask_size;
|
||||
screen_info->red_pos = fbs[0].red_mask_shift;
|
||||
screen_info->green_size = fbs[0].green_mask_size;
|
||||
screen_info->green_pos = fbs[0].green_mask_shift;
|
||||
screen_info->blue_size = fbs[0].blue_mask_size;
|
||||
screen_info->blue_pos = fbs[0].blue_mask_shift;
|
||||
|
||||
if (fbs[0].edid != NULL) {
|
||||
memcpy(&boot_params->edid_info, fbs[0].edid, sizeof(struct edid_info_struct));
|
||||
}
|
||||
|
||||
#if defined (BIOS)
|
||||
screen_info->orig_video_isVGA = VIDEO_TYPE_VLFB;
|
||||
@ -564,12 +567,6 @@ set_textmode:;
|
||||
#if defined (UEFI)
|
||||
no_fb:;
|
||||
#endif
|
||||
struct edid_info_struct *edid_info = get_edid_info();
|
||||
|
||||
if (edid_info != NULL) {
|
||||
memcpy(&boot_params->edid_info, edid_info, sizeof(struct edid_info_struct));
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// RSDP
|
||||
///////////////////////////////////////
|
||||
|
@ -302,77 +302,62 @@ noreturn void multiboot1_load(char *config, char *cmdline) {
|
||||
multiboot1_info->bootloader_name = (uint32_t)(size_t)lowmem_bootname - mb1_info_slide;
|
||||
multiboot1_info->flags |= (1 << 9);
|
||||
|
||||
if (term != NULL) {
|
||||
term->deinit(term, pmm_free);
|
||||
term = NULL;
|
||||
}
|
||||
term_notready();
|
||||
|
||||
size_t req_width = 0;
|
||||
size_t req_height = 0;
|
||||
size_t req_bpp = 0;
|
||||
|
||||
if (header.flags & (1 << 2)) {
|
||||
size_t req_width = header.fb_width;
|
||||
size_t req_height = header.fb_height;
|
||||
size_t req_bpp = header.fb_bpp;
|
||||
req_width = header.fb_width;
|
||||
req_height = header.fb_height;
|
||||
req_bpp = header.fb_bpp;
|
||||
|
||||
if (header.fb_mode == 0) {
|
||||
#if defined (UEFI)
|
||||
modeset:;
|
||||
#endif
|
||||
char *resolution = config_get_value(config, 0, "RESOLUTION");
|
||||
if (resolution != NULL)
|
||||
parse_resolution(&req_width, &req_height, &req_bpp, resolution);
|
||||
|
||||
struct fb_info fbinfo;
|
||||
if (!fb_init(&fbinfo, req_width, req_height, req_bpp)) {
|
||||
struct fb_info *fbs;
|
||||
size_t fbs_count;
|
||||
fb_init(&fbs, &fbs_count, req_width, req_height, req_bpp);
|
||||
if (fbs_count == 0) {
|
||||
#if defined (UEFI)
|
||||
goto skip_modeset;
|
||||
#elif defined (BIOS)
|
||||
textmode:
|
||||
vga_textmode_init(false);
|
||||
|
||||
multiboot1_info->fb_addr = 0xb8000;
|
||||
multiboot1_info->fb_width = term->cols;
|
||||
multiboot1_info->fb_height = term->rows;
|
||||
multiboot1_info->fb_width = 80;
|
||||
multiboot1_info->fb_height = 25;
|
||||
multiboot1_info->fb_bpp = 16;
|
||||
multiboot1_info->fb_pitch = 2 * term->cols;
|
||||
multiboot1_info->fb_pitch = 2 * 80;
|
||||
multiboot1_info->fb_type = 2;
|
||||
#endif
|
||||
} else {
|
||||
multiboot1_info->fb_addr = (uint64_t)fbinfo.framebuffer_addr;
|
||||
multiboot1_info->fb_width = fbinfo.framebuffer_width;
|
||||
multiboot1_info->fb_height = fbinfo.framebuffer_height;
|
||||
multiboot1_info->fb_bpp = fbinfo.framebuffer_bpp;
|
||||
multiboot1_info->fb_pitch = fbinfo.framebuffer_pitch;
|
||||
multiboot1_info->fb_addr = (uint64_t)fbs[0].framebuffer_addr;
|
||||
multiboot1_info->fb_width = fbs[0].framebuffer_width;
|
||||
multiboot1_info->fb_height = fbs[0].framebuffer_height;
|
||||
multiboot1_info->fb_bpp = fbs[0].framebuffer_bpp;
|
||||
multiboot1_info->fb_pitch = fbs[0].framebuffer_pitch;
|
||||
multiboot1_info->fb_type = 1;
|
||||
multiboot1_info->fb_red_mask_size = fbinfo.red_mask_size;
|
||||
multiboot1_info->fb_red_mask_shift = fbinfo.red_mask_shift;
|
||||
multiboot1_info->fb_green_mask_size = fbinfo.green_mask_size;
|
||||
multiboot1_info->fb_green_mask_shift = fbinfo.green_mask_shift;
|
||||
multiboot1_info->fb_blue_mask_size = fbinfo.blue_mask_size;
|
||||
multiboot1_info->fb_blue_mask_shift = fbinfo.blue_mask_shift;
|
||||
multiboot1_info->fb_red_mask_size = fbs[0].red_mask_size;
|
||||
multiboot1_info->fb_red_mask_shift = fbs[0].red_mask_shift;
|
||||
multiboot1_info->fb_green_mask_size = fbs[0].green_mask_size;
|
||||
multiboot1_info->fb_green_mask_shift = fbs[0].green_mask_shift;
|
||||
multiboot1_info->fb_blue_mask_size = fbs[0].blue_mask_size;
|
||||
multiboot1_info->fb_blue_mask_shift = fbs[0].blue_mask_shift;
|
||||
}
|
||||
} else {
|
||||
#if defined (UEFI)
|
||||
print("multiboot1: Warning: Cannot use text mode with UEFI\n");
|
||||
struct fb_info fbinfo;
|
||||
if (!fb_init(&fbinfo, 0, 0, 0)) {
|
||||
goto skip_modeset;
|
||||
}
|
||||
multiboot1_info->fb_addr = (uint64_t)fbinfo.framebuffer_addr;
|
||||
multiboot1_info->fb_width = fbinfo.framebuffer_width;
|
||||
multiboot1_info->fb_height = fbinfo.framebuffer_height;
|
||||
multiboot1_info->fb_bpp = fbinfo.framebuffer_bpp;
|
||||
multiboot1_info->fb_pitch = fbinfo.framebuffer_pitch;
|
||||
multiboot1_info->fb_type = 1;
|
||||
multiboot1_info->fb_red_mask_size = fbinfo.red_mask_size;
|
||||
multiboot1_info->fb_red_mask_shift = fbinfo.red_mask_shift;
|
||||
multiboot1_info->fb_green_mask_size = fbinfo.green_mask_size;
|
||||
multiboot1_info->fb_green_mask_shift = fbinfo.green_mask_shift;
|
||||
multiboot1_info->fb_blue_mask_size = fbinfo.blue_mask_size;
|
||||
multiboot1_info->fb_blue_mask_shift = fbinfo.blue_mask_shift;
|
||||
goto modeset;
|
||||
#elif defined (BIOS)
|
||||
vga_textmode_init(false);
|
||||
|
||||
multiboot1_info->fb_addr = 0xb8000;
|
||||
multiboot1_info->fb_width = term->cols;
|
||||
multiboot1_info->fb_height = term->rows;
|
||||
multiboot1_info->fb_bpp = 16;
|
||||
multiboot1_info->fb_pitch = 2 * term->cols;
|
||||
multiboot1_info->fb_type = 2;
|
||||
goto textmode;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -516,29 +516,36 @@ noreturn void multiboot2_load(char *config, char* cmdline) {
|
||||
tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
|
||||
tag->common.size = sizeof(struct multiboot_tag_framebuffer);
|
||||
|
||||
if (term != NULL) {
|
||||
term->deinit(term, pmm_free);
|
||||
term = NULL;
|
||||
}
|
||||
term_notready();
|
||||
|
||||
size_t req_width = 0;
|
||||
size_t req_height = 0;
|
||||
size_t req_bpp = 0;
|
||||
|
||||
if (fbtag) {
|
||||
size_t req_width = fbtag->width;
|
||||
size_t req_height = fbtag->height;
|
||||
size_t req_bpp = fbtag->depth;
|
||||
req_width = fbtag->width;
|
||||
req_height = fbtag->height;
|
||||
req_bpp = fbtag->depth;
|
||||
|
||||
#if defined (UEFI)
|
||||
modeset:;
|
||||
#endif
|
||||
char *resolution = config_get_value(config, 0, "RESOLUTION");
|
||||
if (resolution != NULL)
|
||||
parse_resolution(&req_width, &req_height, &req_bpp, resolution);
|
||||
|
||||
struct fb_info fbinfo;
|
||||
if (!fb_init(&fbinfo, req_width, req_height, req_bpp)) {
|
||||
struct fb_info *fbs;
|
||||
size_t fbs_count;
|
||||
fb_init(&fbs, &fbs_count, req_width, req_height, req_bpp);
|
||||
if (fbs_count == 0) {
|
||||
#if defined (BIOS)
|
||||
textmode:
|
||||
vga_textmode_init(false);
|
||||
|
||||
tag->common.framebuffer_addr = 0xb8000;
|
||||
tag->common.framebuffer_pitch = 2 * term->cols;
|
||||
tag->common.framebuffer_width = term->cols;
|
||||
tag->common.framebuffer_height = term->rows;
|
||||
tag->common.framebuffer_pitch = 2 * 80;
|
||||
tag->common.framebuffer_width = 80;
|
||||
tag->common.framebuffer_height = 25;
|
||||
tag->common.framebuffer_bpp = 16;
|
||||
tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT;
|
||||
#elif defined (UEFI)
|
||||
@ -549,54 +556,26 @@ noreturn void multiboot2_load(char *config, char* cmdline) {
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
tag->common.framebuffer_addr = fbinfo.framebuffer_addr;
|
||||
tag->common.framebuffer_pitch = fbinfo.framebuffer_pitch;
|
||||
tag->common.framebuffer_width = fbinfo.framebuffer_width;
|
||||
tag->common.framebuffer_height = fbinfo.framebuffer_height;
|
||||
tag->common.framebuffer_bpp = fbinfo.framebuffer_bpp;
|
||||
tag->common.framebuffer_addr = fbs[0].framebuffer_addr;
|
||||
tag->common.framebuffer_pitch = fbs[0].framebuffer_pitch;
|
||||
tag->common.framebuffer_width = fbs[0].framebuffer_width;
|
||||
tag->common.framebuffer_height = fbs[0].framebuffer_height;
|
||||
tag->common.framebuffer_bpp = fbs[0].framebuffer_bpp;
|
||||
tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB; // We only support RGB for VBE
|
||||
|
||||
tag->framebuffer_red_field_position = fbinfo.red_mask_shift;
|
||||
tag->framebuffer_red_mask_size = fbinfo.red_mask_size;
|
||||
tag->framebuffer_green_field_position = fbinfo.green_mask_shift;
|
||||
tag->framebuffer_green_mask_size = fbinfo.green_mask_size;
|
||||
tag->framebuffer_blue_field_position = fbinfo.blue_mask_shift;
|
||||
tag->framebuffer_blue_mask_size = fbinfo.blue_mask_size;
|
||||
tag->framebuffer_red_field_position = fbs[0].red_mask_shift;
|
||||
tag->framebuffer_red_mask_size = fbs[0].red_mask_size;
|
||||
tag->framebuffer_green_field_position = fbs[0].green_mask_shift;
|
||||
tag->framebuffer_green_mask_size = fbs[0].green_mask_size;
|
||||
tag->framebuffer_blue_field_position = fbs[0].blue_mask_shift;
|
||||
tag->framebuffer_blue_mask_size = fbs[0].blue_mask_size;
|
||||
}
|
||||
} else {
|
||||
#if defined (UEFI)
|
||||
print("multiboot2: Warning: Cannot use text mode with UEFI\n");
|
||||
struct fb_info fbinfo;
|
||||
if (!fb_init(&fbinfo, 0, 0, 0)) {
|
||||
if (is_framebuffer_required) {
|
||||
panic(true, "multiboot2: Failed to set video mode");
|
||||
} else {
|
||||
goto skip_modeset;
|
||||
}
|
||||
}
|
||||
|
||||
tag->common.framebuffer_addr = fbinfo.framebuffer_addr;
|
||||
tag->common.framebuffer_pitch = fbinfo.framebuffer_pitch;
|
||||
tag->common.framebuffer_width = fbinfo.framebuffer_width;
|
||||
tag->common.framebuffer_height = fbinfo.framebuffer_height;
|
||||
tag->common.framebuffer_bpp = fbinfo.framebuffer_bpp;
|
||||
tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB; // We only support RGB for VBE
|
||||
|
||||
tag->framebuffer_red_field_position = fbinfo.red_mask_shift;
|
||||
tag->framebuffer_red_mask_size = fbinfo.red_mask_size;
|
||||
tag->framebuffer_green_field_position = fbinfo.green_mask_shift;
|
||||
tag->framebuffer_green_mask_size = fbinfo.green_mask_size;
|
||||
tag->framebuffer_blue_field_position = fbinfo.blue_mask_shift;
|
||||
tag->framebuffer_blue_mask_size = fbinfo.blue_mask_size;
|
||||
goto modeset;
|
||||
#elif defined (BIOS)
|
||||
vga_textmode_init(false);
|
||||
|
||||
tag->common.framebuffer_addr = 0xb8000;
|
||||
tag->common.framebuffer_width = term->cols;
|
||||
tag->common.framebuffer_height = term->rows;
|
||||
tag->common.framebuffer_bpp = 16;
|
||||
tag->common.framebuffer_pitch = 2 * term->cols;
|
||||
tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT;
|
||||
goto textmode;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user