Home | History | Annotate | Download | only in PiSmbiosRecordOnDataHubSmbiosRecordThunk
      1 /** @file
      2   Common filling functions used in translating Datahub's record
      3   to PI SMBIOS's record.
      4 
      5 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "Thunk.h"
     17 
     18 /**
     19   Field Filling Function for Cache SubClass record type 5&6 -- Cache SRAM type.
     20   Offset is mandatory
     21 
     22   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
     23   @param Offset           Offset of SMBIOS record which RecordData will be filled.
     24   @param RecordData       RecordData buffer will be filled.
     25   @param RecordDataSize   The size of RecordData buffer.
     26 
     27   @retval EFI_SUCCESS   Success fill RecordData into SMBIOS's record buffer.
     28 **/
     29 EFI_STATUS
     30 SmbiosFldCacheType5 (
     31   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
     32   IN      UINT32                    Offset,
     33   IN      VOID                      *RecordData,
     34   IN      UINT32                    RecordDataSize
     35   )
     36 {
     37   EFI_CACHE_SRAM_TYPE_DATA SramData;
     38   UINT32                   Temp;
     39 
     40   SramData = *(EFI_CACHE_SRAM_TYPE_DATA*)RecordData;
     41 
     42   //
     43   // Swap two fields because of inconsistency between smbios and datahub specs
     44   //
     45   Temp                  = SramData.Asynchronous;
     46   SramData.Asynchronous = SramData.Synchronous;
     47   SramData.Synchronous  = Temp;
     48 
     49   //
     50   // Truncate the data to word
     51   //
     52   CopyMem (
     53     (UINT8 *) (StructureNode->Structure) + Offset,
     54     (EFI_CACHE_SRAM_TYPE_DATA *) &SramData,
     55     2
     56     );
     57 
     58   return EFI_SUCCESS;
     59 }
     60 
     61 /**
     62   Field Filling Function for Cache SubClass record type 10 -- Cache Config.
     63   Offset is mandatory
     64 
     65   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
     66   @param Offset           Offset of SMBIOS record which RecordData will be filled.
     67   @param RecordData       RecordData buffer will be filled.
     68   @param RecordDataSize   The size of RecordData buffer.
     69 
     70   @retval EFI_SUCCESS   Success fill RecordData into SMBIOS's record buffer.
     71 **/
     72 EFI_STATUS
     73 SmbiosFldCacheType10 (
     74   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
     75   IN      UINT32                    Offset,
     76   IN      VOID                      *RecordData,
     77   IN      UINT32                    RecordDataSize
     78   )
     79 {
     80 
     81   UINT16  CacheConfig;
     82 
     83   CopyMem (&CacheConfig, RecordData, 2);
     84 
     85   if ((CacheConfig & 0x07) == 0) {
     86     return EFI_INVALID_PARAMETER;
     87   }
     88   //
     89   // Truncate the data to 2 bytes and make cache level zero-based.
     90   //
     91   CacheConfig--;
     92   CopyMem (
     93     (UINT8 *) (StructureNode->Structure) + Offset,
     94     &CacheConfig,
     95     2
     96     );
     97 
     98   return EFI_SUCCESS;
     99 }
    100 
    101 /**
    102   Enlarge the structure buffer of a structure node in SMBIOS database.
    103   The function maybe lead the structure pointer for SMBIOS record changed.
    104 
    105   @param StructureNode The structure node whose structure buffer is to be enlarged.
    106   @param NewLength     The new length of SMBIOS record which does not include unformat area.
    107   @param OldBufferSize The old size of SMBIOS record buffer.
    108   @param NewBufferSize The new size is targeted for enlarged.
    109 
    110   @retval EFI_OUT_OF_RESOURCES  No more memory to allocate new record
    111   @retval EFI_SUCCESS           Success to enlarge the record buffer size.
    112 **/
    113 EFI_STATUS
    114 SmbiosEnlargeStructureBuffer (
    115   IN OUT  SMBIOS_STRUCTURE_NODE *StructureNode,
    116   UINT8                         NewLength,
    117   UINTN                         OldBufferSize,
    118   UINTN                         NewBufferSize
    119   )
    120 {
    121   EFI_SMBIOS_TABLE_HEADER   *NewRecord;
    122   EFI_SMBIOS_PROTOCOL       *Smbios;
    123   EFI_STATUS                Status;
    124   UINT8                     CountOfString;
    125 
    126   NewRecord = NULL;
    127   Smbios    = GetSmbiosProtocol();
    128   ASSERT (Smbios != NULL);
    129 
    130   NewRecord = (EFI_SMBIOS_TABLE_HEADER*) AllocateZeroPool (NewBufferSize);
    131   if (NewRecord == NULL) {
    132     return EFI_OUT_OF_RESOURCES;
    133   }
    134   CopyMem (NewRecord, StructureNode->Structure, OldBufferSize);
    135 
    136 
    137   Status = Smbios->Remove (Smbios, StructureNode->SmbiosHandle);
    138   ASSERT_EFI_ERROR (Status);
    139 
    140   //
    141   // try to use original handle to enlarge the buffer.
    142   //
    143   NewRecord->Length = NewLength;
    144   Status = Smbios->Add (Smbios, NULL, &StructureNode->SmbiosHandle, NewRecord);
    145   ASSERT_EFI_ERROR (Status);
    146   FreePool (NewRecord);
    147 
    148   StructureNode->Structure = GetSmbiosBufferFromHandle (
    149                                StructureNode->SmbiosHandle,
    150                                StructureNode->SmbiosType,
    151                                NULL
    152                                );
    153   GetSmbiosStructureSize (
    154     StructureNode->Structure,
    155     &StructureNode->StructureSize,
    156     &CountOfString
    157     );
    158   return EFI_SUCCESS;
    159 }
    160 
    161 /**
    162   Update the structure buffer of a structure node in SMBIOS database.
    163   The function lead the structure pointer for SMBIOS record changed.
    164 
    165   @param StructureNode The structure node whose structure buffer is to be enlarged.
    166   @param NewRecord     The new SMBIOS record.
    167 
    168 **/
    169 VOID
    170 SmbiosUpdateStructureBuffer (
    171   IN OUT  SMBIOS_STRUCTURE_NODE *StructureNode,
    172   IN EFI_SMBIOS_TABLE_HEADER    *NewRecord
    173   )
    174 {
    175   EFI_SMBIOS_PROTOCOL       *Smbios;
    176   EFI_STATUS                Status;
    177   UINT8                     CountOfString;
    178 
    179   Smbios    = GetSmbiosProtocol();
    180   ASSERT (Smbios != NULL);
    181 
    182   Status = Smbios->Remove (Smbios, StructureNode->SmbiosHandle);
    183   ASSERT_EFI_ERROR (Status);
    184 
    185   //
    186   // try to use original handle to enlarge the buffer.
    187   //
    188   Status = Smbios->Add (Smbios, NULL, &StructureNode->SmbiosHandle, NewRecord);
    189   ASSERT_EFI_ERROR (Status);
    190 
    191   StructureNode->Structure = GetSmbiosBufferFromHandle (
    192                                StructureNode->SmbiosHandle,
    193                                StructureNode->SmbiosType,
    194                                NULL
    195                                );
    196   GetSmbiosStructureSize (
    197     StructureNode->Structure,
    198     &StructureNode->StructureSize,
    199     &CountOfString
    200     );
    201   return ;
    202 }
    203 
    204 /**
    205   Fill a standard Smbios string field.
    206 
    207   This function will convert the unicode string to single byte chars, and only
    208   English language is supported.
    209   This function changes the Structure pointer value of the structure node,
    210   which should be noted by Caller.
    211 
    212   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
    213   @param Offset           Offset of SMBIOS record which RecordData will be filled.
    214   @param RecordData       RecordData buffer will be filled.
    215   @param RecordDataSize   The size of RecordData buffer.
    216 
    217   @retval EFI_INVALID_PARAMETER   RecordDataSize is too larger
    218   @retval EFI_OUT_OF_RESOURCES    No memory to allocate new buffer for string
    219   @retval EFI_SUCCESS             Sucess append string for a SMBIOS record.
    220 **/
    221 EFI_STATUS
    222 SmbiosFldString (
    223   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
    224   IN      UINT32                    Offset,
    225   IN      VOID                      *RecordData,
    226   IN      UINT32                    RecordDataSize
    227   )
    228 {
    229   EFI_STATUS              Status;
    230   UINT16                  *Data;
    231   CHAR8                   AsciiData[SMBIOS_STRING_MAX_LENGTH];
    232   UINT8                   CountOfStrings;
    233   UINTN                   OrigStringNumber;
    234   EFI_SMBIOS_PROTOCOL     *Smbios;
    235   EFI_SMBIOS_HANDLE       SmbiosHandle;
    236   UINT32                  OrigStructureSize;
    237   UINTN                   NewStructureSize;
    238   EFI_SMBIOS_TABLE_HEADER *NewRecord;
    239   UINT32                  StringLength;
    240 
    241   Status            = EFI_SUCCESS;
    242   OrigStringNumber  = 0;
    243   OrigStructureSize = 0;
    244 
    245   //
    246   // if we have a NULL token,
    247   //
    248   if (0 == *((STRING_REF *) RecordData)) {
    249     *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + Offset) = 0;
    250     return EFI_SUCCESS;
    251   }
    252 
    253   //
    254   // Get the String from the Hii Database
    255   //
    256   Data = HiiGetPackageString (
    257              &(StructureNode->ProducerName),
    258              *((EFI_STRING_ID *) RecordData),
    259              NULL
    260              );
    261   if (Data == NULL) {
    262     return EFI_INVALID_PARAMETER;
    263   }
    264 
    265   StringLength = (UINT32)StrLen (Data);
    266   //
    267   // Count the string size including the terminating 0.
    268   //
    269   if (StringLength == 0) {
    270     *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + Offset) = 0;
    271     FreePool (Data);
    272     return EFI_SUCCESS;
    273   }
    274 
    275   if (StringLength > SMBIOS_STRING_MAX_LENGTH) {
    276     //
    277     // Too long a string
    278     //
    279     FreePool (Data);
    280     return EFI_INVALID_PARAMETER;
    281   }
    282 
    283   Smbios = GetSmbiosProtocol();
    284   ASSERT (Smbios != NULL);
    285 
    286   //
    287   // Convert Unicode string to Ascii string which only supported by SMBIOS.
    288   //
    289   ZeroMem (AsciiData, SMBIOS_STRING_MAX_LENGTH);
    290   UnicodeStrToAsciiStr (Data, AsciiData);
    291 
    292   //
    293   // if the field at offset is already filled with some value,
    294   // find out the string it points to
    295   //
    296   OrigStringNumber = *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + Offset);
    297   if (OrigStringNumber != 0) {
    298     DEBUG ((EFI_D_ERROR, "[SMBIOSThunk] Update %dth string for type[%d],offset[0x%x],handle[0x%x] to [%s]\n",
    299             OrigStringNumber, StructureNode->SmbiosType, Offset, StructureNode->SmbiosHandle, AsciiData));
    300 
    301     //
    302     // If original string number is not zero, just update string
    303     //
    304     Status = Smbios->UpdateString (Smbios, &StructureNode->SmbiosHandle, &OrigStringNumber, AsciiData);
    305     if (EFI_ERROR (Status)) {
    306       DEBUG ((EFI_D_ERROR, "[SMBIOSThunk] Fail to update %dth string in offset 0x%x for handle:0x%x type:0x%x\n",
    307              OrigStringNumber, Offset, StructureNode->SmbiosHandle, StructureNode->SmbiosType));
    308       ASSERT_EFI_ERROR (Status);
    309       return Status;
    310     }
    311   } else {
    312     //
    313     // If the string has not been filled in SMBIOS database, remove it and add again
    314     // with string appended.
    315     //
    316     Status = GetSmbiosStructureSize (StructureNode->Structure, &OrigStructureSize, &CountOfStrings);
    317     ASSERT_EFI_ERROR (Status);
    318 
    319     if (CountOfStrings == 0) {
    320       NewStructureSize = OrigStructureSize + StringLength;
    321     } else {
    322       NewStructureSize = OrigStructureSize + StringLength + 1;
    323     }
    324 
    325     NewRecord = AllocateZeroPool (NewStructureSize);
    326     if (NewRecord == NULL) {
    327       return EFI_OUT_OF_RESOURCES;
    328     }
    329     CopyMem (NewRecord, StructureNode->Structure, OrigStructureSize);
    330 
    331     //
    332     // Copy new string into tail of original SMBIOS record buffer.
    333     //
    334     if (CountOfStrings == 0) {
    335       AsciiStrCpy ((CHAR8 *)NewRecord + OrigStructureSize - 2, AsciiData);
    336     } else {
    337       AsciiStrCpy ((CHAR8 *)NewRecord + OrigStructureSize - 1, AsciiData);
    338     }
    339     DEBUG ((EFI_D_ERROR, "[SMBIOSThunk] Type(%d) offset(0x%x) StringNumber:%d\n",
    340             StructureNode->SmbiosType, Offset, CountOfStrings + 1));
    341     //
    342     // Update string reference number
    343     //
    344     *(UINT8 *) ((UINT8 *) NewRecord + Offset) = (UINT8) (CountOfStrings + 1);
    345     SmbiosHandle = StructureNode->SmbiosHandle;
    346 
    347     //
    348     // Remove original SMBIOS record and add new one
    349     //
    350     Status = Smbios->Remove (Smbios, StructureNode->SmbiosHandle);
    351     ASSERT_EFI_ERROR (Status);
    352 
    353     //
    354     // Add new SMBIOS record
    355     //
    356     Status = Smbios->Add (Smbios, NULL, &SmbiosHandle, NewRecord);
    357     ASSERT_EFI_ERROR (Status);
    358 
    359     StructureNode->SmbiosHandle = SmbiosHandle;
    360 
    361     FreePool (NewRecord);
    362   }
    363 
    364   //
    365   // The SMBIOS record buffer maybe re-allocated in SMBIOS database,
    366   // so update cached buffer pointer in DataHub structure list.
    367   //
    368   StructureNode->Structure = GetSmbiosBufferFromHandle (
    369                                StructureNode->SmbiosHandle,
    370                                StructureNode->SmbiosType,
    371                                NULL
    372                                );
    373   ASSERT (StructureNode->Structure != NULL);
    374 
    375   //
    376   // The string update action maybe lead the record is re-allocated in SMBIOS database
    377   // so update cached record pointer
    378   //
    379   Status = GetSmbiosStructureSize (StructureNode->Structure, &StructureNode->StructureSize, &CountOfStrings);
    380   ASSERT_EFI_ERROR (Status);
    381 
    382   return EFI_SUCCESS;
    383 }
    384 
    385 /**
    386   Find a handle that matches the Link Data and the target Smbios type.
    387 
    388   @param  TargetType     the Smbios type
    389   @param  SubClass       the SubClass
    390   @param  LinkData       Specifies Instance, SubInstance and ProducerName
    391   @param  Handle         the HandleNum found
    392 
    393   @retval EFI_NOT_FOUND Can not find the record according to handle
    394   @retval EFI_SUCCESS   Success to find the handle
    395 **/
    396 EFI_STATUS
    397 SmbiosFindHandle (
    398   IN      UINT8               TargetType,
    399   IN      EFI_GUID            *SubClass,
    400   IN      EFI_INTER_LINK_DATA *LinkData,
    401   IN OUT  UINT16              *HandleNum
    402   )
    403 {
    404   LIST_ENTRY        *Link;
    405   SMBIOS_STRUCTURE_NODE *StructureNode;
    406 
    407   StructureNode = NULL;
    408 
    409   //
    410   // Find out the matching handle
    411   //
    412   for (Link = mStructureList.ForwardLink; Link != &mStructureList; Link = Link->ForwardLink) {
    413     StructureNode = CR (Link, SMBIOS_STRUCTURE_NODE, Link, SMBIOS_STRUCTURE_NODE_SIGNATURE);
    414     if (StructureNode->Structure->Type == TargetType &&
    415         CompareGuid (&(StructureNode->SubClass), SubClass) &&
    416         StructureNode->Instance == LinkData->Instance &&
    417         StructureNode->SubInstance == LinkData->SubInstance
    418         ) {
    419       break;
    420     }
    421   }
    422 
    423   if (Link == &mStructureList || StructureNode == NULL) {
    424     return EFI_NOT_FOUND;
    425   } else {
    426     *HandleNum = StructureNode->Structure->Handle;
    427     return EFI_SUCCESS;
    428   }
    429 }
    430 
    431 /**
    432   Fill the inter link field for a SMBIOS recorder.
    433 
    434   Some SMBIOS recorder need to reference the handle of another SMBIOS record. But
    435   maybe another SMBIOS record has not been added, so put the InterLink request into
    436   a linked list and the interlink will be fixedup when a new SMBIOS record is added.
    437 
    438   @param StructureNode        Point to SMBIOS_STRUCTURE_NODE which reference another record's handle
    439   @param LinkSmbiosNodeOffset The offset in this record for holding the handle of another SMBIOS record
    440   @param LinkSmbiosType       The type of SMBIOS record want to be linked.
    441   @param InterLink            Point to EFI_INTER_LINK_DATA will be put linked list.
    442   @param SubClassGuid         The guid of subclass for linked SMBIOS record.
    443 
    444   @retval EFI_SUCESS  The linked record is found and no need fixup in future.
    445   @retval !EFI_SUCESS The linked record can not be found and InterLink is put a fixing-p linked list.
    446 **/
    447 EFI_STATUS
    448 SmbiosFldInterLink (
    449   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
    450   IN      UINT16                    LinkSmbiosNodeOffset,
    451   IN      UINT8                     LinkSmbiosType,
    452   IN      EFI_INTER_LINK_DATA       *InterLink,
    453   IN      EFI_GUID                  *SubClassGuid
    454   )
    455 {
    456   EFI_STATUS                  Status;
    457   SMBIOS_LINK_DATA_FIXUP_NODE *LinkDataFixupNode;
    458   UINT16                      StructureHandle;
    459 
    460   Status            = EFI_SUCCESS;
    461   LinkDataFixupNode = NULL;
    462 
    463   Status = SmbiosFindHandle (
    464             LinkSmbiosType, // Smbios type
    465             SubClassGuid,
    466             InterLink,
    467             &StructureHandle
    468             );
    469   if (!EFI_ERROR (Status)) {
    470     //
    471     // Set the handle
    472     //
    473     CopyMem (
    474       (UINT8 *) (StructureNode->Structure) + LinkSmbiosNodeOffset,
    475       &StructureHandle,
    476       sizeof (EFI_SMBIOS_HANDLE)
    477       );
    478   } else {
    479     //
    480     // Hang this in the link data fixup node
    481     //
    482     LinkDataFixupNode = AllocateZeroPool (sizeof (SMBIOS_LINK_DATA_FIXUP_NODE));
    483     if (LinkDataFixupNode == NULL) {
    484       return EFI_OUT_OF_RESOURCES;
    485     }
    486 
    487     LinkDataFixupNode->Signature  = SMBIOS_LINK_DATA_FIXUP_NODE_SIGNATURE;
    488     LinkDataFixupNode->Offset     = LinkSmbiosNodeOffset;
    489     LinkDataFixupNode->TargetType = LinkSmbiosType;
    490     CopyMem (
    491       &LinkDataFixupNode->SubClass,
    492       SubClassGuid,
    493       sizeof (EFI_GUID)
    494       );
    495     CopyMem (
    496       &LinkDataFixupNode->LinkData,
    497       InterLink,
    498       sizeof (EFI_INTER_LINK_DATA)
    499       );
    500     InsertTailList (
    501       &StructureNode->LinkDataFixup,
    502       &(LinkDataFixupNode->Link)
    503       );
    504   }
    505 
    506   return Status;
    507 }
    508 
    509 /**
    510   Field Filling Function. Transform an EFI_EXP_BASE10_DATA to a word, with 'Mega'
    511   as the unit.
    512 
    513   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
    514   @param Offset           Offset of SMBIOS record which RecordData will be filled.
    515   @param RecordData       RecordData buffer will be filled.
    516   @param RecordDataSize   The size of RecordData buffer.
    517 
    518   @retval EFI_INVALID_PARAMETER  RecordDataSize is invalid.
    519   @retval EFI_SUCCESS            RecordData is successed to be filled into given SMBIOS record.
    520 **/
    521 EFI_STATUS
    522 SmbiosFldBase10ToWordWithMega (
    523   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
    524   IN      UINT32                    Offset,
    525   IN      VOID                      *RecordData,
    526   IN      UINT32                    RecordDataSize
    527   )
    528 {
    529   EFI_EXP_BASE10_DATA *Base10Data;
    530   INT16               Value;
    531   INT16               Exponent;
    532 
    533   if (RecordDataSize != sizeof (EFI_EXP_BASE10_DATA)) {
    534     return EFI_INVALID_PARAMETER;
    535   }
    536 
    537   Base10Data  = RecordData;
    538   Value       = Base10Data->Value;
    539   Exponent    = Base10Data->Exponent;
    540 
    541   Exponent -= 6;
    542   while (Exponent != 0) {
    543     if (Exponent > 0) {
    544       Value = (INT16) (Value * 10);
    545       Exponent--;
    546     } else {
    547       Value = (INT16) (Value / 10);
    548       Exponent++;
    549     }
    550   }
    551 
    552   CopyMem (
    553     (UINT8 *) (StructureNode->Structure) + Offset,
    554     &Value,
    555     2
    556     );
    557 
    558   return EFI_SUCCESS;
    559 }
    560 
    561 /**
    562   Field Filling Function. Transform an EFI_EXP_BASE2_DATA to a word, with 'Kilo'
    563   as the unit. Granularity implemented for Cache Size.
    564 
    565   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
    566   @param Offset           Offset of SMBIOS record which RecordData will be filled.
    567   @param RecordData       RecordData buffer will be filled.
    568   @param RecordDataSize   The size of RecordData buffer.
    569 
    570   @retval EFI_INVALID_PARAMETER  RecordDataSize is invalid.
    571   @retval EFI_SUCCESS            RecordData is successed to be filled into given SMBIOS record.
    572 **/
    573 EFI_STATUS
    574 SmbiosFldBase2ToWordWithKilo (
    575   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
    576   IN      UINT32                    Offset,
    577   IN      VOID                      *RecordData,
    578   IN      UINT32                    RecordDataSize
    579   )
    580 {
    581   EFI_EXP_BASE2_DATA  *Base2Data;
    582   UINT32              Value;
    583   UINT16              Exponent;
    584 
    585   if (RecordDataSize != sizeof (EFI_EXP_BASE2_DATA)) {
    586     return EFI_INVALID_PARAMETER;
    587   }
    588 
    589   Base2Data = RecordData;
    590   Value     = Base2Data->Value;
    591   Exponent  = Base2Data->Exponent;
    592 
    593   Exponent -= 10;
    594   Value <<= Exponent;
    595 
    596   //
    597   // Implement cache size granularity
    598   //
    599   if(Value >= 0x8000) {
    600     Value >>= 6;
    601     Value |=  0x8000;
    602   }
    603 
    604   CopyMem (
    605     (UINT8 *) (StructureNode->Structure) + Offset,
    606     &Value,
    607     2
    608     );
    609 
    610   return EFI_SUCCESS;
    611 }
    612 
    613 /**
    614   Field Filling Function. Transform an EFI_EXP_BASE2_DATA to a byte, with '64k'
    615   as the unit.
    616 
    617   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
    618   @param Offset           Offset of SMBIOS record which RecordData will be filled.
    619   @param RecordData       RecordData buffer will be filled.
    620   @param RecordDataSize   The size of RecordData buffer.
    621 
    622   @retval EFI_INVALID_PARAMETER  RecordDataSize is invalid.
    623   @retval EFI_SUCCESS            RecordData is successed to be filled into given SMBIOS record.
    624 **/
    625 EFI_STATUS
    626 SmbiosFldBase2ToByteWith64K (
    627   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
    628   IN      UINT32                    Offset,
    629   IN      VOID                      *RecordData,
    630   IN      UINT32                    RecordDataSize
    631   )
    632 {
    633   EFI_EXP_BASE2_DATA  *Base2Data;
    634   UINT16              Value;
    635   UINT16              Exponent;
    636 
    637   if (RecordDataSize != sizeof (EFI_EXP_BASE2_DATA)) {
    638     return EFI_INVALID_PARAMETER;
    639   }
    640 
    641   Base2Data = RecordData;
    642   Value     = Base2Data->Value;
    643   Exponent  = Base2Data->Exponent;
    644   Exponent -= 16;
    645   Value <<= Exponent;
    646 
    647   CopyMem (
    648     (UINT8 *) (StructureNode->Structure) + Offset,
    649     &Value,
    650     1
    651     );
    652 
    653   return EFI_SUCCESS;
    654 }
    655 
    656 /**
    657   Field Filling Function. Transform an EFI_EXP_BASE2_DATA to a word, with 10exp-9
    658   as the unit.
    659 
    660   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
    661   @param Offset           Offset of SMBIOS record which RecordData will be filled.
    662   @param RecordData       RecordData buffer will be filled.
    663   @param RecordDataSize   The size of RecordData buffer.
    664 
    665   @retval EFI_INVALID_PARAMETER  RecordDataSize is invalid.
    666   @retval EFI_SUCCESS            RecordData is successed to be filled into given SMBIOS record.
    667 **/
    668 EFI_STATUS
    669 SmbiosFldBase10ToByteWithNano (
    670   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
    671   IN      UINT32                    Offset,
    672   IN      VOID                      *RecordData,
    673   IN      UINT32                    RecordDataSize
    674   )
    675 {
    676   EFI_EXP_BASE10_DATA *Base10Data;
    677   INT16               Value;
    678   INT16               Exponent;
    679 
    680   if (RecordDataSize != sizeof (EFI_EXP_BASE2_DATA)) {
    681     return EFI_INVALID_PARAMETER;
    682   }
    683 
    684   Base10Data  = RecordData;
    685   Value       = Base10Data->Value;
    686   Exponent    = Base10Data->Exponent;
    687 
    688   Exponent += 9;
    689   while (Exponent != 0) {
    690     if (Exponent > 0) {
    691       Value = (INT16) (Value * 10);
    692       Exponent--;
    693     } else {
    694       Value = (INT16) (Value / 10);
    695       Exponent++;
    696     }
    697   }
    698 
    699   * (UINT8 *) ((UINT8 *) (StructureNode->Structure) + Offset) = (UINT8) Value;
    700 
    701   return EFI_SUCCESS;
    702 }
    703 
    704 /**
    705   Field Filling Function: truncate record data to byte and fill in the
    706   field as indicated by Offset.
    707 
    708   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
    709   @param Offset           Offset of SMBIOS record which RecordData will be filled.
    710   @param RecordData       RecordData buffer will be filled.
    711   @param RecordDataSize   The size of RecordData buffer.
    712 
    713   @retval EFI_INVALID_PARAMETER  RecordDataSize is invalid.
    714   @retval EFI_SUCCESS            RecordData is successed to be filled into given SMBIOS record.
    715 **/
    716 EFI_STATUS
    717 SmbiosFldTruncateToByte (
    718   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
    719   IN      UINT32                    Offset,
    720   IN      VOID                      *RecordData,
    721   IN      UINT32                    RecordDataSize
    722   )
    723 {
    724   EFI_STATUS  Status;
    725 
    726   Status = EFI_SUCCESS;
    727 
    728   //
    729   // Truncate the data to 8 bits
    730   //
    731   *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + Offset) = (UINT8) (*(UINT8 *) RecordData);
    732 
    733   return Status;
    734 }
    735 
    736 /**
    737   Field Filling Function: truncate record data to byte and fill in the
    738   field as indicated by Offset.
    739 
    740   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
    741   @param Offset           Offset of SMBIOS record which RecordData will be filled.
    742   @param RecordData       RecordData buffer will be filled.
    743   @param RecordDataSize   The size of RecordData buffer.
    744 
    745   @retval EFI_INVALID_PARAMETER  RecordDataSize is invalid.
    746   @retval EFI_SUCCESS            RecordData is successed to be filled into given SMBIOS record.
    747 **/
    748 EFI_STATUS
    749 SmbiosFldTruncateToWord (
    750   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
    751   IN      UINT32                    Offset,
    752   IN      VOID                      *RecordData,
    753   IN      UINT32                    RecordDataSize
    754   )
    755 {
    756   EFI_STATUS  Status;
    757 
    758   Status = EFI_SUCCESS;
    759 
    760   //
    761   // Truncate the data to 8 bits
    762   //
    763   CopyMem (
    764     (UINT8 *) (StructureNode->Structure) + Offset,
    765     RecordData,
    766     2
    767     );
    768 
    769   return Status;
    770 }
    771 
    772 /**
    773   Check if OEM structure has included 2 trailing 0s in data record.
    774 
    775   @param RecordData       Point to record data will be checked.
    776   @param RecordDataSize   The size of record data.
    777 
    778   @retval 0    2 trailing 0s exist in unformatted section
    779   @retval 1    1 trailing 0 exists at the end of unformatted section
    780   @retval -1   There is no 0 at the end of unformatted section
    781 **/
    782 INT8
    783 SmbiosCheckTrailingZero (
    784   IN      VOID                      *RecordData,
    785   IN      UINT32                    RecordDataSize
    786   )
    787 {
    788   SMBIOS_STRUCTURE  *Smbios;
    789   CHAR8             *Start;
    790   CHAR8             *End;
    791 
    792   Smbios = (SMBIOS_STRUCTURE *) RecordData;
    793 
    794   //
    795   // Skip over formatted section
    796   //
    797   Start = (CHAR8 *) ((UINT8 *) Smbios + Smbios->Length);
    798   End   = (CHAR8 *) RecordData + RecordDataSize;
    799 
    800   //
    801   // Unformatted section exists
    802   //
    803   while (Start < End - 1) {
    804     //
    805     // Avoid unaligned issue on IPF
    806     //
    807     if ((*Start == 0) && (*(Start + 1) == 0)) {
    808       //
    809       // 2 trailing 0s exist in unformatted section
    810       //
    811       return 0;
    812     }
    813     Start++;
    814   }
    815 
    816   if (Start == End - 1) {
    817     //
    818     // Check if there has been already 1 trailing 0
    819     //
    820     if (*Start == 0) {
    821       return 1;
    822     }
    823   }
    824 
    825   //
    826   // There is no 0 at the end of unformatted section
    827   //
    828   return -1;
    829 }
    830