Index: trunk/i386/libsaio/shortatombios.h =================================================================== --- trunk/i386/libsaio/shortatombios.h (revision 0) +++ trunk/i386/libsaio/shortatombios.h (revision 127) @@ -0,0 +1,192 @@ +/****************************************************************************/ +/*Portion I: Definitions shared between VBIOS and Driver */ +/****************************************************************************/ + + +#ifndef _SHORT_ATOMBIOS_H +#define _SHORT_ATOMBIOS_H + +#define ATOM_VERSION_MAJOR 0x00020000 +#define ATOM_VERSION_MINOR 0x00000002 + +#define ATOM_HEADER_VERSION (ATOM_VERSION_MAJOR | ATOM_VERSION_MINOR) + +typedef unsigned char BOOLEAN; +typedef signed char INT8; +typedef unsigned char UINT8; +typedef signed short INT16; +typedef unsigned short UINT16; +typedef signed long INT32; +typedef unsigned long UINT32; +typedef unsigned char CHAR8; +typedef unsigned short CHAR16; +typedef unsigned short USHORT; +typedef unsigned char UCHAR; +typedef unsigned long ULONG; + +#pragma pack(1) /* BIOS data must use byte aligment */ + +/* Define offset to location of ROM header. */ + +#define OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER 0x00000048L +#define OFFSET_TO_ATOM_ROM_IMAGE_SIZE 0x00000002L + +typedef struct _ATOM_COMMON_TABLE_HEADER +{ + USHORT usStructureSize; + UCHAR ucTableFormatRevision; /*Change it when the Parser is not backward compatible */ + UCHAR ucTableContentRevision; /*Change it only when the table needs to change but the firmware */ + /*Image can't be updated, while Driver needs to carry the new table! */ +}ATOM_COMMON_TABLE_HEADER; + +typedef struct _ATOM_ROM_HEADER +{ + ATOM_COMMON_TABLE_HEADER sHeader; + UCHAR uaFirmWareSignature[4]; /*Signature to distinguish between Atombios and non-atombios, + atombios should init it as "ATOM", don't change the position */ + USHORT usBiosRuntimeSegmentAddress; + USHORT usProtectedModeInfoOffset; + USHORT usConfigFilenameOffset; + USHORT usCRC_BlockOffset; + USHORT usBIOS_BootupMessageOffset; + USHORT usInt10Offset; + USHORT usPciBusDevInitCode; + USHORT usIoBaseAddress; + USHORT usSubsystemVendorID; + USHORT usSubsystemID; + USHORT usPCI_InfoOffset; + USHORT usMasterCommandTableOffset; /*Offset for SW to get all command table offsets, Don't change the position */ + USHORT usMasterDataTableOffset; /*Offset for SW to get all data table offsets, Don't change the position */ + UCHAR ucExtendedFunctionCode; + UCHAR ucReserved; +}ATOM_ROM_HEADER; + +/****************************************************************************/ +// Structure used in Data.mtb +/****************************************************************************/ +typedef struct _ATOM_MASTER_LIST_OF_DATA_TABLES +{ + USHORT UtilityPipeLine; // Offest for the utility to get parser info,Don't change this position! + USHORT MultimediaCapabilityInfo; // Only used by MM Lib,latest version 1.1, not configuable from Bios, need to include the table to build Bios + USHORT MultimediaConfigInfo; // Only used by MM Lib,latest version 2.1, not configuable from Bios, need to include the table to build Bios + USHORT StandardVESA_Timing; // Only used by Bios + USHORT FirmwareInfo; // Shared by various SW components,latest version 1.4 + USHORT DAC_Info; // Will be obsolete from R600 + USHORT LVDS_Info; // Shared by various SW components,latest version 1.1 + USHORT TMDS_Info; // Will be obsolete from R600 + USHORT AnalogTV_Info; // Shared by various SW components,latest version 1.1 + USHORT SupportedDevicesInfo; // Will be obsolete from R600 + USHORT GPIO_I2C_Info; // Shared by various SW components,latest version 1.2 will be used from R600 + USHORT VRAM_UsageByFirmware; // Shared by various SW components,latest version 1.3 will be used from R600 + USHORT GPIO_Pin_LUT; // Shared by various SW components,latest version 1.1 + USHORT VESA_ToInternalModeLUT; // Only used by Bios + USHORT ComponentVideoInfo; // Shared by various SW components,latest version 2.1 will be used from R600 + USHORT PowerPlayInfo; // Shared by various SW components,latest version 2.1,new design from R600 + USHORT CompassionateData; // Will be obsolete from R600 + USHORT SaveRestoreInfo; // Only used by Bios + USHORT PPLL_SS_Info; // Shared by various SW components,latest version 1.2, used to call SS_Info, change to new name because of int ASIC SS info + USHORT OemInfo; // Defined and used by external SW, should be obsolete soon + USHORT XTMDS_Info; // Will be obsolete from R600 + USHORT MclkSS_Info; // Shared by various SW components,latest version 1.1, only enabled when ext SS chip is used + USHORT Object_Header; // Shared by various SW components,latest version 1.1 + USHORT IndirectIOAccess; // Only used by Bios,this table position can't change at all!! + USHORT MC_InitParameter; // Only used by command table + USHORT ASIC_VDDC_Info; // Will be obsolete from R600 + USHORT ASIC_InternalSS_Info; // New tabel name from R600, used to be called "ASIC_MVDDC_Info" + USHORT TV_VideoMode; // Only used by command table + USHORT VRAM_Info; // Only used by command table, latest version 1.3 + USHORT MemoryTrainingInfo; // Used for VBIOS and Diag utility for memory training purpose since R600. the new table rev start from 2.1 + USHORT IntegratedSystemInfo; // Shared by various SW components + USHORT ASIC_ProfilingInfo; // New table name from R600, used to be called "ASIC_VDDCI_Info" for pre-R600 + USHORT VoltageObjectInfo; // Shared by various SW components, latest version 1.1 + USHORT PowerSourceInfo; // Shared by various SW components, latest versoin 1.1 +}ATOM_MASTER_LIST_OF_DATA_TABLES; + +typedef struct _ATOM_MASTER_DATA_TABLE +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_MASTER_LIST_OF_DATA_TABLES ListOfDataTables; +}ATOM_MASTER_DATA_TABLE; + +typedef union _ATOM_MODE_MISC_INFO_ACCESS +{ + USHORT usAccess; +}ATOM_MODE_MISC_INFO_ACCESS; + +/****************************************************************************/ +// Structure used in StandardVESA_TimingTable +// AnalogTV_InfoTable +// ComponentVideoInfoTable +/****************************************************************************/ +typedef struct _ATOM_MODE_TIMING +{ + USHORT usCRTC_H_Total; + USHORT usCRTC_H_Disp; + USHORT usCRTC_H_SyncStart; + USHORT usCRTC_H_SyncWidth; + USHORT usCRTC_V_Total; + USHORT usCRTC_V_Disp; + USHORT usCRTC_V_SyncStart; + USHORT usCRTC_V_SyncWidth; + USHORT usPixelClock; //in 10Khz unit + ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo; + USHORT usCRTC_OverscanRight; + USHORT usCRTC_OverscanLeft; + USHORT usCRTC_OverscanBottom; + USHORT usCRTC_OverscanTop; + USHORT usReserve; + UCHAR ucInternalModeNumber; + UCHAR ucRefreshRate; +}ATOM_MODE_TIMING; + +typedef struct _ATOM_DTD_FORMAT +{ + USHORT usPixClk; + USHORT usHActive; + USHORT usHBlanking_Time; + USHORT usVActive; + USHORT usVBlanking_Time; + USHORT usHSyncOffset; + USHORT usHSyncWidth; + USHORT usVSyncOffset; + USHORT usVSyncWidth; + USHORT usImageHSize; + USHORT usImageVSize; + UCHAR ucHBorder; + UCHAR ucVBorder; + ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo; + UCHAR ucInternalModeNumber; + UCHAR ucRefreshRate; +}ATOM_DTD_FORMAT; + +typedef struct _ATOM_LVDS_INFO_V12 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_DTD_FORMAT sLCDTiming; + USHORT usExtInfoTableOffset; + USHORT usSupportedRefreshRate; //Refer to panel info table in ATOMBIOS extension Spec. + USHORT usOffDelayInMs; + UCHAR ucPowerSequenceDigOntoDEin10Ms; + UCHAR ucPowerSequenceDEtoBLOnin10Ms; + UCHAR ucLVDS_Misc; // Bit0:{=0:single, =1:dual},Bit1 {=0:666RGB, =1:888RGB},Bit2:3:{Grey level} + // Bit4:{=0:LDI format for RGB888, =1 FPDI format for RGB888} + // Bit5:{=0:Spatial Dithering disabled;1 Spatial Dithering enabled} + // Bit6:{=0:Temporal Dithering disabled;1 Temporal Dithering enabled} + UCHAR ucPanelDefaultRefreshRate; + UCHAR ucPanelIdentification; + UCHAR ucSS_Id; + USHORT usLCDVenderID; + USHORT usLCDProductID; + UCHAR ucLCDPanel_SpecialHandlingCap; + UCHAR ucPanelInfoSize; // start from ATOM_DTD_FORMAT to end of panel info, include ExtInfoTable + UCHAR ucReserved[2]; +}ATOM_LVDS_INFO_V12; + + +typedef struct _ATOM_STANDARD_VESA_TIMING +{ + ATOM_COMMON_TABLE_HEADER sHeader; + char * aModeTimings; // 16 is not the real array number, just for initial allocation +}ATOM_STANDARD_VESA_TIMING; + +#endif \ No newline at end of file Index: trunk/i386/libsaio/vbe.c =================================================================== --- trunk/i386/libsaio/vbe.c (revision 126) +++ trunk/i386/libsaio/vbe.c (revision 127) @@ -27,6 +27,7 @@ */ #include "libsaio.h" +#include "edid.h" #include "vbe.h" /* @@ -106,6 +107,22 @@ } /* + *EDID/DDC Readings + */ + +int getEDID( void *ddcblock, uint8_t blocksleft ) +{ + bb.intno = 0x10; + bb.eax.rr = FUNC_GET_EDID; + bb.ebx.r.l = SERVICE_READ_EDID; + bb.es = SEG( ddcblock ); + bb.edi.rr = OFF( ddcblock ); + bb.edx.rr = blocksleft; + bios( &bb ); + return( bb.eax.r.h ); +} + +/* * Default GTF parameter values. */ #define kCellGranularity 8.0 // character cell granularity Index: trunk/i386/libsaio/vbe.h =================================================================== --- trunk/i386/libsaio/vbe.h (revision 126) +++ trunk/i386/libsaio/vbe.h (revision 127) @@ -272,6 +272,12 @@ extern int getVBEModeInfo(int mode, void *minfo_p); extern int getVBEDACFormat(unsigned char *format); extern int setVBEDACFormat(unsigned char format); + +/* + * DDC + */ +extern int getEDID(void *ddcblock, uint8_t blocksleft); + extern int setVBEPalette(void *palette); extern int getVBEPalette(void *palette); extern int setVBEMode(unsigned short mode, const VBECRTCInfoBlock *timing); Index: trunk/i386/libsaio/Makefile =================================================================== --- trunk/i386/libsaio/Makefile (revision 126) +++ trunk/i386/libsaio/Makefile (revision 127) @@ -43,7 +43,7 @@ smbios_patcher.o fake_efi.o ext2fs.o \ hpet.o spd.o usb.o pci_setup.o \ device_inject.o nvidia.o ati.o pci_root.o \ - convert.o mem.o + convert.o mem.o 915resolution.o edid.o SAIO_EXTERN_OBJS = console.o Index: trunk/i386/libsaio/915resolution.c =================================================================== --- trunk/i386/libsaio/915resolution.c (revision 0) +++ trunk/i386/libsaio/915resolution.c (revision 127) @@ -0,0 +1,937 @@ + +/* 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. + */ + +#include "libsaio.h" +#include "915resolution.h" +#include "../boot2/graphics.h" + +char * chipset_type_names[] = { + "UNKNOWN", "830", "845G", "855GM", "865G", "915G", "915GM", "945G", "945GM", "945GME", + "946GZ", "955X", "G965", "Q965", "965GM", "975X", + "P35", "X48", "B43", "Q45", "P45", "GM45", "G41", "G31", "G45", "500" +}; + +char * bios_type_names[] = {"UNKNOWN", "TYPE 1", "TYPE 2", "TYPE 3"}; + +int freqs[] = { 60, 75, 85 }; + + +UInt32 get_chipset_id(void) { + outl(0xcf8, 0x80000000); + return inl(0xcfc); +} + +chipset_type get_chipset(UInt32 id) { + chipset_type type; + + switch (id) { + case 0x35758086: + type = CT_830; + break; + + case 0x25608086: + type = CT_845G; + break; + + case 0x35808086: + type = CT_855GM; + break; + + case 0x25708086: + type = CT_865G; + break; + + case 0x25808086: + type = CT_915G; + break; + + case 0x25908086: + type = CT_915GM; + break; + + case 0x27708086: + type = CT_945G; + break; + + case 0x27748086: + type = CT_955X; + break; + + case 0x277c8086: + type = CT_975X; + break; + + case 0x27a08086: + type = CT_945GM; + break; + + case 0x27ac8086: + type = CT_945GME; + break; + + case 0x29708086: + type = CT_946GZ; + break; + + case 0x29a08086: + type = CT_G965; + break; + + case 0x29908086: + type = CT_Q965; + break; + + case 0x2a008086: + type = CT_965GM; + break; + + case 0x29e08086: + type = CT_X48; + break; + + case 0x2a408086: + type = CT_GM45; + break; + + case 0x2e108086: + case 0X2e908086: + type = CT_B43; + break; + + case 0x2e208086: + type = CT_P45; + break; + + case 0x2e308086: + type = CT_G41; + break; + + case 0x29c08086: + type = CT_G31; + break; + + case 0x29208086: + type = CT_G45; + break; + + case 0x81008086: + type = CT_500; + break; + + default: + type = CT_UNKWN; + break; + } + return type; +} + +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; +} + +char detect_bios_type(vbios_map * map, char modeline, int 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; + } + } + + /*printf("r1 = %d r2 = %d\n", r1, r2);*/ + } + + return (r2-r1-6) % entry_size == 0; +} + +char detect_ati_bios_type(vbios_map * map) { + return map->mode_table_size % sizeof(ATOM_MODE_TIMING) == 0; +} + +void close_vbios(vbios_map * map); + +vbios_map * open_vbios(chipset_type forced_chipset) { + UInt32 z; + vbios_map * map = NEW(vbios_map); + for(z=0; zchipset_id = get_chipset_id(); + map->chipset = get_chipset(map->chipset_id); + } + else if (forced_chipset != CT_UNKWN) { + map->chipset = forced_chipset; + } + else { + map->chipset = CT_915GM; + } + + /* + * Map the video bios to memory + */ + + map->bios_ptr = (unsigned char *)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 + *(unsigned short *) (map->bios_ptr + OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER)); + if (strcmp ((char *) map->ati_tables.AtomRomHeader->uaFirmWareSignature, "ATOM") != 0) { + printf("Not an AtomBios Card\n"); + } else { + map->bios = BT_ATI_1; + } + + + /* + * check if we have NVidia + */ + if (map->bios != BT_ATI_1) { + int i = 0; + while (i < 512) { // we don't need to look through the whole bios, just the firs 512 bytes + if ((map->bios_ptr[i] == 'N') + && (map->bios_ptr[i+1] == 'V') + && (map->bios_ptr[i+2] == 'I') + && (map->bios_ptr[i+3] == 'D')) + { + map->bios = BT_NVDA; + break; + } + i++; + } + } + + /* + * check if we have Intel + */ + + /*if (map->chipset == CT_UNKWN && memmem(map->bios_ptr, VBIOS_SIZE, INTEL_SIGNATURE, strlen(INTEL_SIGNATURE))) { + printf( "Intel chipset detected. However, 915resolution was unable to determine the chipset type.\n"); + + printf("Chipset Id: %x\n", map->chipset_id); + + printf("Please report this problem to stomljen@yahoo.com\n"); + + close_vbios(map); + return 0; + }*/ + + /* + * check for others + */ + + if (map->chipset == CT_UNKWN) { + printf("Unknown chipset type and unrecognized bios.\n"); + + printf("915resolution only works with Intel 800/900 series graphic chipsets.\n"); + + printf("Chipset Id: %x\n", map->chipset_id); + close_vbios(map); + return 0; + } + + /* + * Figure out where the mode table is + */ + + if ((map->bios != BT_ATI_1) && (map->bios != BT_NVDA)) + { + unsigned char* p = map->bios_ptr + 16; + unsigned char* limit = map->bios_ptr + VBIOS_SIZE - (3 * sizeof(vbios_mode)); + + 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) { + printf("Unable to locate the mode table.\n"); + printf("Please run the program 'dump_bios' as root and\n"); + printf("email the file 'vbios.dmp' to stomljen@yahoo.com.\n"); + printf("Chipset: %s\n", chipset_type_names[map->chipset]); + close_vbios(map); + return 0; + } + } + else if (map->bios == BT_ATI_1) + { + map->ati_tables.MasterDataTables = (unsigned short *) &((ATOM_MASTER_DATA_TABLE *) (map->bios_ptr + map->ati_tables.AtomRomHeader->usMasterDataTableOffset))->ListOfDataTables; + unsigned short std_vesa_offset = (unsigned short) ((ATOM_MASTER_LIST_OF_DATA_TABLES *)map->ati_tables.MasterDataTables)->StandardVESA_Timing; + ATOM_STANDARD_VESA_TIMING * std_vesa = (ATOM_STANDARD_VESA_TIMING *) (map->bios_ptr + std_vesa_offset); + + map->ati_mode_table = (char *) &std_vesa->aModeTimings; + if (map->ati_mode_table == 0) { + printf("Unable to locate the mode table.\n"); + printf("Please run the program 'dump_bios' as root and\n"); + printf("email the file 'vbios.dmp' to stomljen@yahoo.com.\n"); + printf("Chipset: %s\n", chipset_type_names[map->chipset]); + close_vbios(map); + return 0; + } + map->mode_table_size = std_vesa->sHeader.usStructureSize - sizeof(ATOM_COMMON_TABLE_HEADER); + + if (!detect_ati_bios_type(map)) map->bios = BT_ATI_2; + } + else if (map->bios == BT_NVDA) + { + unsigned short nv_data_table_offset = 0; + unsigned short nv_modeline_2_offset = 0; + unsigned short * nv_data_table; + NV_VESA_TABLE * std_vesa; + + int i = 0; + + while (i < 0x300) { //We don't need to look for the table in the whole bios, the 768 first bytes only + if ((map->bios_ptr[i] == 0x44) + && (map->bios_ptr[i+1] == 0x01) + && (map->bios_ptr[i+2] == 0x04) + && (map->bios_ptr[i+3] == 0x00)) { + nv_data_table_offset = (unsigned short) (map->bios_ptr[i+4] | (map->bios_ptr[i+5] << 8)); + break; + } + i++; + } + + while (i < VBIOS_SIZE) { //We don't know how to locate it other way + if ((map->bios_ptr[i] == 0x00) && (map->bios_ptr[i+1] == 0x04) //this is the first 1024 modeline. + && (map->bios_ptr[i+2] == 0x00) && (map->bios_ptr[i+3] == 0x03) + && (map->bios_ptr[i+4] == 0x80) + && (map->bios_ptr[i+5] == 0x2F) + && (map->bios_ptr[i+6] == 0x10) + && (map->bios_ptr[i+7] == 0x10) + && (map->bios_ptr[i+8] == 0x05)) { + nv_modeline_2_offset = (unsigned short) i; + break; + } + i++; + } + + nv_data_table = (unsigned short *) (map->bios_ptr + (nv_data_table_offset + OFFSET_TO_VESA_TABLE_INDEX)); + std_vesa = (NV_VESA_TABLE *) (map->bios_ptr + *nv_data_table); + + map->nv_mode_table = (char *) std_vesa->sModelines; + if (nv_modeline_2_offset == (VBIOS_SIZE-1) || nv_modeline_2_offset == 0) { + map->nv_mode_table_2 = NULL; + } else { + map->nv_mode_table_2 = (char*) map->bios_ptr + nv_modeline_2_offset; + } + if (map->nv_mode_table == 0) { + printf("Unable to locate the mode table.\n"); + printf("Please run the program 'dump_bios' as root and\n"); + printf("email the file 'vbios.dmp' to stomljen@yahoo.com.\n"); + printf("Chipset: %s\n", chipset_type_names[map->chipset]); + close_vbios(map); + return 0; + } + map->mode_table_size = std_vesa->sHeader.usTable_Size; + } + + + /* + * 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++; + } + } + + /* + * 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; + } + else if (detect_bios_type(map, TRUE, sizeof(vbios_modeline_type2))) { + map->bios = BT_2; + } + else if (detect_bios_type(map, FALSE, sizeof(vbios_resolution_type1))) { + map->bios = BT_1; + } + else { + printf("Unable to determine bios type.\n"); + printf("Please run the program 'dump_bios' as root and\n"); + printf("email the file 'vbios.dmp' to stomljen@yahoo.com.\n"); + + printf("Chipset: %s\n", chipset_type_names[map->chipset]); + printf("Mode Table Offset: $C0000 + $%x\n", ((UInt32)map->mode_table) - ((UInt32)map->bios_ptr)); + + printf("Mode Table Entries: %u\n", map->mode_table_size); + return 0; + } + } + + return map; +} + +void close_vbios(vbios_map * map) { + FREE(map); +} + +void unlock_vbios(vbios_map * map) { + + map->unlocked = TRUE; + + switch (map->chipset) { + case CT_UNKWN: + break; + case CT_830: + case CT_855GM: + outl(0xcf8, 0x8000005a); + map->b1 = inb(0xcfe); + + outl(0xcf8, 0x8000005a); + outb(0xcfe, 0x33); + break; + case CT_845G: + case CT_865G: + case CT_915G: + case CT_915GM: + case CT_945G: + case CT_945GM: + case CT_945GME: + case CT_946GZ: + case CT_955X: + case CT_G965: + case CT_Q965: + case CT_965GM: + case CT_975X: + case CT_P35: + case CT_X48: + case CT_B43: + case CT_Q45: + case CT_P45: + case CT_GM45: + case CT_G41: + case CT_G31: + case CT_G45: + case CT_500: + + outl(0xcf8, 0x80000090); + map->b1 = inb(0xcfd); + map->b2 = inb(0xcfe); + outl(0xcf8, 0x80000090); + outb(0xcfd, 0x33); + outb(0xcfe, 0x33); + break; + } + + #if DEBUG + { + UInt32 t = inl(0xcfc); + printf("unlock PAM: (0x%08x)\n", t); + } +#endif +} + +void relock_vbios(vbios_map * map) { + + map->unlocked = FALSE; + + switch (map->chipset) { + case CT_UNKWN: + break; + case CT_830: + case CT_855GM: + outl(0xcf8, 0x8000005a); + outb(0xcfe, map->b1); + break; + case CT_845G: + case CT_865G: + case CT_915G: + case CT_915GM: + case CT_945G: + case CT_945GM: + case CT_945GME: + case CT_946GZ: + case CT_955X: + case CT_G965: + case CT_Q965: + case CT_965GM: + case CT_975X: + case CT_P35: + case CT_X48: + case CT_B43: + case CT_Q45: + case CT_P45: + case CT_GM45: + case CT_G41: + case CT_G31: + case CT_G45: + case CT_500: + + outl(0xcf8, 0x80000090); + outb(0xcfd, map->b1); + outb(0xcfe, map->b2); + break; + } + + #if DEBUG + { + UInt32 t = inl(0xcfc); + printf("relock PAM: (0x%08x)\n", t); + } + #endif +} + +void save_vbios(vbios_map * map) +{ + map->bios_backup_ptr = malloc(VBIOS_SIZE); + bcopy((const unsigned char *)0xC0000, map->bios_backup_ptr, VBIOS_SIZE); +} + +void restore_vbios(vbios_map * map) +{ + bcopy(map->bios_backup_ptr,(unsigned char *)0xC0000, VBIOS_SIZE); +} + + + +static void gtf_timings(UInt32 x, UInt32 y, UInt32 freq, + unsigned long *clock, + UInt16 *hsyncstart, UInt16 *hsyncend, UInt16 *hblank, + UInt16 *vsyncstart, UInt16 *vsyncend, UInt16 *vblank) +{ + UInt32 hbl, vbl, vfreq; + + vbl = y + (y+1)/(20000/(11*freq) - 1) + 1; + + vfreq = vbl * freq; + hbl = 16 * (int)(x * (30 - 300000 / vfreq) / + + (70 + 300000 / vfreq) / 16 + 0); + + *vsyncstart = y; + *vsyncend = y + 3; + *vblank = vbl - 1; + *hsyncstart = x + hbl / 2 - (x + hbl + 50) / 100 * 8 - 1; + *hsyncend = x + hbl / 2 - 1; + *hblank = x + hbl - 1; + *clock = (x + hbl) * vfreq / 1000; +} + +void cvt_timings(UInt32 x, UInt32 y, UInt32 freq, + unsigned long *clock, + UInt16 *hsyncstart, UInt16 *hsyncend, UInt16 *hblank, + UInt16 *vsyncstart, UInt16 *vsyncend, UInt16 *vblank, bool reduced) +{ + UInt32 hbl, hbp, vbl, vsync, hperiod; + + if (!(y % 3) && ((y * 4 / 3) == x)) + vsync = 4; + else if (!(y % 9) && ((y * 16 / 9) == x)) + vsync = 5; + else if (!(y % 10) && ((y * 16 / 10) == x)) + vsync = 6; + else if (!(y % 4) && ((y * 5 / 4) == x)) + vsync = 7; + else if (!(y % 9) && ((y * 15 / 9) == x)) + vsync = 7; + else /* Custom */ + vsync = 10; + + if (!reduced) { + hperiod = (1000000/freq - 550) / (y + 3); + vbl = y + (550/hperiod) + 3; + hbp = 30 - ((300*hperiod)/1000); + hbl = (x * hbp) / (100 - hbp); + + *vsyncstart = y + 6; + *vsyncend = *vsyncstart + vsync; + *vblank = vbl - 1; + *hsyncstart = x + hbl / 2 - (x + hbl + 50) / 100 * 8 - 1; + *hsyncend = x + hbl / 2 - 1; + *hblank = x + hbl - 1; + + } else { + hperiod = (1000000/freq - 460) / y; + vbl = y + 460/hperiod + 1; + hbl = 160; + + *vsyncstart = y + 3; + *vsyncend = *vsyncstart + vsync; + *vblank = vbl - 1; + *hsyncstart = x + hbl / 2 - 32; + *hsyncend = x + hbl / 2 - 1; + *hblank = x + hbl - 1; + + } + *clock = (x + hbl) * 1000 / hperiod; +} + +void set_mode(vbios_map * map, 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) { + switch(map->bios) { + 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 = 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); + } + break; + case BT_2: + { + vbios_resolution_type2 * res = map_type2_resolution(map, map->mode_table[i].resolution); + + res->xchars = x / 8; + res->ychars = 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 = x-1; + modeline->y1 = modeline->y2 = 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 = htotal; + else + modeline->htotal = modeline->hblank; + + if (vtotal) + modeline->vtotal = vtotal; + else + modeline->vtotal = modeline->vblank; + } + } + } + break; + case BT_3: + { + vbios_resolution_type3 * res = map_type3_resolution(map, map->mode_table[i].resolution); + + 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 = x-1; + modeline->y1 = modeline->y2 = 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 = htotal; + else + modeline->htotal = modeline->hblank; + if (vtotal) + modeline->vtotal = vtotal; + else + modeline->vtotal = modeline->vblank; + + modeline->timing_h = y-1; + modeline->timing_v = x-1; + } + } + } + break; + case BT_ATI_1: + { + edid_mode mode; + VBEModeInfoBlock minfo; + unsigned short mode_n; + unsigned short vesaVersion; + + ATOM_MODE_TIMING *mode_timing = (ATOM_MODE_TIMING *) map->ati_mode_table; + + mode_n = getVESAModeWithProperties( x, y, 32, maColorModeBit | + maModeIsSupportedBit | + maGraphicsModeBit | + maLinearFrameBufferAvailBit, + 0, + &minfo, &vesaVersion ); + + if ( mode_n == modeEndOfList ) + { + minfo.XResolution = 1024; + minfo.YResolution = 768; + } + + + int m_status = getMode(&mode); + + if (m_status || (mode.h_active != x)) { + vbios_modeline_type2 * modeline = malloc(sizeof(vbios_modeline_type2)); + bzero(modeline, sizeof(vbios_modeline_type2)); + + cvt_timings(x, y, 60, &modeline->clock, + &modeline->hsyncstart, &modeline->hsyncend, + &modeline->hblank, &modeline->vsyncstart, + &modeline->vsyncend, &modeline->vblank, FALSE); + + mode.pixel_clock = modeline->clock /10; + mode.h_active = x; + mode.h_sync_offset = modeline->hsyncstart - x; + mode.h_sync_width = modeline->hsyncend - modeline->hsyncstart; + mode.h_blanking = modeline->hblank - x; + mode.v_active = y; + mode.v_sync_offset = modeline->vsyncstart - y; + mode.v_sync_width = modeline->vsyncend - modeline->vsyncstart; + mode.v_blanking = modeline->vblank - y; + + free(modeline); + m_status = 0; + } + + if (!m_status) { + while (i < (map->mode_table_size / sizeof(ATOM_MODE_TIMING))) + { + if (mode_timing[i].usCRTC_H_Disp == minfo.XResolution) { + mode_timing[i].usCRTC_H_Total = mode.h_active + mode.h_blanking; + mode_timing[i].usCRTC_H_Disp = mode.h_active; + mode_timing[i].usCRTC_H_SyncStart = mode.h_active + mode.h_sync_offset; + mode_timing[i].usCRTC_H_SyncWidth = mode.h_sync_width; + + mode_timing[i].usCRTC_V_Total = mode.v_active + mode.v_blanking; + mode_timing[i].usCRTC_V_Disp = mode.v_active; + mode_timing[i].usCRTC_V_SyncStart = mode.v_active + mode.v_sync_offset; + mode_timing[i].usCRTC_V_SyncWidth = mode.v_sync_width; + + mode_timing[i].usPixelClock = mode.pixel_clock; + } + i++; + } + } + } + break; + case BT_ATI_2: + { + edid_mode mode; + VBEModeInfoBlock minfo; + unsigned short mode_n; + unsigned short vesaVersion; + + ATOM_DTD_FORMAT *mode_timing = (ATOM_DTD_FORMAT *) map->ati_mode_table; + + mode_n = getVESAModeWithProperties( x, y, 32, maColorModeBit | + maModeIsSupportedBit | + maGraphicsModeBit | + maLinearFrameBufferAvailBit, + 0, + &minfo, &vesaVersion ); + + if ( mode_n == modeEndOfList ) + { + minfo.XResolution = 1024; + minfo.YResolution = 768; + } + + + int m_status = getMode(&mode); + + if (m_status || (mode.h_active != x)) { + vbios_modeline_type2 * modeline = malloc(sizeof(vbios_modeline_type2)); + bzero(modeline, sizeof(vbios_modeline_type2)); + + cvt_timings(x, y, 60, &modeline->clock, + &modeline->hsyncstart, &modeline->hsyncend, + &modeline->hblank, &modeline->vsyncstart, + &modeline->vsyncend, &modeline->vblank, FALSE); + + mode.pixel_clock = modeline->clock /10; + mode.h_active = x; + mode.h_sync_offset = modeline->hsyncstart - x; + mode.h_sync_width = modeline->hsyncend - modeline->hsyncstart; + mode.h_blanking = modeline->hblank - x; + mode.v_active = y; + mode.v_sync_offset = modeline->vsyncstart - y; + mode.v_sync_width = modeline->vsyncend - modeline->vsyncstart; + mode.v_blanking = modeline->vblank - y; + + free(modeline); + m_status = 0; + } + + if (!m_status) { + while (i < (map->mode_table_size / sizeof(ATOM_DTD_FORMAT))) + { + if (mode_timing[i].usHActive == minfo.XResolution) { + + mode_timing[i].usHBlanking_Time = mode.h_blanking; + mode_timing[i].usHActive = mode.h_active; + mode_timing[i].usHSyncOffset = mode.h_sync_offset; + mode_timing[i].usHSyncWidth = mode.h_sync_width; + + mode_timing[i].usVBlanking_Time = mode.v_blanking; + mode_timing[i].usVActive = mode.v_active; + mode_timing[i].usVSyncOffset = mode.v_sync_offset; + mode_timing[i].usVSyncWidth = mode.v_sync_width; + + mode_timing[i].usPixClk = mode.pixel_clock; + } + i++; + } + } + + } + break; + case BT_NVDA: + { + s_aspect aspect_ratio; + /* + * Get the aspect ratio for the requested mode + */ + if ((y * 16 / 9) == x) { + aspect_ratio.width = 16; + aspect_ratio.height = 9; + } else if ((y * 16 / 10) == x) { + aspect_ratio.width = 16; + aspect_ratio.height = 10; + } else if ((y * 5 / 4) == x) { + aspect_ratio.width = 5; + aspect_ratio.height = 4; + } else if ((y * 15 / 9) == x) { + aspect_ratio.width = 15; + aspect_ratio.height = 9; + } else { + aspect_ratio.width = 4; + aspect_ratio.height = 3; + } + + NV_MODELINE *mode_timing = (NV_MODELINE *) map->nv_mode_table; + NV_MODELINE_2 *mode_timing_2 = (NV_MODELINE_2 *) map->nv_mode_table_2; + + i = 0; + if (mode_timing_2[i].h_disp == 0x140) { //From 320x200 mode. + while (mode_timing_2[i].h_disp <= 0x800) { + + vbios_modeline_type2 * modeliner = malloc(sizeof(vbios_modeline_type2)); + bzero(modeliner, sizeof(vbios_modeline_type2)); + + x = mode_timing_2[i].h_disp; + y = x * aspect_ratio.height / aspect_ratio.width; + + cvt_timings(x, y, 60, &modeliner->clock, + &modeliner->hsyncstart, &modeliner->hsyncend, + &modeliner->hblank, &modeliner->vsyncstart, + &modeliner->vsyncend, &modeliner->vblank, TRUE); + + mode_timing_2[i].h_disp = x; + mode_timing_2[i].v_disp = y; + mode_timing_2[i].h_blank = modeliner->hblank - x; + mode_timing_2[i].h_syncoffset = modeliner->hsyncstart - x; + mode_timing_2[i].h_syncwidth = modeliner->hsyncend - modeliner->hsyncstart; + mode_timing_2[i].v_blank = modeliner->vblank - y; + i++; + free(modeliner); + } + } + i = 0; + + while ((mode_timing[i].reserved3 & 0xff) == 0xff) { + x = mode_timing[i].usH_Active; + y = x * aspect_ratio.height / aspect_ratio.width; + + vbios_modeline_type2 * modeliner = malloc(sizeof(vbios_modeline_type2)); + bzero(modeliner, sizeof(vbios_modeline_type2)); + + cvt_timings(x, y, 60, &modeliner->clock, + &modeliner->hsyncstart, &modeliner->hsyncend, + &modeliner->hblank, &modeliner->vsyncstart, + &modeliner->vsyncend, &modeliner->vblank, FALSE); + + mode_timing[i].usH_Total = x + modeliner->hblank; + mode_timing[i].usH_Active = x; + mode_timing[i].usH_Active_minus_One = x - 1; + mode_timing[i].usH_Active_minus_One_ = x - 1; + mode_timing[i].usH_Active = y; + mode_timing[i].usH_SyncStart = modeliner->hsyncstart; + mode_timing[i].usH_SyncEnd = modeliner->hsyncend; + + mode_timing[i].usV_Total = y + modeliner->vblank; + mode_timing[i].usV_Active = y; + mode_timing[i].usV_Active_minus_One = y - 1; + mode_timing[i].usV_Active_minus_One_ = y - 1; + mode_timing[i].usV_SyncStart = modeliner->vsyncend; + mode_timing[i].usV_SyncEnd = modeliner->vsyncend; + + mode_timing[i].usPixel_Clock = modeliner->clock; + + i++; + } + } + + break; + case BT_UNKWN: + break; + } +// } +// } +} + Index: trunk/i386/libsaio/edid.c =================================================================== --- trunk/i386/libsaio/edid.c (revision 0) +++ trunk/i386/libsaio/edid.c (revision 127) @@ -0,0 +1,161 @@ +/* + * edid.c + * + * + * Created by Evan Lojewski on 12/1/09. + * Copyright 2009. All rights reserved. + * + */ + + +#include "libsaio.h" +#include "edid.h" +#include "vbe.h" +#include "bootstruct.h" +//#include "graphics.h" + +//static biosBuf_t bb; + +UInt32 xResolution = 0; +UInt32 yResolution = 0; +UInt32 bpResolution = 0; + + +void getResolution(UInt32* x, UInt32* y, UInt32* bp) +{ + unsigned char* edidInfo = readEDID(); + + if(!edidInfo) { + xResolution = 1024; + yResolution = 768; + bpResolution = 32; + + free( edidInfo ); + } else { + // TODO: check *all* resolutions reported and eithe ruse the highest, or the native resolution (if there is a flag for that) + xResolution = edidInfo[56] | ((edidInfo[58] & 0xF0) << 4); + yResolution = edidInfo[59] | ((edidInfo[61] & 0xF0) << 4); + + bpResolution = 32; // assume 32bits + + free( edidInfo ); + } + + if (!xResolution) xResolution = 1024; + if (!yResolution) yResolution = 768; + + *x = xResolution; + *y = yResolution; + *bp = bpResolution; + +} + +int getMode(edid_mode *mode) +{ + unsigned char* edidInfo = readEDID(); + + if(!edidInfo) return 1; + + mode->pixel_clock = (edidInfo[55] << 8) | edidInfo[54]; + mode->h_active = edidInfo[56] | ((edidInfo[58] & 0xF0) << 4); + mode->h_blanking = ((edidInfo[58] & 0x0F) << 8) | edidInfo[57]; + mode->v_active = edidInfo[59] | ((edidInfo[61] & 0xF0) << 4); + mode->v_blanking = ((edidInfo[61] & 0x0F) << 8) | edidInfo[60]; + mode->h_sync_offset = ((edidInfo[65] & 0xC0) >> 2) | edidInfo[62]; + mode->h_sync_width = (edidInfo[65] & 0x30) | edidInfo[63]; + mode->v_sync_offset = (edidInfo[65] & 0x0C) | ((edidInfo[64] & 0x0C) >> 2); + mode->v_sync_width = ((edidInfo[65] & 0x3) << 2) | (edidInfo[64] & 0x03); + + + free( edidInfo ); + + if(!mode->h_active) return 1; + + return 0; + +} + +unsigned char* readEDID() +{ + SInt16 last_reported = -1; + UInt8 edidInfo[EDID_BLOCK_SIZE]; + + //UInt8 pointer; + + UInt8 header1[] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}; + UInt8 header2[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + int status; + unsigned int blocks_left = 1; + + do + { + // TODO: This currently only retrieves the *last* block, make the block buffer expand as needed / calculated from the first block + + bzero( edidInfo, EDID_BLOCK_SIZE); + + status = getEDID(edidInfo, blocks_left); + + //printf("Buffer location: 0x%X\n", SEG(buffer) << 16 | OFF(buffer)); + + /* + int j, i; + for (j = 0; j < 8; j++) { + for(i = 0; i < 16; i++) printf("0x%X ", ebiosInfo[((i+1) * (j + 1)) - 1]); + + } + printf("\n"); + */ + + if(status == 0) + { + //if( edidInfo[0] == 0x00 || edidInfo[0] == 0xFF) + if((memcmp(edidInfo, header1, sizeof(header1)) != 0) || + (memcmp(edidInfo, header2, sizeof(header2)) != 0) ) + { + blocks_left--; + int reported = edidInfo[ EDID_V1_BLOCKS_TO_GO_OFFSET ]; + + if ( reported > blocks_left ) + { + + printf("EDID claims %d more blocks left\n", reported); + } + + if ( (last_reported <= reported && last_reported != -1) + || reported == 0xff + /* 0xff frequently comes up in corrupt edids */ + //|| reported == MAGIC + ) + { + printf("Last reported %d\n", last_reported); + printf( "EDID blocks left is wrong.\n" + "Your EDID is probably invalid.\n"); + return 0; + } + else + { + //printf("Reading EDID block\n"); + //printf("H Active = %d", ebiosInfo[56] | ((ebiosInfo[58] & 0xF0) << 4) ); + //printf("V Active = %d", ebiosInfo[59] | ((ebiosInfo[61] & 0xF0) << 4) ); + + last_reported = reported; + blocks_left = reported; + } + } + else + { + printf("Invalid block %d\n", blocks_left); + printf("Header1 = %d", memcmp(edidInfo, header1, sizeof(header1)) ); + printf("Header2 = %d", memcmp(edidInfo, header2, sizeof(header2)) ); + return 0; + } + } else return 0; + + blocks_left = 0; + } while(blocks_left); + + UInt8* ret = malloc(sizeof(edidInfo)); + memcpy(ret, edidInfo, sizeof(edidInfo)); + return (ret); +} Index: trunk/i386/libsaio/915resolution.h =================================================================== --- trunk/i386/libsaio/915resolution.h (revision 0) +++ trunk/i386/libsaio/915resolution.h (revision 127) @@ -0,0 +1,219 @@ + +/* 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. + */ +#ifndef __915_RESOLUTION_H +#define __915_RESOLUTION_H + +#include "shortatombios.h" +#include "edid.h" + +#define NEW(a) ((a *)(malloc(sizeof(a)))) +#define FREE(a) (free(a)) + +#define VBIOS_START 0xc0000 +#define VBIOS_SIZE 0x10000 + +#define FALSE 0 +#define TRUE 1 + +#define MODE_TABLE_OFFSET_845G 617 + + +#define ATI_SIGNATURE1 "ATI MOBILITY RADEON" +#define ATI_SIGNATURE2 "ATI Technologies Inc" +#define NVIDIA_SIGNATURE "NVIDIA Corp" +#define INTEL_SIGNATURE "Intel Corp" + +typedef struct { + unsigned char width; + unsigned char height; +} s_aspect; + +/* + * NVidia Defines and structures + */ + +#define OFFSET_TO_VESA_TABLE_INDEX 2 + +typedef struct { + unsigned char ucTable_Major; + unsigned char ucTable_Minor; + unsigned char ucTable_Rev; + unsigned short usTable_Size; +} NV_COMMON_TABLE_HEADER; + +typedef struct { + unsigned short usPixel_Clock; + unsigned short usH_Active; + unsigned short usH_Active_minus_One; + unsigned short reserved1; + unsigned short usH_Active_minus_One_; + unsigned short usH_SyncStart; + unsigned short usH_SyncEnd; + unsigned short usH_Total; + unsigned short usV_Active; + unsigned short usV_Active_minus_One; + unsigned short reserved2; + unsigned short usV_Active_minus_One_; + unsigned short usV_SyncStart; + unsigned short usV_SyncEnd; + unsigned short usV_Total; + unsigned short reserved3; +} NV_MODELINE; + +typedef struct { + unsigned short h_disp; + unsigned short v_disp; + unsigned char h_blank; + unsigned char h_syncoffset; + unsigned char h_syncwidth; + unsigned char v_blank; + unsigned char v_syncwidth; +} NV_MODELINE_2; + +typedef struct { + NV_COMMON_TABLE_HEADER sHeader; + NV_MODELINE * sModelines; +} NV_VESA_TABLE; + +/*---*/ + + +typedef enum { + CT_UNKWN, CT_830, CT_845G, CT_855GM, CT_865G, + CT_915G, CT_915GM, CT_945G, CT_945GM, CT_945GME, CT_946GZ, + CT_955X, CT_G965, CT_Q965, CT_965GM, CT_975X, + CT_P35, CT_X48, CT_B43, CT_Q45, CT_P45, + CT_GM45, CT_G41, CT_G31, CT_G45, CT_500 +} chipset_type; + + +typedef enum { + BT_UNKWN, BT_1, BT_2, BT_3, BT_ATI_1, BT_ATI_2, BT_NVDA +} bios_type; + +typedef struct { + unsigned char *base; + ATOM_ROM_HEADER *AtomRomHeader; + unsigned short *MasterCommandTables; + unsigned short *MasterDataTables; +} bios_tables_t; + +typedef struct { + UInt8 mode; + UInt8 bits_per_pixel; + UInt16 resolution; + UInt8 unknown; +} __attribute__((packed)) vbios_mode; + +typedef struct { + UInt8 unknow1[2]; + UInt8 x1; + UInt8 x_total; + UInt8 x2; + UInt8 y1; + UInt8 y_total; + UInt8 y2; +} __attribute__((packed)) vbios_resolution_type1; + +typedef struct { + unsigned long clock; + + UInt16 x1; + UInt16 htotal; + UInt16 x2; + UInt16 hblank; + UInt16 hsyncstart; + UInt16 hsyncend; + UInt16 y1; + UInt16 vtotal; + UInt16 y2; + UInt16 vblank; + UInt16 vsyncstart; + UInt16 vsyncend; +} __attribute__((packed)) vbios_modeline_type2; + +typedef struct { + UInt8 xchars; + UInt8 ychars; + UInt8 unknown[4]; + + vbios_modeline_type2 modelines[]; +} __attribute__((packed)) vbios_resolution_type2; + +typedef struct { + unsigned long clock; + + UInt16 x1; + UInt16 htotal; + UInt16 x2; + UInt16 hblank; + UInt16 hsyncstart; + UInt16 hsyncend; + + UInt16 y1; + UInt16 vtotal; + UInt16 y2; + UInt16 vblank; + UInt16 vsyncstart; + UInt16 vsyncend; + + UInt16 timing_h; + UInt16 timing_v; + + UInt8 unknown[6]; +} __attribute__((packed)) vbios_modeline_type3; + +typedef struct { + unsigned char unknown[6]; + + vbios_modeline_type3 modelines[]; +} __attribute__((packed)) vbios_resolution_type3; + +typedef struct { + UInt32 chipset_id; + chipset_type chipset; + bios_type bios; + + bios_tables_t ati_tables; + + UInt32 bios_fd; + unsigned char* bios_backup_ptr; + unsigned char* bios_ptr; + + vbios_mode * mode_table; + char * ati_mode_table; + char * nv_mode_table; + char * nv_mode_table_2; + + UInt32 mode_table_size; + UInt8 b1, b2; + + UInt8 unlocked; +} vbios_map; + + + +void display_map_info(vbios_map*); +vbios_map * open_vbios(chipset_type); +void close_vbios (vbios_map*); +void unlock_vbios(vbios_map*); +void relock_vbios(vbios_map*); +void save_vbios(vbios_map*); +void restore_vbios(vbios_map*); +void set_mode(vbios_map*, UInt32, UInt32, UInt32, UInt32, UInt32); +void list_modes(vbios_map *map, UInt32 raw); + +#endif Index: trunk/i386/libsaio/edid.h =================================================================== --- trunk/i386/libsaio/edid.h (revision 0) +++ trunk/i386/libsaio/edid.h (revision 127) @@ -0,0 +1,39 @@ +/* + * edid.h + * + * + * Created by Evan Lojewski on 12/1/09. + * Copyright 2009. All rights reserved. + * + */ + +#ifndef _EDID_H +#define _EDID_H + +#define EDID_BLOCK_SIZE 128 +#define EDID_V1_BLOCKS_TO_GO_OFFSET 126 + +#define SERVICE_REPORT_DDC 0 +#define SERVICE_READ_EDID 1 +#define SERVICE_LAST 1 // Read VDIF has been removed from the spec. + +#define FUNC_GET_EDID 0x4F15 + +typedef struct _edid_mode { + unsigned short pixel_clock; + unsigned short h_active; + unsigned short h_blanking; + unsigned short v_active; + unsigned short v_blanking; + unsigned short h_sync_offset; + unsigned short h_sync_width; + unsigned short v_sync_offset; + unsigned short v_sync_width; +}edid_mode; + + +unsigned char* readEDID(); +void getResolution(UInt32* x, UInt32* y, UInt32* bp); +int getMode(edid_mode* mode); + +#endif \ No newline at end of file Index: trunk/i386/boot2/graphics.c =================================================================== --- trunk/i386/boot2/graphics.c (revision 126) +++ trunk/i386/boot2/graphics.c (revision 127) @@ -180,7 +180,7 @@ // Return the VESA mode that matches the properties specified. // If a mode is not found, then return the "best" available mode. -static unsigned short +unsigned short getVESAModeWithProperties( unsigned short width, unsigned short height, unsigned char bitsPerPixel, @@ -1030,7 +1030,7 @@ //========================================================================== // getNumberArrayFromProperty -static int +int getNumberArrayFromProperty( const char * propKey, unsigned long numbers[], unsigned long maxArrayCount ) Index: trunk/i386/boot2/boot.c =================================================================== --- trunk/i386/boot2/boot.c (revision 126) +++ trunk/i386/boot2/boot.c (revision 127) @@ -58,6 +58,8 @@ #include "ramdisk.h" #include "gui.h" #include "platform.h" +#include "edid.h" +#include "915resolution.h" long gBootMode; /* defaults to 0 == kBootModeNormal */ bool gOverrideKernel; @@ -78,6 +80,7 @@ BVRef menuBVR; BVRef bvChain; bool useGUI; +bool autoResolution; //static void selectBiosDevice(void); static unsigned long Adler32(unsigned char *buffer, long length); @@ -128,10 +131,14 @@ //========================================================================== // execKernel - Load the kernel image (mach-o) and jump to its entry point. -static int ExecKernel(void *binary) +static int ExecKernel(void *binary, vbios_map *map) { entry_t kernelEntry; int ret; + + UInt32 params[4]; + int count; + params[3] = 0; bootArgs->kaddr = bootArgs->ksize = 0; @@ -158,9 +165,39 @@ printf("Errors encountered while starting up the computer.\n"); printf("Pausing %d seconds...\n", kBootErrorTimeout); sleep(kBootErrorTimeout); - } + } + + //if the vbios patch have been applied retore it before performing fake efi stuff + if (autoResolution == TRUE) { + unlock_vbios(map); + restore_vbios(map); + relock_vbios(map); + } setupFakeEfi(); + + //Reapply the vbios patch before setting mode for boot graphics + if (autoResolution == TRUE) { + count = getNumberArrayFromProperty(kGraphicsModeKey, params, 4); + if ( count < 3 ) { + getResolution(¶ms[0], ¶ms[1], ¶ms[2]); + } + else + { + if ( params[2] == 256 ) params[2] = 8; + if ( params[2] == 555 ) params[2] = 16; + if ( params[2] == 888 ) params[2] = 32; + } + + if (params[0]!=0 && params[1]!=0) { + + unlock_vbios(map); + + set_mode(map, params[0], params[1], params[2], 0, 0); + + relock_vbios(map); + } + } verbose("Starting Darwin %s\n",( archCpuType == CPU_TYPE_I386 ) ? "x86" : "x86_64"); @@ -189,6 +226,14 @@ else drawBootGraphics(); + //Boot Graphis are set finalize and free vbios patch structures + if (autoResolution == TRUE) { + unlock_vbios(map); + restore_vbios(map); + relock_vbios(map); + close_vbios(map); + } + finalizeBootStruct(); // Jump to kernel's entry point. There's no going back now. @@ -316,9 +361,54 @@ getc(); #endif - useGUI = true; - // Override useGUI default - getBoolForKey(kGUIKey, &useGUI, &bootInfo->bootConfig); + + useGUI = TRUE; + // Override useGUI default + getBoolForKey(kGUIKey, &useGUI, &bootInfo->bootConfig); + + // Before initGui, patch the video bios with the correct resolution + + UInt32 params[4]; + int count; + params[3] = 0; + vbios_map * map = open_vbios(CT_UNKWN); + + autoResolution = TRUE; + // Override AutoResolution default + getBoolForKey(kAutoResolutionKey, &autoResolution, &bootInfo->bootConfig); + + if (autoResolution == TRUE) { + count = getNumberArrayFromProperty(kGraphicsModeKey, params, 4); + if ( count < 3 ) + getResolution(¶ms[0], ¶ms[1], ¶ms[2]); + else + { + if ( params[2] == 256 ) params[2] = 8; + if ( params[2] == 555 ) params[2] = 16; + if ( params[2] == 888 ) params[2] = 32; + } + + if (params[0]!=0 && params[1]!=0) { + vbios_map * map = open_vbios(CT_UNKWN); + + unlock_vbios(map); + + save_vbios(map); + + set_mode(map, params[0], params[1], params[2], 0, 0); + + relock_vbios(map); + + verbose("Patched resolution mode to %dx%d.\n", params[0], params[1]); + } + } + + + + + + + if (useGUI) { /* XXX AsereBLN handle error */ initGUI(); @@ -572,7 +662,7 @@ } } else { /* Won't return if successful. */ - ret = ExecKernel(binary); + ret = ExecKernel(binary, map); } } Index: trunk/i386/boot2/graphics.h =================================================================== --- trunk/i386/boot2/graphics.h (revision 126) +++ trunk/i386/boot2/graphics.h (revision 127) @@ -10,6 +10,7 @@ #include "boot.h" #include "bootstruct.h" #include "graphic_utils.h" +#include "vbe.h" #ifndef __BOOT_GRAPHICS_H @@ -37,9 +38,21 @@ int loadEmbeddedPngImage(uint8_t *pngData, int pngSize, uint16_t *width, uint16_t *height, uint8_t **imageData); +int getNumberArrayFromProperty( const char * propKey, + unsigned long numbers[], + unsigned long maxArrayCount ); + char *getVBEInfoString(); char *getVBEModeInfoString(); +unsigned short getVESAModeWithProperties( unsigned short width, + unsigned short height, + unsigned char bitsPerPixel, + unsigned short attributesSet, + unsigned short attributesClear, + VBEModeInfoBlock * outModeInfo, + unsigned short * vesaVersion ); + void getGraphicModeParams(unsigned long params[]); #endif /* !__BOOT_GRAPHICS_H */ Index: trunk/i386/boot2/boot.h =================================================================== --- trunk/i386/boot2/boot.h (revision 126) +++ trunk/i386/boot2/boot.h (revision 127) @@ -56,6 +56,7 @@ #define kInsantMenuKey "Instant Menu" #define kDefaultKernel "mach_kernel" #define kGUIKey "GUI" +#define kAutoResolutionKey "AutoResolution" #define kBootBannerKey "Boot Banner" #define kWaitForKeypressKey "Wait" /* AsereBLN: added the other keys */ @@ -121,6 +122,7 @@ extern bool gEnableCDROMRescan; extern bool gScanSingleDrive; extern bool useGUI; +extern bool autoResolution; /* * Boot Modes Index: trunk/i386/boot2/gui.c =================================================================== --- trunk/i386/boot2/gui.c (revision 126) +++ trunk/i386/boot2/gui.c (revision 127) @@ -11,6 +11,7 @@ #include "gui.h" #include "appleboot.h" #include "vers.h" +#include "edid.h" #define THEME_NAME_DEFAULT "Default" static const char *theme_name = THEME_NAME_DEFAULT; @@ -556,7 +557,7 @@ int initGUI(void) { - int val; + //int val; #ifdef EMBED_THEME config_file_t *config; @@ -578,12 +579,12 @@ } #endif // parse display size parameters - if (getIntForKey("screen_width", &val, &bootInfo->themeConfig)) { + /*if (getIntForKey("screen_width", &val, &bootInfo->themeConfig)) { screen_params[0] = val; } if (getIntForKey("screen_height", &val, &bootInfo->themeConfig)) { screen_params[1] = val; - } + }*/ screen_params[2] = 32; // Initalizing GUI strucutre. @@ -1697,17 +1698,30 @@ loadBootGraphics(); } - // parse screen size parameters - if (getIntForKey("boot_width", &pos, &bootInfo->themeConfig)) { - screen_params[0] = pos; - } else { - screen_params[0] = DEFAULT_SCREEN_WIDTH; - } - if (getIntForKey("boot_height", &pos, &bootInfo->themeConfig)) { - screen_params[1] = pos; - } else { - screen_params[1] = DEFAULT_SCREEN_HEIGHT; - } + if (autoResolution = FALSE) { + VBEModeInfoBlock minfo; + unsigned short mode_n; + unsigned short vesaVersion; + + mode_n = getVESAModeWithProperties( screen_params[0], screen_params[1], 32, maColorModeBit | + maModeIsSupportedBit | + maGraphicsModeBit | + maLinearFrameBufferAvailBit, + 0, + &minfo, &vesaVersion ); + } else { + // parse screen size parameters + if(getIntForKey("boot_width", &pos, &bootInfo->themeConfig)) + screen_params[0] = pos; + else + screen_params[0] = DEFAULT_SCREEN_WIDTH; + + if(getIntForKey("boot_height", &pos, &bootInfo->themeConfig)) + screen_params[1] = pos; + else + screen_params[1] = DEFAULT_SCREEN_HEIGHT; + } + screen_params[2] = 32; gui.screen.width = screen_params[0];