summaryrefslogtreecommitdiffstats
path: root/resources/utilities/ich9deblob/common/x86compatibility.c
blob: 46c60a7d1509ff62b435dd194d21dd486d74f26d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
 *  x86compatibility.c
 *  This file is part of the ich9deblob utility from the libreboot project
 * 
 * Purpose: compiler/cpu compatibility checks. ich9deblob is not portable, yet.
 *
 *  Copyright (C) 2014 Steve Shenton <sgsit@libreboot.org>
 *                     Francis Rowe <info@gluglug.org.uk>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
#include <stdio.h>
#include <string.h>
#include "x86compatibility.h"

/*
 * ---------------------------------------------------------------------
 * x86 compatibility checking:
 * ---------------------------------------------------------------------
 */

/* fail if struct size is incorrect */
int structSizesIncorrect(struct DESCRIPTORREGIONRECORD descriptorDummy, struct GBEREGIONRECORD_8K gbe8kDummy) 
{
	unsigned int descriptorRegionStructSize = sizeof(descriptorDummy);
	unsigned int gbeRegion8kStructSize = sizeof(gbe8kDummy);
	
	/* check compiler bit-packs in a compatible way. basically, it is expected that this code will be used on x86 */
	if (DESCRIPTORREGIONSIZE != descriptorRegionStructSize){
		printf("\nerror: compiler incompatibility: descriptor struct length is %i bytes (should be %i)\n", descriptorRegionStructSize, DESCRIPTORREGIONSIZE);
		return 1;
	}
	if (GBEREGIONSIZE_8K != gbeRegion8kStructSize){
		printf("\nerror: compiler incompatibility: gbe struct length is %i bytes (should be %i)\n", gbeRegion8kStructSize, GBEREGIONSIZE_8K);
		return 1;
	}
	
	return 0;
}

/* endianness check. big endian forced to fail */
int systemIsBigEndian() 
{
	unsigned short steak = 0xBEEF;
	unsigned char *grill = (unsigned char*)&steak;
	
	if (*grill==0xBE) {
		printf("\nunsigned short 0xBEEF: first byte should be EF, but it's BE. Your system is big endian, and unsupported (only little endian is tested)\n");
		return 1;
	}
	return 0; /* you got the good half of the steak */
}

/* fail if members are presented in the wrong order */
int structMembersWrongOrder()
{
	int i;
	struct DESCRIPTORREGIONRECORD descriptorDummy;
	unsigned char *meVsccTablePtr = (unsigned char*)&descriptorDummy.meVsccTable;
	
	/* These do not use bitfields.  */
	descriptorDummy.meVsccTable.jid0 = 0x01020304;  /* unsigned int 32-bit */
	descriptorDummy.meVsccTable.vscc0 = 0x10203040; /* unsigned int 32-bit */
	descriptorDummy.meVsccTable.jid1 = 0x11223344;  /* unsigned int 32-bit */
	descriptorDummy.meVsccTable.vscc1 = 0x05060708; /* unsigned int 32-bit */
	descriptorDummy.meVsccTable.jid2 = 0x50607080;  /* unsigned int 32-bit */
	descriptorDummy.meVsccTable.vscc2 = 0x55667788; /* unsigned int 32-bit */
	descriptorDummy.meVsccTable.padding[0] = 0xAA;  /* unsigned char 8-bit */
	descriptorDummy.meVsccTable.padding[1] = 0xBB;  /* unsigned char 8-bit */
	descriptorDummy.meVsccTable.padding[2] = 0xCC;  /* unsigned char 8-bit */
	descriptorDummy.meVsccTable.padding[3] = 0xDD;  /* unsigned char 8-bit */
	
	/*
	 * Look from the top down, and concatenate the unsigned ints but
	 * with each unsigned in little endian order. 
	 * Then, concatenate the unsigned chars in big endian order. (in the padding array)
	 *
	 * combined, these should become:
	 * 01020304 10203040 11223344 05060708 50607080 55667788 AA BB CC DD (ignore this. big endian. just working it out manually:)
	 * 04030201 40302010 44332211 08070605 80706050 88776655 AA BB CC DD (ignore this. not byte-separated, just working it out:)
	 * 04 03 02 01 40 30 20 10 44 33 22 11 08 07 06 05 80 70 60 50 88 77 66 55 AA BB CC DD <-- it should match this
	 */
	
	if (
			!
			(
				*meVsccTablePtr      == 0x04 && *(meVsccTablePtr+1)  == 0x03 && *(meVsccTablePtr+2)  == 0x02 && *(meVsccTablePtr+3)  == 0x01
			&& *(meVsccTablePtr+4)  == 0x40 && *(meVsccTablePtr+5)  == 0x30 && *(meVsccTablePtr+6)  == 0x20 && *(meVsccTablePtr+7)  == 0x10
			&& *(meVsccTablePtr+8)  == 0x44 && *(meVsccTablePtr+9)  == 0x33 && *(meVsccTablePtr+10) == 0x22 && *(meVsccTablePtr+11) == 0x11
			&& *(meVsccTablePtr+12) == 0x08 && *(meVsccTablePtr+13) == 0x07 && *(meVsccTablePtr+14) == 0x06 && *(meVsccTablePtr+15) == 0x05
			&& *(meVsccTablePtr+16) == 0x80 && *(meVsccTablePtr+17) == 0x70 && *(meVsccTablePtr+18) == 0x60 && *(meVsccTablePtr+19) == 0x50
			&& *(meVsccTablePtr+20) == 0x88 && *(meVsccTablePtr+21) == 0x77 && *(meVsccTablePtr+22) == 0x66 && *(meVsccTablePtr+23) == 0x55
			&& *(meVsccTablePtr+24) == 0xAA && *(meVsccTablePtr+25) == 0xBB && *(meVsccTablePtr+26) == 0xCC && *(meVsccTablePtr+27) == 0xDD
	      )
	   ) {
			
		printf("\nStruct member order check (descriptorDummy.meVsccTable) with junk/dummy data:");
		printf("\nShould be: 04 03 02 01 40 30 20 10 44 33 22 11 08 07 06 05 80 70 60 50 88 77 66 55 aa bb cc dd ");
		printf("\nAnd it is: ");
		
		for (i = 0; i < 28; i++) {
			printf("%02x ", *(meVsccTablePtr + i));	
		}
		printf("\nIncorrect order.\n");
		
		return 1;
	}
	
	return 0;
}

