]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Compatibility/PiSmbiosRecordOnDataHubSmbiosRecordThunk/Translate.c
Add missing fields of Type 4 conversion.
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / PiSmbiosRecordOnDataHubSmbiosRecordThunk / Translate.c
CommitLineData
bd1a4d18 1/** @file\r
024b1029 2 Translate the DataHub records via EFI_DATA_HUB_PROTOCOL to Smbios recorders \r
3 via EFI_SMBIOS_PROTOCOL.\r
4 \r
584d5652
HT
5Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
6This program and the accompanying materials\r
024b1029 7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "Thunk.h"\r
17\r
18EFI_GUID ZeroGuid = { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };\r
19EFI_SMBIOS_PROTOCOL *mSmbiosProtocol = NULL;\r
20\r
21/**\r
22 Release the structure Node. \r
23 \r
24 @param StructureNode Point to SMBIOS_STRUCTURE_NODE which will be removed.\r
25**/\r
26VOID\r
27ReleaseStructureNode (\r
28 SMBIOS_STRUCTURE_NODE *StructureNode\r
29 )\r
30{\r
31 EFI_SMBIOS_PROTOCOL *Smbios;\r
32 \r
33 RemoveEntryList (&(StructureNode->Link));\r
34 Smbios = GetSmbiosProtocol();\r
35 ASSERT (Smbios != NULL);\r
36 Smbios->Remove (Smbios, StructureNode->SmbiosHandle);\r
37 gBS->FreePool (StructureNode);\r
38}\r
39\r
40/**\r
41 Process a datahub's record and find corresponding translation way to translate\r
42 to SMBIOS record.\r
43 \r
44 @param Record Point to datahub record.\r
45**/\r
46VOID\r
47SmbiosProcessDataRecord (\r
48 IN EFI_DATA_RECORD_HEADER *Record\r
49 )\r
50{\r
51 EFI_DATA_RECORD_HEADER *RecordHeader;\r
52 EFI_SUBCLASS_TYPE1_HEADER *DataHeader;\r
53 UINTN Index;\r
54 SMBIOS_CONVERSION_TABLE_ENTRY *Conversion;\r
55 UINT8 *SrcData;\r
56 UINTN SrcDataSize;\r
57 LIST_ENTRY *Link;\r
58 SMBIOS_STRUCTURE_NODE *StructureNode;\r
59 BOOLEAN StructureCreated;\r
60 EFI_STATUS Status;\r
61 \r
62 Conversion = NULL;\r
63 StructureNode = NULL;\r
64 StructureCreated = FALSE;\r
65 RecordHeader = Record;\r
66 DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);\r
67 SrcData = (UINT8 *) (DataHeader + 1);\r
68 SrcDataSize = RecordHeader->RecordSize - RecordHeader->HeaderSize - sizeof (EFI_SUBCLASS_TYPE1_HEADER);\r
69\r
70 if (DataHeader->HeaderSize != sizeof (EFI_SUBCLASS_TYPE1_HEADER) ||\r
71 DataHeader->Instance == EFI_SUBCLASS_INSTANCE_RESERVED ||\r
72 DataHeader->SubInstance == EFI_SUBCLASS_INSTANCE_RESERVED\r
73 ) {\r
74 //\r
75 // Invalid Data Record\r
76 //\r
77 goto Done;\r
78 }\r
79\r
80 Index = 0;\r
81 while(TRUE) {\r
82 //\r
83 // Find a matching entry in the conversion table for this\r
84 // (SubClass, RecordNumber) pair\r
85 //\r
86 for (; !CompareGuid (&(mConversionTable[Index].SubClass), &ZeroGuid); Index++) {\r
87 if (CompareGuid (\r
88 &(mConversionTable[Index].SubClass),\r
89 &(RecordHeader->DataRecordGuid)\r
90 )) {\r
91 if (mConversionTable[Index].RecordType == DataHeader->RecordType) {\r
92 break;\r
93 }\r
94 }\r
95 }\r
96\r
97 if (CompareGuid (&(mConversionTable[Index].SubClass), &ZeroGuid)) {\r
98 //\r
99 // We cannot find a matching entry in conversion table,\r
100 // this means this data record cannot be used for SMBIOS.\r
101 // Just skip it.\r
102 //\r
103 goto Done;\r
104 }\r
105\r
106 Conversion = &mConversionTable[Index++];\r
107\r
108 //\r
109 // Find corresponding structure in the Structure List\r
110 //\r
111 for (Link = mStructureList.ForwardLink; Link != &mStructureList; Link = Link->ForwardLink) {\r
112\r
113 StructureNode = CR (\r
114 Link,\r
115 SMBIOS_STRUCTURE_NODE,\r
116 Link,\r
117 SMBIOS_STRUCTURE_NODE_SIGNATURE\r
118 );\r
119\r
26a76fbc 120 if (Conversion->StructureLocatingMethod == BySubclassInstanceSubinstanceProducer) {\r
024b1029 121 //\r
122 // Look at SubClass, Instance, SubInstance and ProducerName for a matching\r
123 // node\r
124 //\r
125 if (CompareGuid (&(StructureNode->SubClass), &(RecordHeader->DataRecordGuid)) &&\r
126 StructureNode->Instance == DataHeader->Instance &&\r
127 StructureNode->SubInstance == DataHeader->SubInstance &&\r
128 CompareGuid (&(StructureNode->ProducerName), &(RecordHeader->ProducerName))\r
129 ) {\r
130 if (Conversion->SmbiosType >= 0X80) {\r
131 if (StructureNode->SmbiosType == ((SMBIOS_STRUCTURE_HDR *) SrcData)->Type) {\r
132 break;\r
133 }\r
134 } else if (StructureNode->SmbiosType == Conversion->SmbiosType) {\r
135 break;\r
136 }\r
137 }\r
138\r
26a76fbc 139 } else if (Conversion->StructureLocatingMethod == BySubClassInstanceProducer) {\r
024b1029 140 //\r
141 // Look at SubClass, Instance and ProducerName for a matching node\r
142 //\r
143 if (CompareGuid (&(StructureNode->SubClass), &(RecordHeader->DataRecordGuid)) &&\r
144 StructureNode->Instance == DataHeader->Instance &&\r
145 CompareGuid (&(StructureNode->ProducerName), &(RecordHeader->ProducerName))\r
146 ) {\r
147 if (Conversion->SmbiosType >= 0X80) {\r
148 if (StructureNode->SmbiosType == ((SMBIOS_STRUCTURE_HDR *) SrcData)->Type) {\r
149 break;\r
150 }\r
151 } else if (StructureNode->SmbiosType == Conversion->SmbiosType) {\r
152 break;\r
153 }\r
154 }\r
155\r
156 } else {\r
157 //\r
158 // Invalid conversion table entry\r
159 //\r
160 goto Done;\r
161 }\r
162 }\r
163\r
234980f6 164 if (Link == &mStructureList || StructureNode == NULL) {\r
024b1029 165\r
166 //\r
167 // Not found, create a new structure\r
168 //\r
169 StructureNode = AllocateZeroPool (sizeof (SMBIOS_STRUCTURE_NODE));\r
170\r
bd1a4d18 171 if (StructureNode == NULL) {\r
024b1029 172 goto Done;\r
173 }\r
174\r
26a76fbc 175 if (Conversion->StructureLocatingMethod == BySubclassInstanceSubinstanceProducer) {\r
024b1029 176 //\r
177 // Fill in SubClass, Instance, SubInstance and ProducerName\r
178 //\r
179 CopyMem (&(StructureNode->SubClass), &(RecordHeader->DataRecordGuid), sizeof (EFI_GUID));\r
180 StructureNode->Instance = DataHeader->Instance;\r
181 StructureNode->SubInstance = DataHeader->SubInstance;\r
182 CopyMem (&(StructureNode->ProducerName), &(RecordHeader->ProducerName), sizeof (EFI_GUID));\r
183\r
26a76fbc 184 } else if (Conversion->StructureLocatingMethod == BySubClassInstanceProducer) {\r
024b1029 185 //\r
186 // Fill in at SubClass, Instance and ProducerName, mark SubInstance as Non\r
187 // Applicable\r
188 //\r
189 CopyMem (&(StructureNode->SubClass), &(RecordHeader->DataRecordGuid), sizeof (EFI_GUID));\r
190 StructureNode->Instance = DataHeader->Instance;\r
191 StructureNode->SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;\r
192 CopyMem (&(StructureNode->ProducerName), &(RecordHeader->ProducerName), sizeof (EFI_GUID));\r
193\r
194 }\r
195 //\r
196 // Allocate the structure instance\r
197 //\r
198 StructureNode->StructureSize = SmbiosGetTypeMinimalLength (Conversion->SmbiosType);\r
199 StructureNode->SmbiosType = Conversion->SmbiosType;\r
200 \r
201 //\r
202 // StructureSize include the TWO trailing zero byte.\r
203 //\r
204 if (StructureNode->StructureSize < (sizeof(SMBIOS_STRUCTURE) + 2)) {\r
205 //\r
206 // Invalid Type\r
207 //\r
208 gBS->FreePool (StructureNode);\r
209 goto Done;\r
210 }\r
211\r
212 StructureNode->SmbiosType = Conversion->SmbiosType;\r
213 StructureNode->SmbiosHandle = 0;\r
214 Status = SmbiosProtocolCreateRecord (\r
215 NULL, \r
216 StructureNode\r
217 );\r
218 if (EFI_ERROR (Status)) {\r
219 goto Done;\r
220 }\r
221 //\r
222 // Temporary cache the structrue pointer to Smbios database.\r
223 //\r
224 StructureNode->Structure = GetSmbiosBufferFromHandle (StructureNode->SmbiosHandle, StructureNode->SmbiosType, NULL);\r
225 \r
226 InitializeListHead (&StructureNode->LinkDataFixup);\r
227\r
228 //\r
229 // Insert the Structure Node into the Strucutre List\r
230 //\r
231 StructureNode->Signature = SMBIOS_STRUCTURE_NODE_SIGNATURE;\r
232 InsertTailList (&mStructureList, &(StructureNode->Link));\r
233\r
234 StructureCreated = TRUE;\r
235\r
236 }\r
237 \r
238 \r
239 //\r
240 // Re-calculate the structure pointer to Smbios database.\r
241 //\r
242 StructureNode->Structure = GetSmbiosBufferFromHandle (StructureNode->SmbiosHandle, StructureNode->SmbiosType, NULL);\r
243 \r
244 //\r
245 // Fill the Structure's field corresponding to this data record\r
246 //\r
26a76fbc 247 if (Conversion->FieldFillingMethod == RecordDataUnchangedOffsetSpecified) {\r
024b1029 248 //\r
249 // Field data is just the record data without transforming and\r
250 // offset is specified directly in the conversion table entry\r
251 //\r
252 if (Conversion->FieldOffset + SrcDataSize > StructureNode->Structure->Length) {\r
253 //\r
254 // Invalid Conversion Table Entry\r
255 //\r
256 if (StructureCreated) {\r
257 ReleaseStructureNode (StructureNode);\r
258 }\r
259\r
260 goto Done;\r
261 }\r
262 \r
263 CopyMem ((UINT8 *) (StructureNode->Structure) + Conversion->FieldOffset, SrcData, SrcDataSize);\r
264\r
26a76fbc 265 } else if (Conversion->FieldFillingMethod == ByFunctionWithOffsetSpecified) {\r
024b1029 266 //\r
267 // Field offfset is specified in the conversion table entry, but\r
268 // record data needs to be transformed to be filled into the field,\r
269 // so let the FieldFillingFunction do it.\r
270 //\r
bd1a4d18 271 if (Conversion->FieldFillingFunction == NULL) {\r
024b1029 272 //\r
273 // Invalid Conversion Table Entry\r
274 //\r
275 if (StructureCreated) {\r
276 ReleaseStructureNode (StructureNode);\r
277 }\r
278\r
279 goto Done;\r
280 }\r
281\r
282 Status = Conversion->FieldFillingFunction (\r
283 StructureNode,\r
284 Conversion->FieldOffset,\r
285 SrcData,\r
286 (UINT32) SrcDataSize\r
287 );\r
288 if (EFI_ERROR (Status)) {\r
289 if (StructureCreated) {\r
290 ReleaseStructureNode (StructureNode);\r
291 }\r
292\r
293 goto Done;\r
294 }\r
26a76fbc 295 } else if (Conversion->FieldFillingMethod == ByFunction) {\r
024b1029 296 //\r
297 // Both field offset and field content are determined by\r
298 // FieldFillingFunction\r
299 //\r
bd1a4d18 300 if (Conversion->FieldFillingFunction == NULL) {\r
024b1029 301 //\r
302 // Invalid Conversion Table Entry\r
303 //\r
304 if (StructureCreated) {\r
305 ReleaseStructureNode (StructureNode);\r
306 }\r
307\r
308 goto Done;\r
309 }\r
310\r
311 Status = Conversion->FieldFillingFunction (\r
312 StructureNode,\r
313 0,\r
314 SrcData,\r
315 (UINT32) SrcDataSize\r
316 );\r
317 if (EFI_ERROR (Status)) {\r
318 if (StructureCreated) {\r
319 ReleaseStructureNode (StructureNode);\r
320 }\r
321\r
322 goto Done;\r
323 }\r
26a76fbc 324 } else if (Conversion->FieldFillingMethod == ByFunctionWithWholeDataRecord) {\r
024b1029 325 //\r
326 // Both field offset and field content are determined by\r
327 // FieldFillingFunction and the function accepts the whole data record\r
328 // including the data header\r
329 //\r
bd1a4d18 330 if (Conversion->FieldFillingFunction == NULL) {\r
024b1029 331 //\r
332 // Invalid Conversion Table Entry\r
333 //\r
334 if (StructureCreated) {\r
335 ReleaseStructureNode (StructureNode);\r
336 }\r
337\r
338 goto Done;\r
339 }\r
340\r
341 Status = Conversion->FieldFillingFunction (\r
342 StructureNode,\r
343 0,\r
344 DataHeader,\r
345 RecordHeader->RecordSize - RecordHeader->HeaderSize\r
346 );\r
347 if (EFI_ERROR (Status)) {\r
348 if (StructureCreated) {\r
349 ReleaseStructureNode (StructureNode);\r
350 }\r
351\r
352 goto Done;\r
353 }\r
354 } else {\r
355 //\r
356 // Invalid Conversion Table Entry\r
357 //\r
358 if (StructureCreated) {\r
359 ReleaseStructureNode (StructureNode);\r
360 }\r
361\r
362 goto Done;\r
363 }\r
364 }\r
365Done:\r
366 return ;\r
367}\r
368\r
369/**\r
370 Calculate the minimal length for a SMBIOS type. This length maybe not equal\r
371 to sizeof (SMBIOS_RECORD_STRUCTURE), but defined in conformance chapter in SMBIOS specification.\r
372 \r
373 @param Type SMBIOS's type.\r
374 \r
375 @return the minimal length of a smbios record.\r
376**/\r
377UINT32\r
378SmbiosGetTypeMinimalLength (\r
379 IN UINT8 Type\r
380 )\r
381{\r
382 UINTN Index;\r
383\r
384 for (Index = 0; mTypeInfoTable[Index].MinLength != 0; Index++) {\r
385 if (mTypeInfoTable[Index].Type == Type) {\r
386 return mTypeInfoTable[Index].MinLength;\r
387 }\r
388 }\r
389\r
390 return 0;\r
391}\r
392\r
393/**\r
394 Get pointer of EFI_SMBIOS_PROTOCOL.\r
395 \r
396 @return pointer of EFI_SMBIOS_PROTOCOL.\r
397**/\r
398EFI_SMBIOS_PROTOCOL*\r
399GetSmbiosProtocol(\r
400 VOID\r
401 )\r
402{\r
403 EFI_STATUS Status;\r
404 \r
405 if (mSmbiosProtocol == NULL) {\r
406 Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID*) &mSmbiosProtocol);\r
407 ASSERT_EFI_ERROR (Status);\r
408 } \r
409 \r
410 ASSERT (mSmbiosProtocol != NULL);\r
411 return mSmbiosProtocol; \r
412} \r
413\r
414/**\r
415 Create a blank smbios record. The datahub record is only a field of smbios record.\r
416 So before fill any field from datahub's record. A blank smbios record need to be \r
417 created.\r
418 \r
419 @param ProducerHandle The produce handle for a datahub record\r
420 @param StructureNode Point to SMBIOS_STRUCTURE_NODE\r
421 \r
422 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory for new blank SMBIOS record.\r
423 @retval EFI_SUCCESS Success to create blank smbios record.\r
424**/\r
425EFI_STATUS\r
426SmbiosProtocolCreateRecord (\r
427 IN EFI_HANDLE ProducerHandle, OPTIONAL\r
428 IN SMBIOS_STRUCTURE_NODE *StructureNode\r
429 )\r
430{\r
431 EFI_SMBIOS_PROTOCOL *Smbios;\r
432 EFI_SMBIOS_TABLE_HEADER *BlankRecord;\r
433 EFI_STATUS Status;\r
434 SMBIOS_STRUCTURE_NODE *RefStructureNode;\r
435 LIST_ENTRY *Link;\r
436 LIST_ENTRY *Link1;\r
437 LIST_ENTRY *Link2; \r
438 SMBIOS_LINK_DATA_FIXUP_NODE *LinkDataFixupNode;\r
439 UINT8 *BufferPointer;\r
440 \r
441 Smbios = GetSmbiosProtocol();\r
442 ASSERT (Smbios != NULL);\r
443 \r
444 //\r
445 // Prepare a blank smbios record.\r
446 //\r
447 BlankRecord = (EFI_SMBIOS_TABLE_HEADER*) AllocateZeroPool (StructureNode->StructureSize);\r
448 if (BlankRecord == NULL) {\r
449 return EFI_OUT_OF_RESOURCES;\r
450 }\r
451 BlankRecord->Type = StructureNode->SmbiosType;\r
452 BlankRecord->Length = (UINT8) (StructureNode->StructureSize - 2);\r
453 \r
454 //\r
455 // Add blank record into SMBIOS database.\r
456 //\r
457 Status = Smbios->Add (Smbios, NULL, &StructureNode->SmbiosHandle, BlankRecord);\r
458 FreePool (BlankRecord);\r
459 \r
460 //\r
461 // Fix up the InterLink node for new added smbios record if some other\r
462 // existing smbios record want to link this new record's handle.\r
463 //\r
464 for (Link = mStructureList.ForwardLink; Link != &mStructureList; Link = Link->ForwardLink) {\r
465 RefStructureNode = CR (Link, SMBIOS_STRUCTURE_NODE, Link, SMBIOS_STRUCTURE_NODE_SIGNATURE);\r
466 for (Link1 = RefStructureNode->LinkDataFixup.ForwardLink; Link1 != &RefStructureNode->LinkDataFixup;) {\r
467 LinkDataFixupNode = CR (Link1, SMBIOS_LINK_DATA_FIXUP_NODE, Link, SMBIOS_LINK_DATA_FIXUP_NODE_SIGNATURE);\r
468 Link2 = Link1;\r
469 Link1 = Link1->ForwardLink;\r
470 \r
471 if ((StructureNode->SmbiosType != LinkDataFixupNode->TargetType) ||\r
472 !(CompareGuid (&StructureNode->SubClass, &LinkDataFixupNode->SubClass)) ||\r
473 (StructureNode->Instance != LinkDataFixupNode->LinkData.Instance) ||\r
474 (StructureNode->SubInstance != LinkDataFixupNode->LinkData.SubInstance)) {\r
475 continue;\r
476 }\r
477 \r
478 //\r
479 // Fill the field with the handle found\r
480 //\r
481 BufferPointer = (UINT8 *) (RefStructureNode->Structure) + LinkDataFixupNode->Offset;\r
482 *BufferPointer = (UINT8) (StructureNode->SmbiosHandle & 0xFF);\r
483 *(BufferPointer + 1) = (UINT8) ((StructureNode->SmbiosHandle >> 8) & 0xFF);\r
484 BufferPointer = NULL;\r
485\r
486 RemoveEntryList (Link2);\r
487 FreePool (LinkDataFixupNode);\r
488 }\r
489 }\r
490 \r
491 return Status;\r
492} \r
493\r
494/**\r
495 Get pointer of a SMBIOS record's buffer according to its handle.\r
496 \r
497 @param Handle The handle of SMBIOS record want to be searched.\r
498 @param Type The type of SMBIOS record want to be searched.\r
499 @param ProducerHandle The producer handle of SMBIOS record.\r
500 \r
501 @return EFI_SMBIOS_TABLE_HEADER Point to a SMBIOS record's buffer.\r
502**/ \r
503EFI_SMBIOS_TABLE_HEADER*\r
504GetSmbiosBufferFromHandle (\r
505 IN EFI_SMBIOS_HANDLE Handle,\r
506 IN EFI_SMBIOS_TYPE Type,\r
507 IN EFI_HANDLE ProducerHandle OPTIONAL\r
508 )\r
509{\r
510 EFI_SMBIOS_PROTOCOL* Smbios;\r
511 EFI_SMBIOS_HANDLE SearchingHandle;\r
512 EFI_SMBIOS_TABLE_HEADER *RecordInSmbiosDatabase;\r
513 EFI_STATUS Status;\r
514 \r
515 SearchingHandle = 0;\r
516 Smbios = GetSmbiosProtocol();\r
517 ASSERT (Smbios != NULL);\r
518 \r
519 do {\r
520 Status = Smbios->GetNext (Smbios, &SearchingHandle, &Type, &RecordInSmbiosDatabase, NULL);\r
521 } while ((SearchingHandle != Handle) && (Status != EFI_NOT_FOUND));\r
522 \r
523 return RecordInSmbiosDatabase;\r
524} \r
525\r
526/**\r
527\r
528 Get the full size of smbios structure including optional strings that follow the formatted structure.\r
529\r
530 @param Head Pointer to the beginning of smbios structure.\r
531 @param Size The returned size.\r
532 @param NumberOfStrings The returned number of optional strings that follow the formatted structure.\r
533\r
534 @retval EFI_SUCCESS Size retured in Size.\r
535 @retval EFI_INVALID_PARAMETER Input smbios structure mal-formed or Size is NULL.\r
536 \r
537**/\r
538EFI_STATUS\r
539EFIAPI\r
540GetSmbiosStructureSize (\r
541 IN EFI_SMBIOS_TABLE_HEADER *Head,\r
542 OUT UINT32 *Size,\r
543 OUT UINT8 *NumberOfStrings\r
544 )\r
545{\r
546 UINT32 FullSize;\r
547 UINT8 StrLen;\r
548 INT8* CharInStr;\r
549 \r
550 if (Size == NULL || NumberOfStrings == NULL) {\r
551 return EFI_INVALID_PARAMETER;\r
552 }\r
553\r
554 FullSize = Head->Length;\r
555 CharInStr = (INT8*)Head + Head->Length;\r
556 *Size = FullSize;\r
557 *NumberOfStrings = 0;\r
558 StrLen = 0;\r
559 //\r
560 // look for the two consecutive zeros, check the string limit by the way.\r
561 //\r
562 while (*CharInStr != 0 || *(CharInStr+1) != 0) { \r
563 if (*CharInStr == 0) {\r
564 *Size += 1;\r
565 CharInStr++;\r
566 }\r
567\r
568 for (StrLen = 0 ; StrLen < SMBIOS_STRING_MAX_LENGTH; StrLen++) {\r
569 if (*(CharInStr+StrLen) == 0) {\r
570 break;\r
571 } \r
572 }\r
573\r
574 if (StrLen == SMBIOS_STRING_MAX_LENGTH) {\r
575 return EFI_INVALID_PARAMETER;\r
576 }\r
577 //\r
578 // forward the pointer\r
579 //\r
580 CharInStr += StrLen;\r
581 *Size += StrLen;\r
582 *NumberOfStrings += 1;\r
583 \r
584 }\r
585\r
586 //\r
587 // count ending two zeros.\r
588 //\r
589 *Size += 2;\r
590 return EFI_SUCCESS; \r
591}\r