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