]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/TianoTools/FlashMap/Microcode.c
51ae20e9f51e60b7099498baff5915eb2354efb7
[mirror_edk2.git] / Tools / Source / TianoTools / FlashMap / Microcode.c
1 /*++
2
3 Copyright (c) 2004 Intel Corporation. All rights reserved
4 This software and associated documentation (if any) is furnished
5 under a license and may only be used or copied in accordance
6 with the terms of the license. Except as permitted by such
7 license, no part of this software or documentation may be
8 reproduced, stored in a retrieval system, or transmitted in any
9 form or by any means without the express written consent of
10 Intel Corporation.
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 #define INT8 char
28 #define UINT32 unsigned int
29
30 #include "EfiUtilityMsgs.h"
31 #include "Microcode.h"
32
33 #define MAX_LINE_LEN 256
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
126 Line[MAX_LINE_LEN - 1] = 0;
127 *Data = 0;
128 if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {
129 return STATUS_ERROR;
130 }
131 //
132 // If it was a binary file, then it may have overwritten our null terminator
133 //
134 if (Line[MAX_LINE_LEN - 1] != 0) {
135 return STATUS_ERROR;
136 }
137 //
138 // Look for
139 // dd 000000001h ; comment
140 // dd XXXXXXXX
141 // DD XXXXXXXXX
142 // DD XXXXXXXXX
143 //
144 for (cptr = Line; *cptr && isspace(*cptr); cptr++) {
145 }
146 if ((tolower(cptr[0]) == 'd') && (tolower(cptr[1]) == 'd') && isspace (cptr[2])) {
147 //
148 // Skip blanks and look for a hex digit
149 //
150 cptr += 3;
151 for (; *cptr && isspace(*cptr); cptr++) {
152 }
153 if (isxdigit (*cptr)) {
154 if (sscanf (cptr, "%X", Data) != 1) {
155 return STATUS_ERROR;
156 }
157 }
158 return STATUS_SUCCESS;
159 }
160 return STATUS_ERROR;
161 }
162
163 STATUS
164 MicrocodeParseFile (
165 char *InFileName,
166 char *OutFileName
167 )
168 /*++
169
170 Routine Description:
171 Parse a microcode text file, and write the binary results to an output file.
172
173 Arguments:
174 InFileName - input text file to parse
175 OutFileName - output file to write raw binary data from parsed input file
176
177 Returns:
178 STATUS_SUCCESS - no errors or warnings
179 STATUS_ERROR - errors were encountered
180
181 --*/
182 {
183 FILE *InFptr;
184 FILE *OutFptr;
185 STATUS Status;
186 MICROCODE_IMAGE_HEADER *Header;
187 unsigned int Size;
188 unsigned int Size2;
189 unsigned int Data;
190 unsigned int Checksum;
191 char *Buffer;
192 char *Ptr;
193 unsigned int TotalSize;
194
195 Status = STATUS_ERROR;
196 InFptr = NULL;
197 OutFptr = NULL;
198 Buffer = NULL;
199 //
200 // Open the input text file
201 //
202 if ((InFptr = fopen (InFileName, "r")) == NULL) {
203 Error (NULL, 0, 0, InFileName, "failed to open input microcode file for reading");
204 return STATUS_ERROR;
205 }
206 //
207 // Make two passes on the input file. The first pass is to determine how
208 // much data is in the file so we can allocate a working buffer. Then
209 // we'll allocate a buffer and re-read the file into the buffer for processing.
210 //
211 Size = 0;
212 do {
213 Status = MicrocodeReadData (InFptr, &Data);
214 if (Status == STATUS_SUCCESS) {
215 Size += sizeof (Data);
216 }
217 } while (Status == STATUS_SUCCESS);
218 //
219 // Error if no data.
220 //
221 if (Size == 0) {
222 Error (NULL, 0, 0, InFileName, "no parse-able data found in file");
223 goto Done;
224 }
225 if (Size < sizeof (MICROCODE_IMAGE_HEADER)) {
226 Error (NULL, 0, 0, InFileName, "amount of parse-able data is insufficient to contain a microcode header");
227 goto Done;
228 }
229 //
230 // Allocate a buffer for the data
231 //
232 Buffer = (char *) _malloc (Size);
233 if (Buffer == NULL) {
234 Error (NULL, 0, 0, "memory allocation failure", NULL);
235 goto Done;
236 }
237 //
238 // Re-read the file, storing the data into our buffer
239 //
240 fseek (InFptr, 0, SEEK_SET);
241 Ptr = Buffer;
242 do {
243 Status = MicrocodeReadData (InFptr, &Data);
244 if (Status == STATUS_SUCCESS) {
245 *(unsigned int *) Ptr = Data;
246 Ptr += sizeof (Data);
247 }
248 } while (Status == STATUS_SUCCESS);
249 //
250 // Can't do much checking on the header because, per the spec, the
251 // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
252 // and the TotalSize field is invalid (actually missing). Thus we can't
253 // even verify the Reserved fields are 0.
254 //
255 Header = (MICROCODE_IMAGE_HEADER *) Buffer;
256 if (Header->DataSize == 0) {
257 TotalSize = 2048;
258 } else {
259 TotalSize = Header->TotalSize;
260 }
261 if (TotalSize != Size) {
262 Error (NULL, 0, 0, InFileName, "file contents do not contain expected TotalSize 0x%04X", TotalSize);
263 goto Done;
264 }
265 //
266 // Checksum the contents
267 //
268 Ptr = Buffer;
269 Checksum = 0;
270 Size2 = 0;
271 while (Size2 < Size) {
272 Checksum += *(unsigned int *) Ptr;
273 Ptr += 4;
274 Size2 += 4;
275 }
276 if (Checksum != 0) {
277 Error (NULL, 0, 0, InFileName, "checksum failed on file contents");
278 goto Done;
279 }
280 //
281 // Open the output file and write the buffer contents
282 //
283 if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {
284 Error (NULL, 0, 0, OutFileName, "failed to open output microcode file for writing");
285 goto Done;
286 }
287 if (fwrite (Buffer, Size, 1, OutFptr) != 1) {
288 Error (NULL, 0, 0, OutFileName, "failed to write microcode data to output file");
289 goto Done;
290 }
291 Status = STATUS_SUCCESS;
292 Done:
293 if (Buffer != NULL) {
294 free (Buffer);
295 }
296 if (InFptr != NULL) {
297 fclose (InFptr);
298 }
299 if (OutFptr != NULL) {
300 fclose (OutFptr);
301 if (Status == STATUS_ERROR) {
302 remove (OutFileName);
303 }
304 }
305 return Status;
306 }