]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/Source/TianoTools/FlashMap/Microcode.c
Support building on x64 hosts.
[mirror_edk2.git] / Tools / Source / TianoTools / FlashMap / Microcode.c
CommitLineData
d25c4bf0 1/*++\r
2\r
b84b42fc 3Copyright (c) 2004-2006 Intel Corporation. All rights reserved\r
4This program and the accompanying materials are licensed and made available \r
5under the terms and conditions of the BSD License which accompanies this \r
6distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
d25c4bf0 11\r
12Module Name:\r
13\r
14 Microcode.c\r
15\r
16Abstract:\r
17\r
18 Utility for working with microcode patch files in the Intel \r
19 Platform Innovation Framework for EFI build environment.\r
20\r
21--*/\r
22\r
23#include <stdio.h>\r
24#include <string.h> // for memset()\r
25#include <ctype.h>\r
26#include <stdlib.h> // for malloc()\r
d25c4bf0 27\r
28#include "EfiUtilityMsgs.h"\r
29#include "Microcode.h"\r
30\r
31#define MAX_LINE_LEN 256\r
32\r
33//\r
34// Structure definition for a microcode header\r
35//\r
36typedef struct {\r
37 unsigned int HeaderVersion;\r
38 unsigned int PatchId;\r
39 unsigned int Date;\r
40 unsigned int CpuId;\r
41 unsigned int Checksum;\r
42 unsigned int LoaderVersion;\r
43 unsigned int PlatformId;\r
44 unsigned int DataSize; // if 0, then TotalSize = 2048, and TotalSize field is invalid\r
45 unsigned int TotalSize; // number of bytes\r
46 unsigned int Reserved[3];\r
47} MICROCODE_IMAGE_HEADER;\r
48\r
49static\r
50STATUS\r
51MicrocodeReadData (\r
52 FILE *InFptr,\r
53 unsigned int *Data\r
54 );\r
55\r
56void\r
57MicrocodeConstructor (\r
58 void\r
59 )\r
60/*++\r
61\r
62Routine Description:\r
63\r
64 Constructor of module Microcode\r
65\r
66Arguments:\r
67\r
68 None\r
69\r
70Returns:\r
71\r
72 None\r
73\r
74--*/\r
75{\r
76}\r
77\r
78void\r
79MicrocodeDestructor (\r
80 void\r
81 )\r
82/*++\r
83\r
84Routine Description:\r
85\r
86 Destructor of module Microcode\r
87\r
88Arguments:\r
89\r
90 None\r
91\r
92Returns:\r
93\r
94 None\r
95\r
96--*/\r
97{\r
98}\r
99\r
100static\r
101STATUS\r
102MicrocodeReadData (\r
103 FILE *InFptr,\r
104 unsigned int *Data\r
105 )\r
106/*++\r
107\r
108Routine Description:\r
109 Read a 32-bit microcode data value from a text file and convert to raw binary form.\r
110\r
111Arguments:\r
112 InFptr - file pointer to input text file\r
113 Data - pointer to where to return the data parsed\r
114\r
115Returns:\r
116 STATUS_SUCCESS - no errors or warnings, Data contains valid information\r
117 STATUS_ERROR - errors were encountered\r
118\r
119--*/\r
120{\r
121 char Line[MAX_LINE_LEN];\r
122 char *cptr;\r
123\r
124 Line[MAX_LINE_LEN - 1] = 0;\r
125 *Data = 0;\r
126 if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {\r
127 return STATUS_ERROR;\r
128 }\r
129 //\r
130 // If it was a binary file, then it may have overwritten our null terminator\r
131 //\r
132 if (Line[MAX_LINE_LEN - 1] != 0) {\r
133 return STATUS_ERROR;\r
134 }\r
135 //\r
136 // Look for\r
137 // dd 000000001h ; comment\r
138 // dd XXXXXXXX\r
139 // DD XXXXXXXXX\r
140 // DD XXXXXXXXX\r
141 //\r
142 for (cptr = Line; *cptr && isspace(*cptr); cptr++) {\r
143 }\r
144 if ((tolower(cptr[0]) == 'd') && (tolower(cptr[1]) == 'd') && isspace (cptr[2])) {\r
145 //\r
146 // Skip blanks and look for a hex digit\r
147 //\r
148 cptr += 3;\r
149 for (; *cptr && isspace(*cptr); cptr++) {\r
150 }\r
151 if (isxdigit (*cptr)) {\r
152 if (sscanf (cptr, "%X", Data) != 1) {\r
153 return STATUS_ERROR;\r
154 }\r
155 }\r
156 return STATUS_SUCCESS;\r
157 }\r
158 return STATUS_ERROR;\r
159}\r
160\r
161STATUS\r
162MicrocodeParseFile (\r
163 char *InFileName,\r
164 char *OutFileName\r
165 )\r
166/*++\r
167\r
168Routine Description:\r
169 Parse a microcode text file, and write the binary results to an output file.\r
170\r
171Arguments:\r
172 InFileName - input text file to parse\r
173 OutFileName - output file to write raw binary data from parsed input file\r
174\r
175Returns:\r
176 STATUS_SUCCESS - no errors or warnings\r
177 STATUS_ERROR - errors were encountered\r
178\r
179--*/\r
180{\r
181 FILE *InFptr;\r
182 FILE *OutFptr;\r
183 STATUS Status;\r
184 MICROCODE_IMAGE_HEADER *Header;\r
185 unsigned int Size;\r
186 unsigned int Size2;\r
187 unsigned int Data;\r
188 unsigned int Checksum;\r
189 char *Buffer;\r
190 char *Ptr;\r
191 unsigned int TotalSize;\r
192\r
193 Status = STATUS_ERROR;\r
194 InFptr = NULL;\r
195 OutFptr = NULL;\r
196 Buffer = NULL;\r
197 //\r
198 // Open the input text file\r
199 //\r
200 if ((InFptr = fopen (InFileName, "r")) == NULL) {\r
201 Error (NULL, 0, 0, InFileName, "failed to open input microcode file for reading");\r
202 return STATUS_ERROR;\r
203 }\r
204 //\r
205 // Make two passes on the input file. The first pass is to determine how\r
206 // much data is in the file so we can allocate a working buffer. Then\r
207 // we'll allocate a buffer and re-read the file into the buffer for processing.\r
208 //\r
209 Size = 0;\r
210 do {\r
211 Status = MicrocodeReadData (InFptr, &Data);\r
212 if (Status == STATUS_SUCCESS) {\r
213 Size += sizeof (Data);\r
214 }\r
215 } while (Status == STATUS_SUCCESS);\r
216 //\r
217 // Error if no data.\r
218 //\r
219 if (Size == 0) {\r
220 Error (NULL, 0, 0, InFileName, "no parse-able data found in file");\r
221 goto Done;\r
222 }\r
223 if (Size < sizeof (MICROCODE_IMAGE_HEADER)) {\r
224 Error (NULL, 0, 0, InFileName, "amount of parse-able data is insufficient to contain a microcode header");\r
225 goto Done;\r
226 }\r
227 //\r
228 // Allocate a buffer for the data\r
229 //\r
230 Buffer = (char *) _malloc (Size);\r
231 if (Buffer == NULL) {\r
232 Error (NULL, 0, 0, "memory allocation failure", NULL);\r
233 goto Done;\r
234 }\r
235 //\r
236 // Re-read the file, storing the data into our buffer\r
237 //\r
238 fseek (InFptr, 0, SEEK_SET);\r
239 Ptr = Buffer;\r
240 do {\r
241 Status = MicrocodeReadData (InFptr, &Data);\r
242 if (Status == STATUS_SUCCESS) {\r
243 *(unsigned int *) Ptr = Data;\r
244 Ptr += sizeof (Data);\r
245 }\r
246 } while (Status == STATUS_SUCCESS);\r
247 //\r
248 // Can't do much checking on the header because, per the spec, the\r
249 // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,\r
250 // and the TotalSize field is invalid (actually missing). Thus we can't\r
251 // even verify the Reserved fields are 0.\r
252 //\r
253 Header = (MICROCODE_IMAGE_HEADER *) Buffer;\r
254 if (Header->DataSize == 0) {\r
255 TotalSize = 2048;\r
256 } else {\r
257 TotalSize = Header->TotalSize;\r
258 }\r
259 if (TotalSize != Size) {\r
260 Error (NULL, 0, 0, InFileName, "file contents do not contain expected TotalSize 0x%04X", TotalSize);\r
261 goto Done;\r
262 }\r
263 //\r
264 // Checksum the contents\r
265 //\r
266 Ptr = Buffer;\r
267 Checksum = 0;\r
268 Size2 = 0;\r
269 while (Size2 < Size) {\r
270 Checksum += *(unsigned int *) Ptr;\r
271 Ptr += 4;\r
272 Size2 += 4;\r
273 }\r
274 if (Checksum != 0) {\r
275 Error (NULL, 0, 0, InFileName, "checksum failed on file contents");\r
276 goto Done;\r
277 }\r
278 //\r
279 // Open the output file and write the buffer contents\r
280 //\r
281 if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {\r
282 Error (NULL, 0, 0, OutFileName, "failed to open output microcode file for writing");\r
283 goto Done;\r
284 }\r
285 if (fwrite (Buffer, Size, 1, OutFptr) != 1) {\r
286 Error (NULL, 0, 0, OutFileName, "failed to write microcode data to output file");\r
287 goto Done;\r
288 }\r
289 Status = STATUS_SUCCESS;\r
290Done:\r
291 if (Buffer != NULL) {\r
292 free (Buffer);\r
293 }\r
294 if (InFptr != NULL) {\r
295 fclose (InFptr);\r
296 }\r
297 if (OutFptr != NULL) {\r
298 fclose (OutFptr);\r
299 if (Status == STATUS_ERROR) {\r
300 remove (OutFileName);\r
301 }\r
302 }\r
303 return Status;\r
304}\r