]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/Source/TianoTools/VfrCompile/VfrServices.cpp
Translate the Arch enum to an arch directory name. This is necessary for Linux builds...
[mirror_edk2.git] / Tools / Source / TianoTools / VfrCompile / VfrServices.cpp
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2004 - 2005, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. 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
11\r
12Module Name:\r
13\r
14 VfrServices.cpp\r
15\r
16Abstract:\r
17\r
18 Support routines for the VFR compiler\r
19 \r
20--*/ \r
21\r
22#include <stdio.h> // for FILE routines\r
23#include <stdlib.h> // for malloc() and free()\r
24\r
25#include <Base.h>\r
26#include <UefiBaseTypes.h>\r
27#include <MultiPhase.h>\r
28#include "EfiUtilityMsgs.h"\r
29#include "EfiVfr.h"\r
30#include "VfrServices.h"\r
31\r
32#include <UgaDraw.h>\r
33#include <Hii.h>\r
34\r
35static const char *mSourceFileHeader[] = {\r
36 "//",\r
37 "// DO NOT EDIT -- auto-generated file",\r
38 "//",\r
39 "// This file is generated by the VFR compiler.",\r
40 "//",\r
41 NULL\r
42};\r
43\r
44typedef struct {\r
45 CHAR8 *Name;\r
46 INT32 Size;\r
47} IFR_OPCODE_SIZES;\r
48\r
49//\r
50// Create a table that can be used to do internal checking on the IFR\r
51// bytes we emit.\r
52//\r
53static const IFR_OPCODE_SIZES mOpcodeSizes[] = {\r
54 { 0, 0 }, // invalid\r
55 { "EFI_IFR_FORM", sizeof (EFI_IFR_FORM) },\r
56 { "EFI_IFR_SUBTITLE", sizeof (EFI_IFR_SUBTITLE) }, \r
57 { "EFI_IFR_TEXT", -6 }, //sizeof (EFI_IFR_TEXT) }, \r
58 { "unused 0x04 opcode", 0 }, // EFI_IFR_GRAPHIC_OP\r
59 { "EFI_IFR_ONE_OF", sizeof (EFI_IFR_ONE_OF) }, \r
60 { "EFI_IFR_CHECKBOX", sizeof (EFI_IFR_CHECKBOX) }, \r
61 { "EFI_IFR_NUMERIC", sizeof (EFI_IFR_NUMERIC) }, \r
62 { "EFI_IFR_PASSWORD", sizeof (EFI_IFR_PASSWORD) }, \r
63 { "EFI_IFR_ONE_OF_OPTION", sizeof (EFI_IFR_ONE_OF_OPTION) }, \r
64 { "EFI_IFR_SUPPRESS", sizeof (EFI_IFR_SUPPRESS) }, \r
65 { "EFI_IFR_END_FORM", sizeof (EFI_IFR_END_FORM) }, \r
66 { "EFI_IFR_HIDDEN", sizeof (EFI_IFR_HIDDEN) }, \r
67 { "EFI_IFR_END_FORM_SET", sizeof (EFI_IFR_END_FORM_SET) }, \r
68 { "EFI_IFR_FORM_SET", sizeof (EFI_IFR_FORM_SET) }, \r
69 { "EFI_IFR_REF", sizeof (EFI_IFR_REF) }, \r
70 { "EFI_IFR_END_ONE_OF", sizeof (EFI_IFR_END_ONE_OF) }, \r
71 { "EFI_IFR_INCONSISTENT", sizeof (EFI_IFR_INCONSISTENT) }, \r
72 { "EFI_IFR_EQ_ID_VAL", sizeof (EFI_IFR_EQ_ID_VAL) }, \r
73 { "EFI_IFR_EQ_ID_ID", sizeof (EFI_IFR_EQ_ID_ID) }, \r
74 { "EFI_IFR_EQ_ID_LIST", -sizeof (EFI_IFR_EQ_ID_LIST) }, \r
75 { "EFI_IFR_AND", sizeof (EFI_IFR_AND) }, \r
76 { "EFI_IFR_OR", sizeof (EFI_IFR_OR) }, \r
77 { "EFI_IFR_NOT", sizeof (EFI_IFR_NOT) }, \r
78 { "EFI_IFR_END_EXPR", sizeof (EFI_IFR_END_EXPR) }, \r
79 { "EFI_IFR_GRAY_OUT", sizeof (EFI_IFR_GRAY_OUT) }, \r
80 { "EFI_IFR_DATE", sizeof (EFI_IFR_DATE) / 3 }, \r
81 { "EFI_IFR_TIME", sizeof (EFI_IFR_TIME) / 3 }, \r
82 { "EFI_IFR_STRING", sizeof (EFI_IFR_STRING) }, \r
83 { "EFI_IFR_LABEL", sizeof (EFI_IFR_LABEL) }, \r
84 { "EFI_IFR_SAVE_DEFAULTS", sizeof (EFI_IFR_SAVE_DEFAULTS) }, \r
85 { "EFI_IFR_RESTORE_DEFAULTS", sizeof (EFI_IFR_RESTORE_DEFAULTS) }, \r
86 { "EFI_IFR_BANNER", sizeof (EFI_IFR_BANNER) },\r
87 { "EFI_IFR_INVENTORY", sizeof (EFI_IFR_INVENTORY) },\r
88 { "EFI_IFR_EQ_VAR_VAL_OP", sizeof (EFI_IFR_EQ_VAR_VAL) },\r
89 { "EFI_IFR_ORDERED_LIST_OP", sizeof (EFI_IFR_ORDERED_LIST) },\r
90 { "EFI_IFR_VARSTORE_OP", -sizeof (EFI_IFR_VARSTORE) },\r
91 { "EFI_IFR_VARSTORE_SELECT_OP", sizeof (EFI_IFR_VARSTORE_SELECT) },\r
92 { "EFI_IFR_VARSTORE_SELECT_PAIR_OP", sizeof (EFI_IFR_VARSTORE_SELECT_PAIR) },\r
93 { "EFI_IFR_TRUE", sizeof (EFI_IFR_TRUE)},\r
94 { "EFI_IFR_FALSE", sizeof (EFI_IFR_FALSE)},\r
95 { "EFI_IFR_GT", sizeof (EFI_IFR_GT)},\r
96 { "EFI_IFR_GE", sizeof (EFI_IFR_GE)},\r
97 { "EFI_IFR_OEM_DEFINED_OP", -2 },\r
98};\r
99\r
100\r
101VfrOpcodeHandler::VfrOpcodeHandler (\r
102 ) \r
103/*++\r
104\r
105Routine Description:\r
106 Constructor for the VFR opcode handling class.\r
107 \r
108Arguments:\r
109 None\r
110\r
111Returns:\r
112 None\r
113\r
114--*/\r
115{ \r
116 mIfrBytes = NULL; \r
117 mLastIfrByte = NULL;\r
118 mBytesWritten = 0;\r
119 mQueuedByteCount = 0;\r
120 mQueuedOpcodeByteValid = 0;\r
121 mPrimaryVarStoreId = 0;\r
122 mSecondaryVarStoreId = 0;\r
123 mSecondaryVarStoreIdSet = 0;\r
124 mPrimaryVarStoreIdSet = 0;\r
125 mDefaultVarStoreId = 0;\r
126}\r
127\r
128VOID \r
129VfrOpcodeHandler::SetVarStoreId (\r
130 UINT16 VarStoreId\r
131 )\r
132/*++\r
133\r
134Routine Description:\r
135 This function is invoked by the parser when a variable is referenced in the \r
136 VFR. Save the variable store (and set a flag) so that we can later determine \r
137 if we need to emit a varstore-select or varstore-select-pair opcode.\r
138 \r
139Arguments:\r
140 VarStoreId - ID of the variable store referenced in the VFR\r
141\r
142Returns:\r
143 None\r
144\r
145--*/\r
146{\r
147 mPrimaryVarStoreId = VarStoreId;\r
148 mPrimaryVarStoreIdSet = 1;\r
149}\r
150\r
151VOID \r
152VfrOpcodeHandler::SetSecondaryVarStoreId (\r
153 UINT16 VarStoreId\r
154 )\r
155/*++\r
156\r
157Routine Description:\r
158 This function is invoked by the parser when a secondary variable is \r
159 referenced in the VFR. Save the variable store (and set a flag) so \r
160 that we can later determine if we need to emit a varstore-select or \r
161 varstore-pair opcode.\r
162 \r
163Arguments:\r
164 VarStoreId - ID of the variable store referenced in the VFR\r
165\r
166Returns:\r
167 None\r
168\r
169--*/\r
170{\r
171 mSecondaryVarStoreId = VarStoreId;\r
172 mSecondaryVarStoreIdSet = 1;\r
173}\r
174\r
175VOID \r
176VfrOpcodeHandler::WriteIfrBytes (\r
177 ) \r
178/*++\r
179\r
180Routine Description:\r
181 This function is invoked at the end of parsing. Its purpose\r
182 is to write out all the IFR bytes that were queued up while\r
183 parsing.\r
184 \r
185Arguments:\r
186 None\r
187\r
188Returns:\r
189 None\r
190\r
191--*/\r
192{ \r
193 IFR_BYTE *Curr;\r
194 IFR_BYTE *Next;\r
195 UINT32 Count;\r
196 UINT32 LineCount;\r
197 UINT32 PoundLines;\r
198 UINT32 ByteCount;\r
199 CHAR8 Line[MAX_LINE_LEN];\r
200 CHAR8 *Cptr;\r
201 FILE *InFptr;\r
202 FILE *OutFptr;\r
203 UINT32 ListFile;\r
204 EFI_HII_IFR_PACK_HEADER IfrHeader;\r
205 UINT8 *Ptr;\r
206 FILE *IfrBinFptr;\r
207 UINT32 BytesLeftThisOpcode;\r
208 //\r
209 // If someone added a new opcode and didn't update our opcode sizes structure, error out.\r
210 //\r
211 if (sizeof(mOpcodeSizes) / sizeof (mOpcodeSizes[0]) != EFI_IFR_LAST_OPCODE + 1) {\r
212 Error (__FILE__, __LINE__, 0, "application error", "internal IFR binary table size is incorrect");\r
213 return;\r
214 }\r
215 //\r
216 // Flush the queue\r
217 //\r
218 FlushQueue (); \r
219 //\r
220 // If there have been any errors to this point, then skip dumping the IFR\r
221 // binary data. This way doing an nmake again will try to build it again, and\r
222 // the build will fail if they did not fix the problem.\r
223 //\r
224 if (GetUtilityStatus () != STATUS_ERROR) {\r
225 if ((IfrBinFptr = fopen (gOptions.IfrOutputFileName, "w")) == NULL) {\r
226 Error (PROGRAM_NAME, 0, 0, gOptions.IfrOutputFileName, "could not open file for writing");\r
227 return;\r
228 }\r
229 //\r
230 // Write the standard file header to the output file\r
231 //\r
232 WriteStandardFileHeader (IfrBinFptr);\r
233 //\r
234 // Write the structure header\r
235 //\r
236 fprintf (IfrBinFptr, "\nunsigned char %sBin[] = {", gOptions.VfrBaseFileName);\r
237 //\r
238 // Write the header\r
239 //\r
240 memset ((char *)&IfrHeader, 0, sizeof (IfrHeader));\r
241 IfrHeader.Header.Type = EFI_HII_IFR;\r
242 IfrHeader.Header.Length = mBytesWritten + sizeof (IfrHeader); \r
243 Ptr = (UINT8 *)&IfrHeader;\r
244 for (Count = 0; Count < sizeof (IfrHeader); Count++, Ptr++) {\r
245 if ((Count & 0x03) == 0) {\r
246 fprintf (IfrBinFptr, "\n ");\r
247 }\r
248 fprintf (IfrBinFptr, "0x%02X, ", *Ptr); \r
249 }\r
250 //\r
251 //\r
252 // Write all the IFR bytes\r
253 //\r
254 fprintf (IfrBinFptr, "\n // start of IFR data");\r
255 Curr = mIfrBytes;\r
256 Count = 0;\r
257 while (Curr != NULL) {\r
258 if ((Count & 0x0F) == 0) {\r
259 fprintf (IfrBinFptr, "\n ");\r
260 }\r
261 if (Curr->KeyByte != 0) {\r
262 fprintf (IfrBinFptr, "/*%c*/ ", Curr->KeyByte);\r
263 }\r
264 fprintf (IfrBinFptr, "0x%02X, ", Curr->OpcodeByte);\r
265 Count++;\r
266 Curr = Curr->Next;\r
267 }\r
268 fprintf (IfrBinFptr, "\n};\n\n");\r
269 //\r
270 //\r
271 // Close the file\r
272 //\r
273 fclose (IfrBinFptr); \r
274 IfrBinFptr = NULL;\r
275 }\r
276 //\r
277 // Write the bytes as binary data if the user specified to do so\r
278 //\r
279 if ((GetUtilityStatus () != STATUS_ERROR) && (gOptions.CreateIfrBinFile != 0)) {\r
280 //\r
281 // Use the Ifr output file name with a ".hpk" extension.\r
282 //\r
283 for (Cptr = gOptions.IfrOutputFileName + strlen (gOptions.IfrOutputFileName) - 1;\r
284 (*Cptr != '.') && (Cptr > gOptions.IfrOutputFileName) && (*Cptr != '\\');\r
285 Cptr--) {\r
286 //\r
287 // do nothing\r
288 //\r
289 }\r
290 if (*Cptr == '.') {\r
291 strcpy (Cptr, ".hpk");\r
292 } else {\r
293 strcat (gOptions.IfrOutputFileName, ".hpk");\r
294 }\r
295 if ((IfrBinFptr = fopen (gOptions.IfrOutputFileName, "wb")) == NULL) {\r
296 Error (PROGRAM_NAME, 0, 0, gOptions.IfrOutputFileName, "could not open file for writing");\r
297 return;\r
298 }\r
299 //\r
300 // Write the structure header\r
301 //\r
302 memset ((char *)&IfrHeader, 0, sizeof (IfrHeader));\r
303 IfrHeader.Header.Type = EFI_HII_IFR;\r
304 IfrHeader.Header.Length = mBytesWritten + sizeof (IfrHeader); \r
305 Ptr = (UINT8 *)&IfrHeader;\r
306 for (Count = 0; Count < sizeof (IfrHeader); Count++, Ptr++) {\r
307 fwrite (Ptr, 1, 1, IfrBinFptr);\r
308 }\r
309 //\r
310 //\r
311 // Write all the IFR bytes\r
312 //\r
313 Curr = mIfrBytes;\r
314 Count = 0;\r
315 while (Curr != NULL) {\r
316 fwrite (&Curr->OpcodeByte, 1, 1, IfrBinFptr);\r
317 Curr = Curr->Next;\r
318 }\r
319 //\r
320 //\r
321 // Close the file\r
322 //\r
323 fclose (IfrBinFptr); \r
324 IfrBinFptr = NULL;\r
325 }\r
326 //\r
327 // If creating a listing file, then open the input and output files\r
328 //\r
329 ListFile = 0;\r
330 if (gOptions.CreateListFile) {\r
331 //\r
332 // Open the input VFR file and the output list file\r
333 //\r
334 if ((InFptr = fopen (gOptions.PreprocessorOutputFileName, "r")) == NULL) {\r
335 Warning (PROGRAM_NAME, 0, 0, gOptions.PreprocessorOutputFileName, "could not open file for creating a list file");\r
336 } else {\r
337 if ((OutFptr = fopen (gOptions.VfrListFileName, "w")) == NULL) {\r
338 Warning (PROGRAM_NAME, 0, 0, gOptions.VfrListFileName, "could not open output list file for writing");\r
339 fclose (InFptr);\r
340 InFptr = NULL;\r
341 } else {\r
342 LineCount = 0;\r
343 ListFile = 1;\r
344 PoundLines = 0;\r
345 ByteCount = 0;\r
346 }\r
347 }\r
348 }\r
349 //\r
350 // Write the list file\r
351 //\r
352 if (ListFile) {\r
353 //\r
354 // Write out the VFR compiler version\r
355 //\r
356 fprintf (OutFptr, "//\n// VFR compiler version " VFR_COMPILER_VERSION "\n//\n");\r
357 Curr = mIfrBytes;\r
358 while (Curr != NULL) {\r
359 //\r
360 // Print lines until we reach the line of the current opcode\r
361 //\r
362 while (LineCount < PoundLines + Curr->LineNum) {\r
363 if (fgets (Line, sizeof (Line), InFptr) != NULL) {\r
364 //\r
365 // We should check for line length exceeded on the fgets(). Otherwise it\r
366 // throws the listing file output off. Future enhancement perhaps.\r
367 //\r
368 fprintf (OutFptr, "%s", Line);\r
369 if (strncmp (Line, "#line", 5) == 0) {\r
370 PoundLines++;\r
371 }\r
372 }\r
373 LineCount++;\r
374 }\r
375 //\r
376 // Print all opcodes with line numbers less than where we are now\r
377 //\r
378 BytesLeftThisOpcode = 0;\r
379 while ((Curr != NULL) && ((Curr->LineNum == 0) || (LineCount >= PoundLines + Curr->LineNum))) {\r
380 if (BytesLeftThisOpcode == 0) {\r
381 fprintf (OutFptr, ">%08X: ", ByteCount);\r
382 if (Curr->Next != NULL) {\r
383 BytesLeftThisOpcode = (UINT32)Curr->Next->OpcodeByte;\r
384 }\r
385 }\r
386 fprintf (OutFptr, "%02X ", (UINT32)Curr->OpcodeByte);\r
387 ByteCount++;\r
388 BytesLeftThisOpcode--;\r
389 if (BytesLeftThisOpcode == 0) {\r
390 fprintf (OutFptr, "\n");\r
391 }\r
392 Curr = Curr->Next;\r
393 }\r
394 }\r
395 //\r
396 // Dump any remaining lines from the input file\r
397 //\r
398 while (fgets (Line, sizeof (Line), InFptr) != NULL) {\r
399 fprintf (OutFptr, "%s", Line);\r
400 }\r
401 fclose (InFptr);\r
402 fclose (OutFptr);\r
403 }\r
404 //\r
405 // Debug code to make sure that each opcode we write out has as many\r
406 // bytes as the IFR structure requires. If there were errors, then\r
407 // don't do this step.\r
408 //\r
409 if (GetUtilityStatus () != STATUS_ERROR) {\r
410 Curr = mIfrBytes;\r
411 ByteCount = 0;\r
412 while (Curr != NULL) {\r
413 //\r
414 // First byte is the opcode, second byte is the length\r
415 //\r
416 if (Curr->Next == NULL) {\r
417 Error (__FILE__, __LINE__, 0, "application error", "last opcode written does not contain a length byte");\r
418 break;\r
419 }\r
420 Count = (UINT32)Curr->Next->OpcodeByte;\r
421 if (Count == 0) {\r
422 Error (\r
423 __FILE__, \r
424 __LINE__, \r
425 0, \r
426 "application error", \r
427 "opcode with 0 length specified in output at offset 0x%X", \r
428 ByteCount\r
429 );\r
430 break;\r
431 }\r
432 //\r
433 // Check the length\r
434 //\r
435 if ((Curr->OpcodeByte > EFI_IFR_LAST_OPCODE) || (Curr->OpcodeByte == 0)) {\r
436 Error (\r
437 __FILE__, \r
438 __LINE__, \r
439 0, \r
440 "application error", \r
441 "invalid opcode 0x%X in output at offset 0x%X", \r
442 (UINT32) Curr->OpcodeByte, ByteCount\r
443 );\r
444 } else if (mOpcodeSizes[Curr->OpcodeByte].Size < 0) {\r
445 //\r
446 // For those cases where the length is variable, the size is negative, and indicates\r
447 // the miniumum size.\r
448 //\r
449 if ((mOpcodeSizes[Curr->OpcodeByte].Size * -1) > Count) {\r
450 Error (\r
451 __FILE__, \r
452 __LINE__, \r
453 0, \r
454 "application error", \r
455 "insufficient number of bytes written for %s at offset 0x%X",\r
456 mOpcodeSizes[Curr->OpcodeByte].Name, \r
457 ByteCount\r
458 );\r
459 }\r
460 } else {\r
461 //\r
462 // Check for gaps\r
463 //\r
464 if (mOpcodeSizes[Curr->OpcodeByte].Size == 0) {\r
465 Error (\r
466 __FILE__, \r
467 __LINE__, \r
468 0, \r
469 "application error", \r
470 "invalid opcode 0x%X in output at offset 0x%X", \r
471 (UINT32)Curr->OpcodeByte, \r
472 ByteCount\r
473 );\r
474 } else {\r
475 //\r
476 // Check size\r
477 //\r
478 if (mOpcodeSizes[Curr->OpcodeByte].Size != Count) {\r
479 Error (\r
480 __FILE__, \r
481 __LINE__, \r
482 0, \r
483 "application error", \r
484 "invalid number of bytes (%d written s/b %d) written for %s at offset 0x%X",\r
485 Count, \r
486 mOpcodeSizes[Curr->OpcodeByte].Size, \r
487 mOpcodeSizes[Curr->OpcodeByte].Name, \r
488 ByteCount\r
489 );\r
490 }\r
491 }\r
492 }\r
493 //\r
494 // Skip to next opcode\r
495 //\r
496 while (Count > 0) {\r
497 ByteCount++;\r
498 if (Curr == NULL) {\r
499 Error (__FILE__, __LINE__, 0, "application error", "last opcode written has invalid length");\r
500 break;\r
501 }\r
502 Curr = Curr->Next;\r
503 Count--;\r
504 }\r
505 }\r
506 }\r
507}\r
508\r
509VfrOpcodeHandler::~VfrOpcodeHandler(\r
510 ) \r
511/*++\r
512\r
513Routine Description:\r
514 Destructor for the VFR opcode handler. Free up memory allocated\r
515 while parsing the VFR script.\r
516 \r
517Arguments:\r
518 None\r
519\r
520Returns:\r
521 None\r
522\r
523--*/\r
524{\r
525 IFR_BYTE *Curr;\r
526 IFR_BYTE *Next;\r
527 //\r
528 // Free up the IFR bytes\r
529 //\r
530 Curr = mIfrBytes;\r
531 while (Curr != NULL) {\r
532 Next = Curr->Next;\r
533 free (Curr);\r
534 Curr = Next;\r
535 }\r
536}\r
537\r
538int \r
539VfrOpcodeHandler::AddOpcodeByte (\r
540 UINT8 OpcodeByte, \r
541 UINT32 LineNum\r
542 ) \r
543/*++\r
544\r
545Routine Description:\r
546 This function is invoked by the parser when a new IFR\r
547 opcode should be emitted.\r
548 \r
549Arguments:\r
550 OpcodeByte - the IFR opcode\r
551 LineNum - the line number from the source file that resulted\r
552 in the opcode being emitted.\r
553\r
554Returns:\r
555 0 always\r
556\r
557--*/\r
558{\r
559 UINT32 Count;\r
560\r
561 FlushQueue();\r
562 //\r
563 // Now add this new byte\r
564 //\r
565 mQueuedOpcodeByte = OpcodeByte;\r
566 mQueuedLineNum = LineNum;\r
567 mQueuedOpcodeByteValid = 1;\r
568 return 0;\r
569}\r
570\r
571VOID \r
572VfrOpcodeHandler::AddByte (\r
573 UINT8 ByteVal, \r
574 UINT8 KeyByte\r
575 )\r
576/*++\r
577\r
578Routine Description:\r
579 This function is invoked by the parser when it determines\r
580 that more raw IFR bytes should be emitted to the output stream.\r
581 Here we just queue them up into an output buffer.\r
582 \r
583Arguments:\r
584 ByteVal - the raw byte to emit to the output IFR stream\r
585 KeyByte - a value that can be used for debug. \r
586\r
587Returns:\r
588 None\r
589\r
590--*/\r
591{\r
592 //\r
593 // Check for buffer overflow\r
594 //\r
595 if (mQueuedByteCount > MAX_QUEUE_COUNT) {\r
596 Error (PROGRAM_NAME, 0, 0, NULL, "opcode queue overflow");\r
597 } else {\r
598 mQueuedBytes[mQueuedByteCount] = ByteVal;\r
599 mQueuedKeyBytes[mQueuedByteCount] = KeyByte;\r
600 mQueuedByteCount++;\r
601 }\r
602}\r
603\r
604int \r
605VfrOpcodeHandler::FlushQueue (\r
606 )\r
607/*++\r
608\r
609Routine Description:\r
610 This function is invoked to flush the internal IFR buffer.\r
611 \r
612Arguments:\r
613 None\r
614\r
615Returns:\r
616 0 always\r
617\r
618--*/\r
619{\r
620 UINT32 Count;\r
621 UINT32 EmitNoneOnePair;\r
622\r
623 EmitNoneOnePair = 0;\r
624 //\r
625 // If the secondary varstore was specified, then we have to emit\r
626 // a varstore-select-pair opcode, which only applies to the following\r
627 // statement. \r
628 //\r
629 if (mSecondaryVarStoreIdSet) {\r
630 mSecondaryVarStoreIdSet = 0;\r
631 //\r
632 // If primary and secondary are the same as the current default\r
633 // varstore, then we don't have to do anything.\r
634 // Note that the varstore-select-pair only applies to the following\r
635 // opcode.\r
636 //\r
637 if ((mPrimaryVarStoreId != mSecondaryVarStoreId) || (mPrimaryVarStoreId != mDefaultVarStoreId)) {\r
638 IAddByte (EFI_IFR_VARSTORE_SELECT_PAIR_OP, 'O', mQueuedLineNum);\r
639 IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT_PAIR), 'L', 0);\r
640 IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0);\r
641 IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0);\r
642 IAddByte ((UINT8)mSecondaryVarStoreId, 0, 0);\r
643 IAddByte ((UINT8)(mSecondaryVarStoreId >> 8), 0, 0);\r
644 }\r
645 } else if (mPrimaryVarStoreIdSet != 0) {\r
646 mPrimaryVarStoreIdSet = 0;\r
647 if (mDefaultVarStoreId != mPrimaryVarStoreId) {\r
648 //\r
649 // The VFR statement referenced a different variable store \r
650 // than the last one we reported. Insert a new varstore select \r
651 // statement. \r
652 //\r
653 IAddByte (EFI_IFR_VARSTORE_SELECT_OP, 'O', mQueuedLineNum);\r
654 IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT), 'L', 0);\r
655 IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0);\r
656 IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0);\r
657 mDefaultVarStoreId = mPrimaryVarStoreId;\r
658 }\r
659 }\r
660 //\r
661 // Likely a new opcode is being added. Since each opcode item in the IFR has \r
662 // a header that specifies the size of the opcode item (which we don't\r
663 // know until we find the next opcode in the VFR), we queue up bytes\r
664 // until we know the size. Then we write them out. So flush the queue\r
665 // now.\r
666 //\r
667 if (mQueuedOpcodeByteValid != 0) {\r
668 // \r
669 // Add the previous opcode byte, the length byte, and the binary\r
670 // data.\r
671 //\r
672 IAddByte (mQueuedOpcodeByte, 'O', mQueuedLineNum);\r
673 IAddByte ((UINT8)(mQueuedByteCount + 2), 'L', 0);\r
674 for (Count = 0; Count < mQueuedByteCount; Count++) {\r
675 IAddByte (mQueuedBytes[Count], mQueuedKeyBytes[Count], 0); \r
676 }\r
677 mQueuedByteCount = 0;\r
678 mQueuedOpcodeByteValid = 0;\r
679 } \r
680 return 0;\r
681}\r
682\r
683int \r
684VfrOpcodeHandler::IAddByte (\r
685 UINT8 ByteVal, \r
686 UINT8 KeyByte, \r
687 UINT32 LineNum\r
688 )\r
689/*++\r
690\r
691Routine Description:\r
692 This internal function is used to add actual IFR bytes to\r
693 the output stream. Most other functions queue up the bytes\r
694 in an internal buffer. Once they come here, there's no\r
695 going back.\r
696\r
697 \r
698Arguments:\r
699 ByteVal - value to write to output \r
700 KeyByte - key value tied to the byte -- useful for debug\r
701 LineNum - line number from source file the byte resulted from\r
702\r
703Returns:\r
704 0 - if successful\r
705 1 - failed due to memory allocation failure\r
706\r
707--*/\r
708{\r
709 IFR_BYTE *NewByte;\r
710 NewByte = (IFR_BYTE *)malloc (sizeof (IFR_BYTE));\r
711 if (NewByte == NULL) {\r
712 return 1;\r
713 }\r
714 memset ((char *)NewByte, 0, sizeof (IFR_BYTE));\r
715 NewByte->OpcodeByte = ByteVal;\r
716 NewByte->KeyByte = KeyByte;\r
717 NewByte->LineNum = LineNum;\r
718 //\r
719 // Add to the list\r
720 //\r
721 if (mIfrBytes == NULL) {\r
722 mIfrBytes = NewByte;\r
723 } else {\r
724 mLastIfrByte->Next = NewByte;\r
725 } \r
726 mLastIfrByte = NewByte;\r
727 mBytesWritten++;\r
728 return 0;\r
729}\r
730\r
731VOID \r
732WriteStandardFileHeader (\r
733 FILE *OutFptr\r
734 ) \r
735/*++\r
736\r
737Routine Description:\r
738 This function is invoked to emit a standard header to an\r
739 output text file.\r
740 \r
741Arguments:\r
742 OutFptr - file to write the header to\r
743\r
744Returns:\r
745 None\r
746\r
747--*/\r
748{\r
749 UINT32 TempIndex;\r
750 for (TempIndex = 0; mSourceFileHeader[TempIndex] != NULL; TempIndex++) {\r
751 fprintf (OutFptr, "%s\n", mSourceFileHeader[TempIndex]);\r
752 }\r
753 //\r
754 // Write out the VFR compiler version\r
755 //\r
756 fprintf (OutFptr, "// VFR compiler version " VFR_COMPILER_VERSION "\n//\n");\r
757}\r