/* fail if bit fields are presented in the wrong order */
int structBitfieldWrongOrder() 
{
	int i;
	struct DESCRIPTORREGIONRECORD descriptorDummy;
	unsigned char *flMap0Ptr = (unsigned char*)&descriptorDummy.flMaps.flMap0;
	
	descriptorDummy.flMaps.flMap0.FCBA = 0xA2;      /* :8 --> 10100010 */
	descriptorDummy.flMaps.flMap0.NC = 0x02;        /* :2 --> 10       */
	descriptorDummy.flMaps.flMap0.reserved1 = 0x38; /* :6 --> 111000   */
	descriptorDummy.flMaps.flMap0.FRBA = 0xD2;      /* :8 --> 11010010 */
	descriptorDummy.flMaps.flMap0.NR = 0x05;        /* :3 --> 101      */
	descriptorDummy.flMaps.flMap0.reserved2 = 0x1C; /* :5 --> 11100    */
	
	/*
	 * Look from the top bottom up, and concatenate the binary strings.
	 * Then, convert the 8-bit groups to hex and reverse the (8-bit)byte order
	 * 
	 * combined, these should become (in memory), in binary:
	 * 10100010 11100010 11010010 11100101
	 * or in hex:
	 * A2 E2 D2 E5
	 */
		
	if (!(*flMap0Ptr == 0xA2 && *(flMap0Ptr+1) == 0xE2 && *(flMap0Ptr+2) == 0xD2 && *(flMap0Ptr+3) == 0xE5)) 
	{
		printf("\nBitfield order check (descriptorDummy.flMaps.flMaps0) with junk/dummy data:");
		printf("\nShould be: a2 e2 d2 e5 ");
		printf("\nAnd it is: ");

		for (i = 0; i < 4; i++) {
			printf("%02x ", *(flMap0Ptr + i));	
		}
		printf("\nIncorrect order.\n");
		
		return 1;
	}
	
	return 0;
}

/* Compatibility checks. This version of ich9deblob is not yet porable. */
int systemOrCompilerIncompatible(struct DESCRIPTORREGIONRECORD descriptorStruct, struct GBEREGIONRECORD_8K gbeStruct8k) 
{
	if (structSizesIncorrect(descriptorStruct, gbeStruct8k)) return 1;
	if (systemIsBigEndian()) return 1;
	if (structBitfieldWrongOrder()) return 1;
	if (structMembersWrongOrder()) return 1; 
	return 0;
}