1 | /*␊ |
2 | * edid.c␊ |
3 | * ␊ |
4 | *␊ |
5 | * Created by Evan Lojewski on 12/1/09.␊ |
6 | * Copyright 2009. All rights reserved.␊ |
7 | *␊ |
8 | */␊ |
9 | ␊ |
10 | ␊ |
11 | #include "libsaio.h"␊ |
12 | #include "edid.h"␊ |
13 | #include "vbe.h"␊ |
14 | #include "graphics.h"␊ |
15 | #include "boot.h"␊ |
16 | ␊ |
17 | void getResolutionHook(void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6)␊ |
18 | {␊ |
19 | ␉getResolution(arg1, arg2, arg3);␊ |
20 | }␊ |
21 | ␊ |
22 | void getResolution(UInt32* x, UInt32* y, UInt32* bp)␊ |
23 | {␊ |
24 | ␉int val;␊ |
25 | ␉static UInt32 xResolution, yResolution, bpResolution;␊ |
26 | ␊ |
27 | ␉if(getIntForKey(kScreenWidth, &val, &bootInfo->bootConfig))␊ |
28 | ␉{␊ |
29 | ␉␉xResolution = val;␊ |
30 | ␉}␊ |
31 | ␉␊ |
32 | ␉if(getIntForKey(kScreenHeight, &val, &bootInfo->bootConfig))␊ |
33 | ␉{␊ |
34 | ␉␉yResolution = val;␊ |
35 | ␉}␊ |
36 | ␊ |
37 | ␉bpResolution = 32;␉// assume 32bits␊ |
38 | ␊ |
39 | ␉␊ |
40 | ␉if(!xResolution || !yResolution || !bpResolution)␊ |
41 | ␉{␊ |
42 | ␉␉␊ |
43 | ␉␉char* edidInfo = readEDID();␊ |
44 | ␉␉␊ |
45 | ␉␉if(!edidInfo) return;␊ |
46 | ␉␉␊ |
47 | ␉␉// TODO: check *all* resolutions reported and either use the highest, or the native resolution (if there is a flag for that)␊ |
48 | ␉␉xResolution = edidInfo[56] | ((edidInfo[58] & 0xF0) << 4);␊ |
49 | ␉␉yResolution = edidInfo[59] | ((edidInfo[61] & 0xF0) << 4);␊ |
50 | ␉␉␊ |
51 | ␉␉//printf("H Active = %d", edidInfo[56] | ((edidInfo[58] & 0xF0) << 4) );␊ |
52 | ␉␉//printf("V Active = %d", edidInfo[59] | ((edidInfo[61] & 0xF0) << 4) );␊ |
53 | ␉␉␊ |
54 | ␉␉free( edidInfo );␊ |
55 | ␉␉␊ |
56 | ␉␉if(!xResolution) xResolution = DEFAULT_SCREEN_WIDTH;␊ |
57 | ␉␉if(!yResolution) yResolution = DEFAULT_SCREEN_HEIGHT;␊ |
58 | ␊ |
59 | ␉}␊ |
60 | ␊ |
61 | ␉*x = xResolution;␊ |
62 | ␉*y = yResolution;␊ |
63 | ␉*bp = bpResolution;␊ |
64 | ␊ |
65 | }␊ |
66 | ␊ |
67 | char* readEDID()␊ |
68 | {␊ |
69 | ␉SInt16 last_reported = -1;␊ |
70 | ␉UInt8 edidInfo[EDID_BLOCK_SIZE];␊ |
71 | ␊ |
72 | ␉UInt8 header1[] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00};␊ |
73 | ␉UInt8 header2[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};␊ |
74 | ␉␊ |
75 | ␉SInt16 status;␊ |
76 | ␉UInt16 blocks_left = 1;␊ |
77 | ␉␊ |
78 | ␉do␊ |
79 | ␉{␊ |
80 | ␉␉// TODO: This currently only retrieves the *last* block, make the block buffer expand as needed / calculated from the first block␊ |
81 | ␊ |
82 | ␉␉bzero( edidInfo, EDID_BLOCK_SIZE);␊ |
83 | ␊ |
84 | ␉␉status = getEDID(edidInfo, blocks_left);␊ |
85 | ␉␉␊ |
86 | ␉␉␊ |
87 | ␉␉//printf("Buffer location: 0x%X\n", SEG(buffer) << 16 | OFF(buffer));␊ |
88 | ␉␉/*␊ |
89 | ␉␉int j, i;␊ |
90 | ␉␉for (j = 0; j < 8; j++) {␊ |
91 | ␉␉␉for(i = 0; i < 16; i++) printf("0x%X ", ebiosInfo[((i+1) * (j + 1)) - 1]);␊ |
92 | ␊ |
93 | ␉␉}␊ |
94 | ␉␉printf("\n");␊ |
95 | ␉␉*/␊ |
96 | ␉␉␊ |
97 | ␉␉if(status == 0)␊ |
98 | ␉␉{␊ |
99 | ␉␉␉//if( edidInfo[0] == 0x00 || edidInfo[0] == 0xFF)␊ |
100 | ␉␉␉if((memcmp(edidInfo, header1, sizeof(header1)) != 0) ||␊ |
101 | ␉␉␉ (memcmp(edidInfo, header2, sizeof(header2)) != 0) )␊ |
102 | ␉␉␉{␊ |
103 | ␉␉␉␉blocks_left--;␊ |
104 | ␉␉␉␉int reported = edidInfo[ EDID_V1_BLOCKS_TO_GO_OFFSET ];␊ |
105 | ␉␉␉␉␊ |
106 | ␉␉␉␉if ( reported > blocks_left )␊ |
107 | ␉␉␉␉{␊ |
108 | ␉␉␉␉␉␊ |
109 | ␉␉␉␉␉printf("EDID claims %d more blocks left\n", reported);␊ |
110 | ␉␉␉␉}␊ |
111 | ␉␉␉␉␊ |
112 | ␉␉␉␉if ( (last_reported <= reported && last_reported != -1)␊ |
113 | ␉␉␉␉␉|| reported == 0xff␊ |
114 | ␉␉␉␉␉/* 0xff frequently comes up in corrupt edids */␊ |
115 | ␉␉␉␉␉//|| reported == MAGIC␊ |
116 | ␉␉␉␉␉)␊ |
117 | ␉␉␉␉{␊ |
118 | ␉␉␉␉␉printf("Last reported %d\n", last_reported);␊ |
119 | ␉␉␉␉␉printf( "EDID blocks left is wrong.\n"␊ |
120 | ␉␉␉␉␉␉ "Your EDID is probably invalid.\n");␊ |
121 | ␉␉␉␉␉return 0;␊ |
122 | ␉␉␉␉}␊ |
123 | ␉␉␉␉else␊ |
124 | ␉␉␉␉{␊ |
125 | ␉␉␉␉␉//printf("Reading EDID block\n");␊ |
126 | ␉␉␉␉␉//printf("H Active = %d", ebiosInfo[56] | ((ebiosInfo[58] & 0xF0) << 4) );␊ |
127 | ␉␉␉␉␉//printf("V Active = %d", ebiosInfo[59] | ((ebiosInfo[61] & 0xF0) << 4) );␊ |
128 | ␊ |
129 | ␉␉␉␉␉last_reported = reported;␊ |
130 | ␉␉␉␉␉blocks_left = reported;␊ |
131 | ␉␉␉␉}␊ |
132 | ␉␉␉} ␊ |
133 | ␉␉␉else␊ |
134 | ␉␉␉{␊ |
135 | ␉␉␉␉printf("Invalid block %d\n", blocks_left);␊ |
136 | ␉␉␉␉printf("Header1 = %d", memcmp(edidInfo, header1, sizeof(header1)) );␊ |
137 | ␉␉␉␉printf("Header2 = %d", memcmp(edidInfo, header2, sizeof(header2)) );␊ |
138 | ␉␉␉␉return 0;␊ |
139 | ␉␉␉}␊ |
140 | ␉␉}␊ |
141 | ␉␉blocks_left = 0;␉␊ |
142 | ␉} while(blocks_left);␊ |
143 | ␊ |
144 | ␉char* ret = malloc(sizeof(edidInfo));␊ |
145 | ␉memcpy(ret, edidInfo, sizeof(edidInfo));␊ |
146 | ␉return ret;␊ |
147 | }␊ |
148 | |