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