]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/CCode/Source/FlashMap/Microcode.c
Modified to strip leading white-space characters and ignore blank or comment only...
[mirror_edk2.git] / Tools / CCode / Source / 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
2e7ddad2 33#define STATUS_IGNORE 0xA\r
34\r
d25c4bf0 35//\r
36// Structure definition for a microcode header\r
37//\r
38typedef struct {\r
39 unsigned int HeaderVersion;\r
40 unsigned int PatchId;\r
41 unsigned int Date;\r
42 unsigned int CpuId;\r
43 unsigned int Checksum;\r
44 unsigned int LoaderVersion;\r
45 unsigned int PlatformId;\r
46 unsigned int DataSize; // if 0, then TotalSize = 2048, and TotalSize field is invalid\r
47 unsigned int TotalSize; // number of bytes\r
48 unsigned int Reserved[3];\r
49} MICROCODE_IMAGE_HEADER;\r
50\r
51static\r
52STATUS\r
53MicrocodeReadData (\r
54 FILE *InFptr,\r
55 unsigned int *Data\r
56 );\r
57\r
58void\r
59MicrocodeConstructor (\r
60 void\r
61 )\r
62/*++\r
63\r
64Routine Description:\r
65\r
66 Constructor of module Microcode\r
67\r
68Arguments:\r
69\r
70 None\r
71\r
72Returns:\r
73\r
74 None\r
75\r
76--*/\r
77{\r
78}\r
79\r
80void\r
81MicrocodeDestructor (\r
82 void\r
83 )\r
84/*++\r
85\r
86Routine Description:\r
87\r
88 Destructor of module Microcode\r
89\r
90Arguments:\r
91\r
92 None\r
93\r
94Returns:\r
95\r
96 None\r
97\r
98--*/\r
99{\r
100}\r
101\r
102static\r
103STATUS\r
104MicrocodeReadData (\r
105 FILE *InFptr,\r
106 unsigned int *Data\r
107 )\r
108/*++\r
109\r
110Routine Description:\r
111 Read a 32-bit microcode data value from a text file and convert to raw binary form.\r
112\r
113Arguments:\r
114 InFptr - file pointer to input text file\r
115 Data - pointer to where to return the data parsed\r
116\r
117Returns:\r
118 STATUS_SUCCESS - no errors or warnings, Data contains valid information\r
119 STATUS_ERROR - errors were encountered\r
120\r
121--*/\r
122{\r
123 char Line[MAX_LINE_LEN];\r
124 char *cptr;\r
2e7ddad2 125 unsigned int ctr;\r
d25c4bf0 126\r
127 Line[MAX_LINE_LEN - 1] = 0;\r
128 *Data = 0;\r
129 if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {\r
130 return STATUS_ERROR;\r
131 }\r
132 //\r
133 // If it was a binary file, then it may have overwritten our null terminator\r
134 //\r
135 if (Line[MAX_LINE_LEN - 1] != 0) {\r
136 return STATUS_ERROR;\r
137 }\r
2e7ddad2 138\r
139 // Strip leading white-space characters (except carriage returns) from Line\r
140 //\r
141 if (isspace(Line[0]) && Line[0] != '\n') {\r
142 while (isspace(Line[0])) {\r
143 for (ctr = 0; ctr < strlen(Line); ctr++)\r
144 if (Line[ctr] != '\n')\r
145 Line[ctr] = Line[ctr + 1];\r
146 }\r
147 }\r
148\r
d25c4bf0 149 //\r
150 // Look for\r
151 // dd 000000001h ; comment\r
152 // dd XXXXXXXX\r
153 // DD XXXXXXXXX\r
154 // DD XXXXXXXXX\r
155 //\r
156 for (cptr = Line; *cptr && isspace(*cptr); cptr++) {\r
157 }\r
158 if ((tolower(cptr[0]) == 'd') && (tolower(cptr[1]) == 'd') && isspace (cptr[2])) {\r
159 //\r
160 // Skip blanks and look for a hex digit\r
161 //\r
162 cptr += 3;\r
163 for (; *cptr && isspace(*cptr); cptr++) {\r
164 }\r
165 if (isxdigit (*cptr)) {\r
166 if (sscanf (cptr, "%X", Data) != 1) {\r
167 return STATUS_ERROR;\r
168 }\r
169 }\r
170 return STATUS_SUCCESS;\r
171 }\r
2e7ddad2 172 if (strlen(Line) == 1) {\r
173 return STATUS_IGNORE;\r
174 }\r
175 if (tolower(cptr[0]) == ';') {\r
176 return STATUS_IGNORE;\r
177 }\r
d25c4bf0 178 return STATUS_ERROR;\r
179}\r
180\r
181STATUS\r
182MicrocodeParseFile (\r
183 char *InFileName,\r
184 char *OutFileName\r
185 )\r
186/*++\r
187\r
188Routine Description:\r
189 Parse a microcode text file, and write the binary results to an output file.\r
190\r
191Arguments:\r
192 InFileName - input text file to parse\r
193 OutFileName - output file to write raw binary data from parsed input file\r
194\r
195Returns:\r
196 STATUS_SUCCESS - no errors or warnings\r
197 STATUS_ERROR - errors were encountered\r
198\r
199--*/\r
200{\r
201 FILE *InFptr;\r
202 FILE *OutFptr;\r
203 STATUS Status;\r
204 MICROCODE_IMAGE_HEADER *Header;\r
205 unsigned int Size;\r
206 unsigned int Size2;\r
207 unsigned int Data;\r
208 unsigned int Checksum;\r
209 char *Buffer;\r
210 char *Ptr;\r
2e7ddad2 211 char *OrigPtr;\r
d25c4bf0 212 unsigned int TotalSize;\r
213\r
214 Status = STATUS_ERROR;\r
215 InFptr = NULL;\r
216 OutFptr = NULL;\r
217 Buffer = NULL;\r
218 //\r
219 // Open the input text file\r
220 //\r
221 if ((InFptr = fopen (InFileName, "r")) == NULL) {\r
222 Error (NULL, 0, 0, InFileName, "failed to open input microcode file for reading");\r
223 return STATUS_ERROR;\r
224 }\r
225 //\r
226 // Make two passes on the input file. The first pass is to determine how\r
227 // much data is in the file so we can allocate a working buffer. Then\r
228 // we'll allocate a buffer and re-read the file into the buffer for processing.\r
229 //\r
230 Size = 0;\r
231 do {\r
232 Status = MicrocodeReadData (InFptr, &Data);\r
233 if (Status == STATUS_SUCCESS) {\r
234 Size += sizeof (Data);\r
235 }\r
2e7ddad2 236 if (Status == STATUS_IGNORE) {\r
237 Status = STATUS_SUCCESS;\r
238 }\r
d25c4bf0 239 } while (Status == STATUS_SUCCESS);\r
240 //\r
241 // Error if no data.\r
242 //\r
243 if (Size == 0) {\r
244 Error (NULL, 0, 0, InFileName, "no parse-able data found in file");\r
245 goto Done;\r
246 }\r
247 if (Size < sizeof (MICROCODE_IMAGE_HEADER)) {\r
248 Error (NULL, 0, 0, InFileName, "amount of parse-able data is insufficient to contain a microcode header");\r
249 goto Done;\r
250 }\r
251 //\r
252 // Allocate a buffer for the data\r
253 //\r
254 Buffer = (char *) _malloc (Size);\r
255 if (Buffer == NULL) {\r
256 Error (NULL, 0, 0, "memory allocation failure", NULL);\r
257 goto Done;\r
258 }\r
259 //\r
260 // Re-read the file, storing the data into our buffer\r
261 //\r
262 fseek (InFptr, 0, SEEK_SET);\r
263 Ptr = Buffer;\r
2e7ddad2 264 OrigPtr = Ptr;\r
d25c4bf0 265 do {\r
2e7ddad2 266 OrigPtr = Ptr;\r
d25c4bf0 267 Status = MicrocodeReadData (InFptr, &Data);\r
268 if (Status == STATUS_SUCCESS) {\r
269 *(unsigned int *) Ptr = Data;\r
270 Ptr += sizeof (Data);\r
271 }\r
2e7ddad2 272 if (Status == STATUS_IGNORE) {\r
273 Ptr = OrigPtr;\r
274 Status = STATUS_SUCCESS;\r
275 }\r
d25c4bf0 276 } while (Status == STATUS_SUCCESS);\r
277 //\r
278 // Can't do much checking on the header because, per the spec, the\r
279 // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,\r
280 // and the TotalSize field is invalid (actually missing). Thus we can't\r
281 // even verify the Reserved fields are 0.\r
282 //\r
283 Header = (MICROCODE_IMAGE_HEADER *) Buffer;\r
284 if (Header->DataSize == 0) {\r
285 TotalSize = 2048;\r
286 } else {\r
287 TotalSize = Header->TotalSize;\r
288 }\r
289 if (TotalSize != Size) {\r
290 Error (NULL, 0, 0, InFileName, "file contents do not contain expected TotalSize 0x%04X", TotalSize);\r
291 goto Done;\r
292 }\r
293 //\r
294 // Checksum the contents\r
295 //\r
296 Ptr = Buffer;\r
297 Checksum = 0;\r
298 Size2 = 0;\r
299 while (Size2 < Size) {\r
300 Checksum += *(unsigned int *) Ptr;\r
301 Ptr += 4;\r
302 Size2 += 4;\r
303 }\r
304 if (Checksum != 0) {\r
305 Error (NULL, 0, 0, InFileName, "checksum failed on file contents");\r
306 goto Done;\r
307 }\r
308 //\r
309 // Open the output file and write the buffer contents\r
310 //\r
311 if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {\r
312 Error (NULL, 0, 0, OutFileName, "failed to open output microcode file for writing");\r
313 goto Done;\r
314 }\r
315 if (fwrite (Buffer, Size, 1, OutFptr) != 1) {\r
316 Error (NULL, 0, 0, OutFileName, "failed to write microcode data to output file");\r
317 goto Done;\r
318 }\r
319 Status = STATUS_SUCCESS;\r
320Done:\r
321 if (Buffer != NULL) {\r
322 free (Buffer);\r
323 }\r
324 if (InFptr != NULL) {\r
325 fclose (InFptr);\r
326 }\r
327 if (OutFptr != NULL) {\r
328 fclose (OutFptr);\r
329 if (Status == STATUS_ERROR) {\r
330 remove (OutFileName);\r
331 }\r
332 }\r
333 return Status;\r
334}\r