2019-09-03 11:58:42 +02:00
|
|
|
/*
|
|
|
|
* resolution.h
|
|
|
|
*
|
|
|
|
* Created by Evan Lojewski on 3/4/10.
|
|
|
|
* Copyright 2009. All rights reserved.
|
|
|
|
*
|
|
|
|
* remake for Clover by dmazar and slice 2012
|
|
|
|
*/
|
|
|
|
#ifndef _RESOLUTION_H_
|
|
|
|
#define _RESOLUTION_H_
|
|
|
|
|
|
|
|
#include "VideoBiosPatchLibInternal.h"
|
|
|
|
|
|
|
|
static const UINT8 nvda_pattern[] = {
|
|
|
|
0x44, 0x01, 0x04, 0x00
|
|
|
|
};
|
|
|
|
|
|
|
|
static const CHAR8 nvda_string[] = "NVID";
|
|
|
|
|
|
|
|
|
|
|
|
//more advanced tables from pene
|
|
|
|
#define RESOLUTIONS_NUMBER 11
|
|
|
|
static TABLE_0 nvda_res[RESOLUTIONS_NUMBER] = {
|
|
|
|
{1280, 720},
|
|
|
|
{1280, 800},
|
|
|
|
{1360, 768},
|
|
|
|
{1400, 1050},
|
|
|
|
{1440, 900},
|
|
|
|
{1600, 900},
|
|
|
|
{1600, 1200},
|
|
|
|
{1680, 1050},
|
|
|
|
{1920, 1080},
|
|
|
|
{1920, 1200},
|
|
|
|
{2048, 1536}
|
|
|
|
};
|
|
|
|
|
|
|
|
static UINT8 Sample0[] =
|
|
|
|
{0x34, 0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x9c, 0x8f, 0x96, 0xb9, 0x8e, 0x1f, 0x00, 0x00, 0x00};
|
|
|
|
|
|
|
|
static TABLE_A nvda_key0[] = {
|
|
|
|
{3, {0x16, 0xCB, 0x9F, 0x9F, 0x8F, 0xA7, 0x17, 0xEA, 0xD2, 0xCF, 0xCF, 0xEB, 0x47, 0xE0, 0xC0, 0x00, 0x01}},
|
|
|
|
{0, {0x12, 0xCD, 0x9F, 0x9F, 0x91, 0xA9, 0x1A, 0x3A, 0x21, 0x1F, 0x1F, 0x3B, 0x44, 0xFE, 0xC0, 0x00, 0x01}},
|
|
|
|
{3, {0x16, 0xB9, 0xA9, 0x9F, 0x8F, 0xB2, 0x16, 0x14, 0x01, 0xFF, 0xCF, 0xEB, 0x46, 0xEA, 0xC0, 0x00, 0x01}},
|
|
|
|
{1, {0x12, 0xE6, 0xAE, 0xAE, 0x8A, 0xBB, 0x8E, 0x3D, 0x1B, 0x19, 0x19, 0x3E, 0x0E, 0x00, 0xC0, 0x24, 0x12}},
|
|
|
|
{0, {0x12, 0xE9, 0xB3, 0xB3, 0x8D, 0xBF, 0x92, 0xA3, 0x85, 0x83, 0x83, 0xA4, 0x48, 0xFE, 0xC0, 0x00, 0x00}},
|
|
|
|
{3, {0x1A, 0xD7, 0xC7, 0xC7, 0x9B, 0xCD, 0x11, 0x9C, 0x86, 0x83, 0x83, 0x9D, 0x4B, 0xFE, 0xC0, 0x00, 0x00}},
|
|
|
|
{1, {0x12, 0x03, 0xC7, 0xC7, 0x87, 0xD1, 0x09, 0xE0, 0xB1, 0xAF, 0xAF, 0xE1, 0x04, 0x00, 0x01, 0x24, 0x13}},
|
|
|
|
{0, {0x12, 0x15, 0xD1, 0xD1, 0x99, 0xE0, 0x17, 0x3D, 0x1B, 0x19, 0x19, 0x3E, 0x0E, 0x00, 0x01, 0x24, 0x13}},
|
|
|
|
{3, {0x16, 0x0E, 0xEF, 0x9F, 0x8F, 0xFD, 0x02, 0x63, 0x3B, 0x37, 0xCF, 0xEB, 0x40, 0x00, 0xC1, 0x24, 0x02}},
|
|
|
|
{0, {0x12, 0x3F, 0xEF, 0xEF, 0x83, 0x01, 0x1B, 0xD8, 0xB1, 0xAF, 0xAF, 0xD9, 0x04, 0x00, 0x41, 0x25, 0x12}},
|
|
|
|
{1, {0x12, 0x63, 0xFF, 0xFF, 0x9D, 0x12, 0x0E, 0x34, 0x01, 0x00, 0x00, 0x35, 0x44, 0xE0, 0x41, 0x25, 0x13}}
|
|
|
|
};
|
|
|
|
|
|
|
|
static UINT8 Sample1[] =
|
|
|
|
{0x28, 0x00, 0x19, 0x00, 0x28, 0x18, 0x08, 0x08, 0x05};
|
|
|
|
|
|
|
|
static TABLE_B nvda_key1[] = {
|
|
|
|
{3, {0x00, 0x05, 0xD0, 0x02, 0xA0, 0x2C, 0x10, 0x07, 0x05}},
|
|
|
|
{0, {0x00, 0x05, 0x20, 0x03, 0xA0, 0x32, 0x10, 0x23, 0x05}},
|
|
|
|
{3, {0x50, 0x05, 0x00, 0x03, 0xAA, 0x2F, 0x10, 0x07, 0x05}},
|
|
|
|
{1, {0x78, 0x05, 0x1A, 0x04, 0xAF, 0x4A, 0x0E, 0x21, 0x05}},
|
|
|
|
{0, {0xA0, 0x05, 0x84, 0x03, 0xB4, 0x38, 0x10, 0x24, 0x05}},
|
|
|
|
{3, {0x40, 0x06, 0x84, 0x03, 0xC8, 0x38, 0x10, 0x27, 0x05}},
|
|
|
|
{1, {0x40, 0x06, 0xB0, 0x04, 0xC8, 0x4A, 0x10, 0x19, 0x05}},
|
|
|
|
{0, {0x90, 0x06, 0x1A, 0x04, 0xD2, 0x41, 0x10, 0x25, 0x05}},
|
|
|
|
{3, {0x80, 0x07, 0x38, 0x04, 0xF0, 0x42, 0x10, 0x07, 0x05}},
|
|
|
|
{0, {0x80, 0x07, 0xB0, 0x04, 0xF0, 0x4B, 0x10, 0x26, 0x05}},
|
|
|
|
{1, {0x00, 0x08, 0x00, 0x06, 0x00, 0x60, 0x10, 0x22, 0x05}}
|
|
|
|
};
|
|
|
|
|
|
|
|
static UINT8 Sample2[] =
|
|
|
|
{0x82, 0x0f, 0x03, 0x01, 0x00, 0x00, 0x08, 0x04, 0x14, 0x00, 0x00, 0x08, 0x17};
|
|
|
|
|
|
|
|
static TABLE_D nvda_key2[] = {
|
|
|
|
{3, {0x7B, 0x01, 0x03, 0x7B, 0x01, 0x08, 0x01, 0x20, 0x80, 0x02, 0xFF, 0xFF, 0x20}},
|
|
|
|
{0, {0x61, 0x01, 0x03, 0x61, 0x01, 0x08, 0x01, 0x20, 0x80, 0x02, 0xFF, 0xFF, 0x20}},
|
|
|
|
{3, {0x4D, 0x01, 0x03, 0x4D, 0x01, 0x08, 0x01, 0x20, 0xA8, 0x02, 0xFF, 0xFF, 0x20}},
|
|
|
|
{1, {0x49, 0x01, 0x03, 0x49, 0x01, 0x08, 0x01, 0x20, 0xBC, 0x02, 0xFF, 0xFF, 0x20}},
|
|
|
|
{0, {0x65, 0x01, 0x03, 0x65, 0x01, 0x08, 0x01, 0x20, 0xD0, 0x02, 0xFF, 0xFF, 0x20}},
|
|
|
|
{3, {0x67, 0x01, 0x03, 0x67, 0x01, 0x08, 0x01, 0x20, 0x20, 0x03, 0xFF, 0xFF, 0x20}},
|
|
|
|
{1, {0x4A, 0x01, 0x03, 0x4A, 0x01, 0x08, 0x01, 0x20, 0x20, 0x03, 0xFF, 0xFF, 0x20}},
|
|
|
|
{0, {0x69, 0x01, 0x03, 0x69, 0x01, 0x08, 0x01, 0x20, 0x48, 0x03, 0xFF, 0xFF, 0x20}},
|
|
|
|
{3, {0x4D, 0x01, 0x03, 0x4D, 0x01, 0x08, 0x01, 0x20, 0xC0, 0x03, 0xFF, 0xFF, 0x20}},
|
|
|
|
{0, {0x7D, 0x01, 0x03, 0x7D, 0x01, 0x08, 0x01, 0x20, 0xC0, 0x03, 0xFF, 0xFF, 0x20}},
|
|
|
|
{1, {0x7A, 0x01, 0x03, 0x52, 0x01, 0x08, 0x01, 0x20, 0x00, 0x04, 0xFF, 0xFF, 0x20}}
|
|
|
|
};
|
|
|
|
|
|
|
|
static UINT8 Sample3[] = {0x40, 0x06, 0xba, 0xb0, 0x04};
|
|
|
|
|
|
|
|
static TABLE_LIMIT nvda_key3[] = {
|
|
|
|
{3, {0x00, 0x05, 0xBA, 0xD0, 0x02}},
|
|
|
|
{0, {0x00, 0x05, 0xBA, 0x20, 0x03}},
|
|
|
|
{3, {0x50, 0x05, 0xBA, 0x00, 0x03}},
|
|
|
|
{1, {0x78, 0x05, 0xBA, 0x1A, 0x04}},
|
|
|
|
{0, {0xA0, 0x05, 0xBA, 0x84, 0x03}},
|
|
|
|
{3, {0x40, 0x06, 0xBA, 0x84, 0x03}},
|
|
|
|
{1, {0x40, 0x06, 0xBA, 0xB0, 0x04}},
|
|
|
|
{0, {0x90, 0x06, 0xBA, 0x1A, 0x04}},
|
|
|
|
{3, {0x80, 0x07, 0xBA, 0x38, 0x04}},
|
|
|
|
{0, {0x80, 0x07, 0xBA, 0xB0, 0x04}},
|
|
|
|
{1, {0x00, 0x08, 0xBA, 0x00, 0x06}}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
//DTD string to replace in Intel BIOSes
|
|
|
|
static UINT8 DTD_1024[] = {0x64, 0x19, 0x00, 0x40, 0x41, 0x00, 0x26, 0x30, 0x18,
|
|
|
|
0x88, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18};
|
|
|
|
|
|
|
|
/* Copied from 915 resolution created by steve tomljenovic
|
|
|
|
*
|
|
|
|
* This code is based on the techniques used in :
|
|
|
|
*
|
|
|
|
* - 855patch. Many thanks to Christian Zietz (czietz gmx net)
|
|
|
|
* for demonstrating how to shadow the VBIOS into system RAM
|
|
|
|
* and then modify it.
|
|
|
|
*
|
|
|
|
* - 1280patch by Andrew Tipton (andrewtipton null li).
|
|
|
|
*
|
|
|
|
* - 855resolution by Alain Poirier
|
|
|
|
*
|
|
|
|
* This source code is into the public domain.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
INT32 freqs[] = { 60, 75, 85 };
|
|
|
|
|
|
|
|
vbios_resolution_type1 * map_type1_resolution(vbios_map * map, UINT16 res)
|
|
|
|
{
|
|
|
|
vbios_resolution_type1 * ptr = ((vbios_resolution_type1*)(map->bios_ptr + res));
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
vbios_resolution_type2 * map_type2_resolution(vbios_map * map, UINT16 res)
|
|
|
|
{
|
|
|
|
vbios_resolution_type2 * ptr = ((vbios_resolution_type2*)(map->bios_ptr + res));
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
vbios_resolution_type3 * map_type3_resolution(vbios_map * map, UINT16 res)
|
|
|
|
{
|
|
|
|
vbios_resolution_type3 * ptr = ((vbios_resolution_type3*)(map->bios_ptr + res));
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
CHAR8 detect_bios_type(vbios_map * map, CHAR8 modeline, INT32 entry_size);
|
|
|
|
CHAR8 detect_bios_type(vbios_map * map, CHAR8 modeline, INT32 entry_size)
|
|
|
|
{
|
|
|
|
UINT32 i;
|
|
|
|
UINT16 r1, r2;
|
|
|
|
|
|
|
|
r1 = r2 = 32000;
|
|
|
|
|
|
|
|
for (i=0; i < map->mode_table_size; i++)
|
|
|
|
{
|
|
|
|
if (map->mode_table[i].resolution <= r1)
|
|
|
|
{
|
|
|
|
r1 = map->mode_table[i].resolution;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (map->mode_table[i].resolution <= r2)
|
|
|
|
{
|
|
|
|
r2 = map->mode_table[i].resolution;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (r2-r1-6) % entry_size == 0;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
VOID close_vbios(vbios_map * map);
|
|
|
|
|
|
|
|
CHAR8 detect_ati_bios_type(vbios_map * map)
|
|
|
|
{
|
|
|
|
return map->mode_table_size % sizeof(ATOM_MODE_TIMING) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vbios_map * open_vbios(chipset_type forced_chipset)
|
|
|
|
{
|
|
|
|
UINTN i;
|
|
|
|
UINTN j;
|
|
|
|
|
|
|
|
vbios_map * map = AllocateZeroPool(sizeof(vbios_map));
|
|
|
|
DBG(" Bios:");
|
|
|
|
/*
|
|
|
|
* Determine chipset
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* dmazar: no need to mess with chipsets - we'll use LegacyRegion protocols to unlock vbios
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Map the video bios to memory
|
|
|
|
*/
|
|
|
|
map->bios_ptr=(CHAR8*)(UINTN)VBIOS_START;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* check if we have ATI Radeon
|
|
|
|
*/
|
|
|
|
map->ati_tables.base = map->bios_ptr;
|
|
|
|
map->ati_tables.AtomRomHeader = (ATOM_ROM_HEADER *) (map->bios_ptr + *(UINT16 *) (map->bios_ptr + OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER));
|
2020-04-23 11:08:10 +02:00
|
|
|
if (AsciiStrCmp((CHAR8 *) map->ati_tables.AtomRomHeader->uaFirmWareSignature, "ATOM") == 0)
|
2019-09-03 11:58:42 +02:00
|
|
|
{
|
|
|
|
UINT16 std_vesa_offset;
|
|
|
|
ATOM_STANDARD_VESA_TIMING * std_vesa;
|
|
|
|
|
|
|
|
// ATI Radeon Card
|
|
|
|
DBG(" ATI");
|
|
|
|
map->bios = BT_ATI_1;
|
|
|
|
|
|
|
|
map->ati_tables.MasterDataTables = (UINT16 *) &((ATOM_MASTER_DATA_TABLE *) (map->bios_ptr + map->ati_tables.AtomRomHeader->usMasterDataTableOffset))->ListOfDataTables;
|
2020-10-10 17:15:54 +02:00
|
|
|
DBG(", MasterDataTables: 0x%llx", (UINTN)map->ati_tables.MasterDataTables);
|
2019-09-03 11:58:42 +02:00
|
|
|
std_vesa_offset = (UINT16) ((ATOM_MASTER_LIST_OF_DATA_TABLES *)map->ati_tables.MasterDataTables)->StandardVESA_Timing;
|
|
|
|
std_vesa = (ATOM_STANDARD_VESA_TIMING *) (map->bios_ptr + std_vesa_offset);
|
2020-10-10 17:15:54 +02:00
|
|
|
DBG(", std_vesa: 0x%llx", (UINTN)std_vesa);
|
2019-09-03 11:58:42 +02:00
|
|
|
|
|
|
|
map->ati_mode_table = (CHAR8 *) &std_vesa->aModeTimings;
|
2020-10-10 17:15:54 +02:00
|
|
|
DBG(", ati_mode_table: 0x%llx", (UINTN)map->ati_mode_table);
|
2019-09-03 11:58:42 +02:00
|
|
|
if (map->ati_mode_table == 0)
|
|
|
|
{
|
|
|
|
DBG("\n Unable to locate the mode table.\n");
|
|
|
|
close_vbios(map);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
map->mode_table_size = std_vesa->sHeader.usStructureSize - sizeof(ATOM_COMMON_TABLE_HEADER);
|
|
|
|
DBG(", mode_table_size: 0x%x", map->mode_table_size);
|
|
|
|
|
|
|
|
if (!detect_ati_bios_type(map)) map->bios = BT_ATI_2;
|
|
|
|
DBG(" %a\n", map->bios == BT_ATI_1 ? "BT_ATI_1" : "BT_ATI_2");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* check if we have NVIDIA
|
|
|
|
*/
|
|
|
|
|
|
|
|
for (i = 0; i < 512; i++)
|
|
|
|
{ // we don't need to look through the whole bios, just the first 512 bytes
|
|
|
|
if (CompareMem(map->bios_ptr+i, nvda_string, 4) == 0)
|
|
|
|
{
|
|
|
|
UINT16 nv_data_table_offset = 0;
|
|
|
|
UINT16 * nv_data_table;
|
|
|
|
NV_VESA_TABLE * std_vesa;
|
|
|
|
DBG(" nVidia");
|
|
|
|
map->bios = BT_NVDA;
|
|
|
|
|
|
|
|
for (j = 0; j < 0x300; j++)
|
|
|
|
{ //We don't need to look for the table in the whole bios, the 768 first bytes only
|
|
|
|
if (CompareMem(map->bios_ptr+j, nvda_pattern, 4)==0)
|
|
|
|
{
|
|
|
|
nv_data_table_offset = *((UINT16*)(map->bios_ptr+j+4));
|
|
|
|
DBG(", nv_data_table_offset: 0x%x", (UINTN)nv_data_table_offset);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nv_data_table = (UINT16 *) (map->bios_ptr + (nv_data_table_offset + OFFSET_TO_VESA_TABLE_INDEX));
|
|
|
|
DBG(", nv_data_table: 0x%p", nv_data_table);
|
|
|
|
std_vesa = (NV_VESA_TABLE *) (map->bios_ptr + *nv_data_table);
|
|
|
|
DBG(", std_vesa: 0x%p", std_vesa);
|
|
|
|
|
|
|
|
map->nv_mode_table = (CHAR8*)std_vesa+sizeof(NV_COMMON_TABLE_HEADER);
|
|
|
|
DBG(", nv_mode_table: 0x%p", map->nv_mode_table);
|
|
|
|
|
|
|
|
if (map->nv_mode_table == 0)
|
|
|
|
{
|
|
|
|
DBG("\n Unable to locate the mode table.\n");
|
|
|
|
close_vbios(map);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
map->mode_table_size = std_vesa->sHeader.usTable_Size;
|
|
|
|
DBG(", mode_table_size: 0x%x\n", map->mode_table_size);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* check if we have Intel
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (*(UINT16*)(map->bios_ptr + 0x44) == 0x8086) {
|
|
|
|
map->bios = BT_INTEL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Figure out where the mode table is
|
|
|
|
*/
|
|
|
|
/* if ((map->bios != BT_ATI_1) && (map->bios != BT_ATI_2) && (map->bios != BT_NVDA))
|
|
|
|
{
|
|
|
|
CHAR8* p = map->bios_ptr + 16;
|
|
|
|
CHAR8* limit = map->bios_ptr + VBIOS_SIZE - (3 * sizeof(vbios_mode));
|
|
|
|
|
|
|
|
DBG(" Other");
|
|
|
|
while (p < limit && map->mode_table == 0)
|
|
|
|
{
|
|
|
|
vbios_mode * mode_ptr = (vbios_mode *) p;
|
|
|
|
|
|
|
|
if (((mode_ptr[0].mode & 0xf0) == 0x30) && ((mode_ptr[1].mode & 0xf0) == 0x30) &&
|
|
|
|
((mode_ptr[2].mode & 0xf0) == 0x30) && ((mode_ptr[3].mode & 0xf0) == 0x30))
|
|
|
|
{
|
|
|
|
map->mode_table = mode_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (map->mode_table == 0)
|
|
|
|
{
|
|
|
|
DBG(", mode table not found");
|
|
|
|
close_vbios(map);
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
DBG(", mode_table: 0x%p", map->mode_table);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Determine size of mode table
|
|
|
|
*/
|
|
|
|
/* if ((map->bios != BT_ATI_1) && (map->bios != BT_ATI_2) && (map->bios != BT_NVDA))
|
|
|
|
{
|
|
|
|
vbios_mode * mode_ptr = map->mode_table;
|
|
|
|
|
|
|
|
while (mode_ptr->mode != 0xff)
|
|
|
|
{
|
|
|
|
map->mode_table_size++;
|
|
|
|
mode_ptr++;
|
|
|
|
}
|
|
|
|
DBG(", mode_table_size: 0x%x", map->mode_table_size);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* Figure out what type of bios we have
|
|
|
|
* order of detection is important
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
if ((map->bios != BT_ATI_1) && (map->bios != BT_ATI_2) && (map->bios != BT_NVDA))
|
|
|
|
{
|
|
|
|
if (detect_bios_type(map, TRUE, sizeof(vbios_modeline_type3)))
|
|
|
|
{
|
|
|
|
map->bios = BT_3;
|
|
|
|
DBG(", bios: BT_3\n");
|
|
|
|
}
|
|
|
|
else if (detect_bios_type(map, TRUE, sizeof(vbios_modeline_type2)))
|
|
|
|
{
|
|
|
|
map->bios = BT_2;
|
|
|
|
DBG(", bios: BT_2\n");
|
|
|
|
}
|
|
|
|
else if (detect_bios_type(map, FALSE, sizeof(vbios_resolution_type1)))
|
|
|
|
{
|
|
|
|
map->bios = BT_1;
|
|
|
|
DBG(", bios: BT_1\n");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DBG(", bios: unknown\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
return map;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID close_vbios(vbios_map * map)
|
|
|
|
{
|
|
|
|
FreePool(map);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
INT32 getMode(edid_mode *mode)
|
|
|
|
{
|
|
|
|
CHAR8* edidInfo = readEDID();
|
|
|
|
|
|
|
|
if(!edidInfo) return 1;
|
|
|
|
//Slice
|
|
|
|
if(!fb_parse_edid((struct EDID *)edidInfo, mode))
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!mode->h_active) return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID gtf_timings(UINT32 x, UINT32 y, UINT32 freq, /* 60, 75, 85 */
|
|
|
|
UINT32 *clock,
|
|
|
|
UINT16 *hsyncstart, UINT16 *hsyncend, UINT16 *hblank,
|
|
|
|
UINT16 *vsyncstart, UINT16 *vsyncend, UINT16 *vblank)
|
|
|
|
{
|
|
|
|
UINT32 hbl, vbl, vfreq;
|
|
|
|
|
|
|
|
vbl = (UINT32)((2 * y) + ((2 * y)+2)/(20000/(11*freq) - 1) + 3) / 2;
|
|
|
|
vfreq = vbl * freq;
|
|
|
|
hbl = 16 * (INT32)((x * (30 - 300000 / vfreq) /
|
|
|
|
+ (70 + 300000 / vfreq) / 8 + 1) / 2);
|
|
|
|
|
|
|
|
/*
|
|
|
|
vbl = (UINT32)(y + (y+1)/(20000.0/(11*freq) - 1) + 1.5);
|
|
|
|
vfreq = vbl * freq;
|
|
|
|
hbl = 16 * (INT32)(x * (30.0 - 300000.0 / vfreq) /
|
|
|
|
+ (70.0 + 300000.0 / vfreq) / 16.0 + 0.5);
|
|
|
|
*/
|
|
|
|
|
|
|
|
*vsyncstart = (UINT16)y;
|
|
|
|
*vsyncend = (UINT16)(y + 3);
|
|
|
|
*vblank = (UINT16)(vbl - 1);
|
|
|
|
*hsyncstart = (UINT16)(x + hbl / 2 - (x + hbl + 50) / 100 * 8 - 1);
|
|
|
|
*hsyncend = (UINT16)(x + hbl / 2 - 1);
|
|
|
|
*hblank = (UINT16)(x + hbl - 1);
|
|
|
|
*clock = (UINT32)((x + hbl) * vfreq / 1000);
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID set_mode(vbios_map * map, /*UINT32 mode,*/ UINT32 x, UINT32 y, UINT32 bp, UINT32 htotal, UINT32 vtotal) {
|
|
|
|
UINT32 xprev, yprev;
|
|
|
|
UINT32 i = 0, j;
|
|
|
|
// patch first available mode
|
|
|
|
|
|
|
|
// for (i=0; i < map->mode_table_size; i++) {
|
|
|
|
// if (map->mode_table[0].mode == mode) {
|
|
|
|
DBG(" Patching: ");
|
|
|
|
switch(map->bios) {
|
|
|
|
case BT_INTEL:
|
|
|
|
{
|
|
|
|
edid_mode mode;
|
|
|
|
UINTN NumReplaces;
|
|
|
|
UINT8* DTD_string = NULL;
|
|
|
|
CHAR8* edidInfo = readEDID();
|
|
|
|
|
|
|
|
DBG("Patch BT_INTEL: ");
|
|
|
|
if (getMode(&mode)) {
|
|
|
|
DBG("have no mode, check your EDID\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ((edidInfo[54] != 0) || (edidInfo[55] != 0) ||
|
|
|
|
(edidInfo[56] != 0) || (edidInfo[58] != 0)) {
|
|
|
|
DTD_string = (UINT8*)&edidInfo[54];
|
|
|
|
} else if ((edidInfo[72] != 0) || (edidInfo[73] != 0) ||
|
|
|
|
(edidInfo[74] != 0) || (edidInfo[76] != 0)) {
|
|
|
|
DTD_string = (UINT8*)&edidInfo[72];
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// NumReplaces = 0;
|
|
|
|
NumReplaces = VideoBiosPatchSearchAndReplace (
|
|
|
|
(UINT8*)(UINTN)VBIOS_START,
|
|
|
|
VBIOS_SIZE,
|
|
|
|
(UINT8*)&DTD_1024[0], 18,
|
|
|
|
DTD_string,
|
|
|
|
-1
|
|
|
|
);
|
2020-04-23 18:05:21 +02:00
|
|
|
DBG(" patched %d time(s)\n", NumReplaces);
|
2019-09-03 11:58:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
case BT_1:
|
|
|
|
{
|
|
|
|
vbios_resolution_type1 * res = map_type1_resolution(map, map->mode_table[i].resolution);
|
|
|
|
|
|
|
|
if (bp) {
|
|
|
|
map->mode_table[i].bits_per_pixel = (UINT8)bp;
|
|
|
|
}
|
|
|
|
|
|
|
|
res->x2 = (htotal?(((htotal-x) >> 8) & 0x0f) : (res->x2 & 0x0f)) | ((x >> 4) & 0xf0);
|
|
|
|
res->x1 = (x & 0xff);
|
|
|
|
|
|
|
|
res->y2 = (vtotal?(((vtotal-y) >> 8) & 0x0f) : (res->y2 & 0x0f)) | ((y >> 4) & 0xf0);
|
|
|
|
res->y1 = (y & 0xff);
|
|
|
|
if (htotal)
|
|
|
|
res->x_total = ((htotal-x) & 0xff);
|
|
|
|
|
|
|
|
if (vtotal)
|
|
|
|
res->y_total = ((vtotal-y) & 0xff);
|
|
|
|
|
|
|
|
DBG("BT_1 patched\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case BT_2:
|
|
|
|
{
|
|
|
|
vbios_resolution_type2 * res = map_type2_resolution(map, map->mode_table[i].resolution);
|
|
|
|
DBG("BT_2");
|
|
|
|
|
|
|
|
res->xchars = (UINT8)(x / 8);
|
|
|
|
res->ychars = (UINT8)(y / 16 - 1);
|
|
|
|
xprev = res->modelines[0].x1;
|
|
|
|
yprev = res->modelines[0].y1;
|
|
|
|
|
|
|
|
for(j=0; j < 3; j++) {
|
|
|
|
vbios_modeline_type2 * modeline = &res->modelines[j];
|
|
|
|
|
|
|
|
if (modeline->x1 == xprev && modeline->y1 == yprev) {
|
|
|
|
modeline->x1 = modeline->x2 = (UINT16)(x-1);
|
|
|
|
modeline->y1 = modeline->y2 = (UINT16)(y-1);
|
|
|
|
|
|
|
|
gtf_timings(x, y, freqs[j], &modeline->clock,
|
|
|
|
&modeline->hsyncstart, &modeline->hsyncend,
|
|
|
|
&modeline->hblank, &modeline->vsyncstart,
|
|
|
|
&modeline->vsyncend, &modeline->vblank);
|
|
|
|
|
|
|
|
if (htotal)
|
|
|
|
modeline->htotal = (UINT16)htotal;
|
|
|
|
else
|
|
|
|
modeline->htotal = modeline->hblank;
|
|
|
|
|
|
|
|
if (vtotal)
|
|
|
|
modeline->vtotal = (UINT16)vtotal;
|
|
|
|
else
|
|
|
|
modeline->vtotal = modeline->vblank;
|
|
|
|
DBG(", modeline %d patched", j);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DBG("\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case BT_3:
|
|
|
|
{
|
|
|
|
vbios_resolution_type3 * res = map_type3_resolution(map, map->mode_table[i].resolution);
|
|
|
|
DBG("BT_3");
|
|
|
|
|
|
|
|
xprev = res->modelines[0].x1;
|
|
|
|
yprev = res->modelines[0].y1;
|
|
|
|
|
|
|
|
for (j=0; j < 3; j++) {
|
|
|
|
vbios_modeline_type3 * modeline = &res->modelines[j];
|
|
|
|
|
|
|
|
if (modeline->x1 == xprev && modeline->y1 == yprev) {
|
|
|
|
modeline->x1 = modeline->x2 = (UINT16)(x-1);
|
|
|
|
modeline->y1 = modeline->y2 = (UINT16)(y-1);
|
|
|
|
|
|
|
|
gtf_timings(x, y, freqs[j], &modeline->clock,
|
|
|
|
&modeline->hsyncstart, &modeline->hsyncend,
|
|
|
|
&modeline->hblank, &modeline->vsyncstart,
|
|
|
|
&modeline->vsyncend, &modeline->vblank);
|
|
|
|
if (htotal)
|
|
|
|
modeline->htotal = (UINT16)htotal;
|
|
|
|
else
|
|
|
|
modeline->htotal = modeline->hblank;
|
|
|
|
if (vtotal)
|
|
|
|
modeline->vtotal = (UINT16)vtotal;
|
|
|
|
else
|
|
|
|
modeline->vtotal = modeline->vblank;
|
|
|
|
|
|
|
|
modeline->timing_h = (UINT16)(y-1);
|
|
|
|
modeline->timing_v = (UINT16)(x-1);
|
|
|
|
DBG(", modeline %d patched", j);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DBG("\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case BT_ATI_1:
|
|
|
|
{
|
|
|
|
edid_mode mode;
|
|
|
|
|
|
|
|
ATOM_MODE_TIMING *mode_timing = (ATOM_MODE_TIMING *) map->ati_mode_table;
|
|
|
|
|
|
|
|
DBG("BT_ATI_1\n");
|
|
|
|
//if (mode.pixel_clock && (mode.h_active == x) && (mode.v_active == y) && !force) {
|
|
|
|
if (!getMode(&mode)) {
|
|
|
|
DBG(" mode 0 (%dx%d) patched to %dx%d\n",
|
|
|
|
mode_timing->usCRTC_H_Disp, mode_timing->usCRTC_V_Disp,
|
|
|
|
mode.h_active, mode.v_active
|
|
|
|
);
|
|
|
|
mode_timing->usCRTC_H_Total = mode.h_active + mode.h_blanking;
|
|
|
|
mode_timing->usCRTC_H_Disp = mode.h_active;
|
|
|
|
mode_timing->usCRTC_H_SyncStart = mode.h_active + mode.h_sync_offset;
|
|
|
|
mode_timing->usCRTC_H_SyncWidth = mode.h_sync_width;
|
|
|
|
|
|
|
|
mode_timing->usCRTC_V_Total = mode.v_active + mode.v_blanking;
|
|
|
|
mode_timing->usCRTC_V_Disp = mode.v_active;
|
|
|
|
mode_timing->usCRTC_V_SyncStart = mode.v_active + mode.v_sync_offset;
|
|
|
|
mode_timing->usCRTC_V_SyncWidth = mode.v_sync_width;
|
|
|
|
|
|
|
|
mode_timing->usPixelClock = mode.pixel_clock;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case BT_ATI_2:
|
|
|
|
{
|
|
|
|
edid_mode mode;
|
|
|
|
|
|
|
|
ATOM_DTD_FORMAT *mode_timing = (ATOM_DTD_FORMAT *) map->ati_mode_table;
|
|
|
|
|
|
|
|
DBG("BT_ATI_2\n");
|
|
|
|
/*if (mode.pixel_clock && (mode.h_active == x) && (mode.v_active == y) && !force) {*/
|
|
|
|
if (!getMode(&mode)) {
|
|
|
|
DBG(" mode 0 (%dx%d) patched to %dx%d\n",
|
|
|
|
mode_timing->usHActive, mode_timing->usVActive,
|
|
|
|
mode.h_active, mode.v_active
|
|
|
|
);
|
|
|
|
mode_timing->usHBlanking_Time = mode.h_blanking;
|
|
|
|
mode_timing->usHActive = mode.h_active;
|
|
|
|
mode_timing->usHSyncOffset = mode.h_sync_offset;
|
|
|
|
mode_timing->usHSyncWidth = mode.h_sync_width;
|
|
|
|
|
|
|
|
mode_timing->usVBlanking_Time = mode.v_blanking;
|
|
|
|
mode_timing->usVActive = mode.v_active;
|
|
|
|
mode_timing->usVSyncOffset = mode.v_sync_offset;
|
|
|
|
mode_timing->usVSyncWidth = mode.v_sync_width;
|
|
|
|
|
|
|
|
mode_timing->usPixClk = mode.pixel_clock;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case BT_NVDA:
|
|
|
|
{
|
|
|
|
edid_mode mode;
|
|
|
|
UINTN NumReplaces;
|
|
|
|
// UINTN NumReplacesTotal;
|
|
|
|
UINTN Index = 0;
|
|
|
|
|
|
|
|
// NV_MODELINE *mode_timing = (NV_MODELINE *) map->nv_mode_table;
|
|
|
|
DBG("BT_NVDA\n");
|
|
|
|
// totally revised on work by pene
|
|
|
|
// http://www.projectosx.com/forum/index.php?showtopic=2562&view=findpost&p=22683
|
|
|
|
|
|
|
|
if (getMode(&mode)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
//Search for desired mode in our matrix
|
|
|
|
for (Index = 0; Index < RESOLUTIONS_NUMBER; Index++) {
|
|
|
|
if ((nvda_res[Index].HRes == mode.h_active) && (nvda_res[Index].VRes == mode.v_active)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (Index == RESOLUTIONS_NUMBER) {
|
|
|
|
DBG("the patch is not ready for the desired resolution\n");
|
|
|
|
break; // not found
|
|
|
|
}
|
|
|
|
|
|
|
|
// NumReplaces = 0;
|
|
|
|
// NumReplacesTotal = 0;
|
|
|
|
NumReplaces = VideoBiosPatchSearchAndReplace (
|
|
|
|
(UINT8*)(UINTN)VBIOS_START,
|
|
|
|
VBIOS_SIZE,
|
|
|
|
(UINT8*)&Sample0[0], 17,
|
|
|
|
(UINT8*)&nvda_key0[Index].Matrix[0],
|
|
|
|
-1
|
|
|
|
);
|
|
|
|
// NumReplacesTotal += NumReplaces;
|
2020-04-23 18:05:21 +02:00
|
|
|
DBG(" patch 0: patched %d time(s)\n", NumReplaces);
|
2019-09-03 11:58:42 +02:00
|
|
|
NumReplaces = VideoBiosPatchSearchAndReplace (
|
|
|
|
(UINT8*)(UINTN)VBIOS_START,
|
|
|
|
VBIOS_SIZE,
|
|
|
|
(UINT8*)&Sample1[0], 9,
|
|
|
|
(UINT8*)&nvda_key1[Index].Matrix[0],
|
|
|
|
-1
|
|
|
|
);
|
|
|
|
// NumReplacesTotal += NumReplaces;
|
2020-04-23 18:05:21 +02:00
|
|
|
DBG(" patch 1: patched %d time(s)\n", NumReplaces);
|
2019-09-03 11:58:42 +02:00
|
|
|
NumReplaces = VideoBiosPatchSearchAndReplace (
|
|
|
|
(UINT8*)(UINTN)VBIOS_START,
|
|
|
|
VBIOS_SIZE,
|
|
|
|
(UINT8*)&Sample2[0], 13,
|
|
|
|
(UINT8*)&nvda_key2[Index].Matrix[0],
|
|
|
|
-1
|
|
|
|
);
|
|
|
|
// NumReplacesTotal += NumReplaces;
|
2020-04-23 18:05:21 +02:00
|
|
|
DBG(" patch 2: patched %d time(s)\n", NumReplaces);
|
2019-09-03 11:58:42 +02:00
|
|
|
NumReplaces = VideoBiosPatchSearchAndReplace (
|
|
|
|
(UINT8*)(UINTN)VBIOS_START,
|
|
|
|
VBIOS_SIZE,
|
|
|
|
(UINT8*)&Sample3[0], 5,
|
|
|
|
(UINT8*)&nvda_key3[Index].Matrix[0],
|
|
|
|
-1
|
|
|
|
);
|
|
|
|
// NumReplacesTotal += NumReplaces;
|
2020-04-23 18:05:21 +02:00
|
|
|
DBG(" patch 3: patched %d time(s)\n", NumReplaces);
|
2019-09-03 11:58:42 +02:00
|
|
|
|
|
|
|
if ((*((UINT8*)(UINTN)(VBIOS_START + 0x34)) & 0x8F) == 0x80 ) {
|
|
|
|
*((UINT8*)(UINTN)(VBIOS_START + 0x34)) |= 0x01;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case BT_UNKNOWN:
|
|
|
|
{
|
|
|
|
DBG("unknown - not patching\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // _RESOLUTION_H_
|