loader: create local copy of mode list provided by vbeinfoblock
Apparently some systems do corrupt mode list memory area, so we need to use local copy instead.
This commit is contained in:
parent
0bc776f3da
commit
ad1ebbe5ce
@ -48,12 +48,14 @@
|
|||||||
|
|
||||||
static struct vbeinfoblock *vbe;
|
static struct vbeinfoblock *vbe;
|
||||||
static struct modeinfoblock *vbe_mode;
|
static struct modeinfoblock *vbe_mode;
|
||||||
|
|
||||||
|
static uint16_t *vbe_mode_list;
|
||||||
|
static size_t vbe_mode_list_size;
|
||||||
|
|
||||||
/* The default VGA color palette format is 6 bits per primary color. */
|
/* The default VGA color palette format is 6 bits per primary color. */
|
||||||
int palette_format = 6;
|
int palette_format = 6;
|
||||||
|
|
||||||
#define VESA_MODE_BASE 0x100
|
#define VESA_MODE_BASE 0x100
|
||||||
#define VESA_MODE_MAX 0x1ff
|
|
||||||
#define VESA_MODE_COUNT (VESA_MODE_MAX - VESA_MODE_BASE + 1)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* palette array for 8-bit indexed colors. In this case, cmap does store
|
* palette array for 8-bit indexed colors. In this case, cmap does store
|
||||||
@ -545,9 +547,17 @@ mode_set(struct env_var *ev, int flags __unused, const void *value)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
vbe_farptr(uint32_t farptr)
|
||||||
|
{
|
||||||
|
return (PTOV((((farptr & 0xffff0000) >> 12) + (farptr & 0xffff))));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
vbe_init(void)
|
vbe_init(void)
|
||||||
{
|
{
|
||||||
|
uint16_t *p, *ml;
|
||||||
|
|
||||||
/* First set FB for text mode. */
|
/* First set FB for text mode. */
|
||||||
gfx_state.tg_fb_type = FB_TEXT;
|
gfx_state.tg_fb_type = FB_TEXT;
|
||||||
gfx_state.tg_fb.fb_height = TEXT_ROWS;
|
gfx_state.tg_fb.fb_height = TEXT_ROWS;
|
||||||
@ -573,6 +583,27 @@ vbe_init(void)
|
|||||||
vbe_mode = NULL;
|
vbe_mode = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy mode list. We must do this because some systems do
|
||||||
|
* corrupt the provided list (vbox 6.1 is one example).
|
||||||
|
*/
|
||||||
|
p = ml = vbe_farptr(vbe->VideoModePtr);
|
||||||
|
while(*p++ != 0xFFFF)
|
||||||
|
;
|
||||||
|
|
||||||
|
vbe_mode_list_size = (uintptr_t)p - (uintptr_t)ml;
|
||||||
|
vbe_mode_list = malloc(vbe_mode_list_size);
|
||||||
|
if (vbe_mode_list == NULL) {
|
||||||
|
free(vbe);
|
||||||
|
vbe = NULL;
|
||||||
|
free(vbe_mode);
|
||||||
|
vbe_mode = NULL;
|
||||||
|
}
|
||||||
|
bcopy(ml, vbe_mode_list, vbe_mode_list_size);
|
||||||
|
|
||||||
|
/* reset VideoModePtr, so we will not have chance to use bad data. */
|
||||||
|
vbe->VideoModePtr = 0;
|
||||||
|
|
||||||
env_setenv("screen.textmode", EV_VOLATILE, "1", mode_set,
|
env_setenv("screen.textmode", EV_VOLATILE, "1", mode_set,
|
||||||
env_nounset);
|
env_nounset);
|
||||||
env_setenv("vbe_max_resolution", EV_VOLATILE, NULL, mode_set,
|
env_setenv("vbe_max_resolution", EV_VOLATILE, NULL, mode_set,
|
||||||
@ -717,12 +748,6 @@ vbe_set_mode(int modenum)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
|
||||||
vbe_farptr(uint32_t farptr)
|
|
||||||
{
|
|
||||||
return (PTOV((((farptr & 0xffff0000) >> 12) + (farptr & 0xffff))));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Verify existance of mode number or find mode by
|
* Verify existance of mode number or find mode by
|
||||||
* dimensions. If depth is not given, walk values 32, 24, 16, 8.
|
* dimensions. If depth is not given, walk values 32, 24, 16, 8.
|
||||||
@ -731,15 +756,13 @@ static int
|
|||||||
vbe_find_mode_xydm(int x, int y, int depth, int m)
|
vbe_find_mode_xydm(int x, int y, int depth, int m)
|
||||||
{
|
{
|
||||||
struct modeinfoblock mi;
|
struct modeinfoblock mi;
|
||||||
uint32_t farptr;
|
uint16_t *farptr;
|
||||||
uint16_t mode;
|
uint16_t mode;
|
||||||
int safety, i;
|
int idx, nitems, i;
|
||||||
|
|
||||||
memset(vbe, 0, sizeof (*vbe));
|
memset(vbe, 0, sizeof (*vbe));
|
||||||
if (biosvbe_info(vbe) != VBE_SUCCESS)
|
if (biosvbe_info(vbe) != VBE_SUCCESS)
|
||||||
return (0);
|
return (0);
|
||||||
if (vbe->VideoModePtr == 0)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
if (m != -1)
|
if (m != -1)
|
||||||
i = 8;
|
i = 8;
|
||||||
@ -748,17 +771,17 @@ vbe_find_mode_xydm(int x, int y, int depth, int m)
|
|||||||
else
|
else
|
||||||
i = depth;
|
i = depth;
|
||||||
|
|
||||||
|
nitems = vbe_mode_list_size / sizeof(*vbe_mode_list);
|
||||||
while (i > 0) {
|
while (i > 0) {
|
||||||
farptr = vbe->VideoModePtr;
|
for (idx = 0; idx < nitems; idx++) {
|
||||||
safety = 0;
|
mode = vbe_mode_list[idx];
|
||||||
while ((mode = *(uint16_t *)vbe_farptr(farptr)) != 0xffff) {
|
if (mode == 0xffff)
|
||||||
safety++;
|
|
||||||
farptr += 2;
|
|
||||||
if (safety == VESA_MODE_COUNT)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (biosvbe_get_mode_info(mode, &mi) != VBE_SUCCESS) {
|
if (biosvbe_get_mode_info(mode, &mi) != VBE_SUCCESS) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we only care about linear modes here */
|
/* we only care about linear modes here */
|
||||||
if (vbe_mode_is_supported(&mi) == 0)
|
if (vbe_mode_is_supported(&mi) == 0)
|
||||||
continue;
|
continue;
|
||||||
@ -910,9 +933,8 @@ void
|
|||||||
vbe_modelist(int depth)
|
vbe_modelist(int depth)
|
||||||
{
|
{
|
||||||
struct modeinfoblock mi;
|
struct modeinfoblock mi;
|
||||||
uint32_t farptr;
|
|
||||||
uint16_t mode;
|
uint16_t mode;
|
||||||
int nmodes = 0, safety = 0;
|
int nmodes, idx, nentries;
|
||||||
int ddc_caps;
|
int ddc_caps;
|
||||||
uint32_t width, height;
|
uint32_t width, height;
|
||||||
bool edid = false;
|
bool edid = false;
|
||||||
@ -948,6 +970,7 @@ vbe_modelist(int depth)
|
|||||||
if (vbe_get_flatpanel(&width, &height))
|
if (vbe_get_flatpanel(&width, &height))
|
||||||
printf(": Panel %dx%d\n", width, height);
|
printf(": Panel %dx%d\n", width, height);
|
||||||
|
|
||||||
|
nmodes = 0;
|
||||||
memset(vbe, 0, sizeof (*vbe));
|
memset(vbe, 0, sizeof (*vbe));
|
||||||
memcpy(vbe->VbeSignature, "VBE2", 4);
|
memcpy(vbe->VbeSignature, "VBE2", 4);
|
||||||
if (biosvbe_info(vbe) != VBE_SUCCESS)
|
if (biosvbe_info(vbe) != VBE_SUCCESS)
|
||||||
@ -958,26 +981,19 @@ vbe_modelist(int depth)
|
|||||||
vbe_print_vbe_info(vbe);
|
vbe_print_vbe_info(vbe);
|
||||||
printf("Modes: ");
|
printf("Modes: ");
|
||||||
|
|
||||||
farptr = vbe->VideoModePtr;
|
nentries = vbe_mode_list_size / sizeof(*vbe_mode_list);
|
||||||
if (farptr == 0)
|
for (idx = 0; idx < nentries; idx++) {
|
||||||
goto done;
|
mode = vbe_mode_list[idx];
|
||||||
|
if (mode == 0xffff)
|
||||||
while ((mode = *(uint16_t *)vbe_farptr(farptr)) != 0xffff) {
|
|
||||||
safety++;
|
|
||||||
farptr += 2;
|
|
||||||
if (safety == VESA_MODE_COUNT) {
|
|
||||||
printf("[?] ");
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
if (biosvbe_get_mode_info(mode, &mi) != VBE_SUCCESS)
|
if (biosvbe_get_mode_info(mode, &mi) != VBE_SUCCESS)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* we only care about linear modes here */
|
/* we only care about linear modes here */
|
||||||
if (vbe_mode_is_supported(&mi) == 0)
|
if (vbe_mode_is_supported(&mi) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* we found some mode so reset safety counter */
|
|
||||||
safety = 0;
|
|
||||||
|
|
||||||
/* apply requested filter */
|
/* apply requested filter */
|
||||||
if (depth != -1 && mi.BitsPerPixel != depth)
|
if (depth != -1 && mi.BitsPerPixel != depth)
|
||||||
continue;
|
continue;
|
||||||
|
Loading…
Reference in New Issue
Block a user