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