Home | History | Annotate | Download | only in VariableInfo
      1 /** @file
      2   If the Variable services have PcdVariableCollectStatistics set to TRUE then
      3   this utility will print out the statistics information. You can use console
      4   redirection to capture the data.
      5 
      6   Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
      7   This program and the accompanying materials
      8   are licensed and made available under the terms and conditions of the BSD License
      9   which accompanies this distribution.  The full text of the license may be found at
     10   http://opensource.org/licenses/bsd-license.php
     11 
     12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 
     17 #include <Uefi.h>
     18 #include <Library/UefiLib.h>
     19 #include <Library/UefiApplicationEntryPoint.h>
     20 #include <Library/BaseMemoryLib.h>
     21 #include <Library/BaseLib.h>
     22 #include <Library/MemoryAllocationLib.h>
     23 #include <Library/DebugLib.h>
     24 #include <Library/UefiBootServicesTableLib.h>
     25 
     26 #include <Guid/VariableFormat.h>
     27 #include <Guid/SmmVariableCommon.h>
     28 #include <Protocol/SmmCommunication.h>
     29 #include <Protocol/SmmVariable.h>
     30 
     31 EFI_SMM_COMMUNICATION_PROTOCOL  *mSmmCommunication = NULL;
     32 
     33 /**
     34   This function get the variable statistics data from SMM variable driver.
     35 
     36   @param[in, out] SmmCommunicateHeader In input, a pointer to a collection of data that will
     37                                        be passed into an SMM environment. In output, a pointer
     38                                        to a collection of data that comes from an SMM environment.
     39   @param[in, out] SmmCommunicateSize   The size of the SmmCommunicateHeader.
     40 
     41   @retval EFI_SUCCESS               Get the statistics data information.
     42   @retval EFI_NOT_FOUND             Not found.
     43   @retval EFI_BUFFER_TO_SMALL       DataSize is too small for the result.
     44 
     45 **/
     46 EFI_STATUS
     47 EFIAPI
     48 GetVariableStatisticsData (
     49   IN OUT  EFI_SMM_COMMUNICATE_HEADER  *SmmCommunicateHeader,
     50   IN OUT  UINTN                       *SmmCommunicateSize
     51   )
     52 {
     53   EFI_STATUS                          Status;
     54   SMM_VARIABLE_COMMUNICATE_HEADER     *SmmVariableFunctionHeader;
     55 
     56   CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);
     57   SmmCommunicateHeader->MessageLength = *SmmCommunicateSize - OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);
     58 
     59   SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) &SmmCommunicateHeader->Data[0];
     60   SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_GET_STATISTICS;
     61 
     62   Status = mSmmCommunication->Communicate (mSmmCommunication, SmmCommunicateHeader, SmmCommunicateSize);
     63   ASSERT_EFI_ERROR (Status);
     64 
     65   Status = SmmVariableFunctionHeader->ReturnStatus;
     66   return Status;
     67 }
     68 
     69 /**
     70 
     71   This function get and print the variable statistics data from SMM variable driver.
     72 
     73   @retval EFI_SUCCESS               Print the statistics information successfully.
     74   @retval EFI_NOT_FOUND             Not found the statistics information.
     75 
     76 **/
     77 EFI_STATUS
     78 PrintInfoFromSmm (
     79   VOID
     80   )
     81 {
     82   EFI_STATUS                                     Status;
     83   VARIABLE_INFO_ENTRY                            *VariableInfo;
     84   EFI_SMM_COMMUNICATE_HEADER                     *CommBuffer;
     85   UINTN                                          RealCommSize;
     86   UINTN                                          CommSize;
     87   SMM_VARIABLE_COMMUNICATE_HEADER                *FunctionHeader;
     88   EFI_SMM_VARIABLE_PROTOCOL                      *Smmvariable;
     89 
     90   Status = gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **) &Smmvariable);
     91   if (EFI_ERROR (Status)) {
     92     return Status;
     93   }
     94 
     95   Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &mSmmCommunication);
     96   if (EFI_ERROR (Status)) {
     97     return Status;
     98   }
     99 
    100   CommSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
    101   RealCommSize = CommSize;
    102   CommBuffer = AllocateZeroPool (CommSize);
    103   ASSERT (CommBuffer != NULL);
    104 
    105   Print (L"Non-Volatile SMM Variables:\n");
    106   do {
    107     Status = GetVariableStatisticsData (CommBuffer, &CommSize);
    108     if (Status == EFI_BUFFER_TOO_SMALL) {
    109       FreePool (CommBuffer);
    110       CommBuffer = AllocateZeroPool (CommSize);
    111       ASSERT (CommBuffer != NULL);
    112       RealCommSize = CommSize;
    113       Status = GetVariableStatisticsData (CommBuffer, &CommSize);
    114     }
    115 
    116     if (EFI_ERROR (Status) || (CommSize <= SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE)) {
    117       break;
    118     }
    119 
    120     if (CommSize < RealCommSize) {
    121       CommSize = RealCommSize;
    122     }
    123 
    124     FunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) CommBuffer->Data;
    125     VariableInfo   = (VARIABLE_INFO_ENTRY *) FunctionHeader->Data;
    126 
    127     if (!VariableInfo->Volatile) {
    128       Print (
    129           L"%g R%03d(%03d) W%03d D%03d:%s\n",
    130           &VariableInfo->VendorGuid,
    131           VariableInfo->ReadCount,
    132           VariableInfo->CacheCount,
    133           VariableInfo->WriteCount,
    134           VariableInfo->DeleteCount,
    135           (CHAR16 *)(VariableInfo + 1)
    136           );
    137     }
    138   } while (TRUE);
    139 
    140   Print (L"Volatile SMM Variables:\n");
    141   ZeroMem (CommBuffer, CommSize);
    142   do {
    143     Status = GetVariableStatisticsData (CommBuffer, &CommSize);
    144     if (Status == EFI_BUFFER_TOO_SMALL) {
    145       FreePool (CommBuffer);
    146       CommBuffer = AllocateZeroPool (CommSize);
    147       ASSERT (CommBuffer != NULL);
    148       RealCommSize = CommSize;
    149       Status = GetVariableStatisticsData (CommBuffer, &CommSize);
    150     }
    151 
    152     if (EFI_ERROR (Status) || (CommSize <= SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE)) {
    153       break;
    154     }
    155 
    156     if (CommSize < RealCommSize) {
    157       CommSize = RealCommSize;
    158     }
    159 
    160     FunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) CommBuffer->Data;
    161     VariableInfo   = (VARIABLE_INFO_ENTRY *) FunctionHeader->Data;
    162 
    163     if (VariableInfo->Volatile) {
    164       Print (
    165           L"%g R%03d(%03d) W%03d D%03d:%s\n",
    166           &VariableInfo->VendorGuid,
    167           VariableInfo->ReadCount,
    168           VariableInfo->CacheCount,
    169           VariableInfo->WriteCount,
    170           VariableInfo->DeleteCount,
    171           (CHAR16 *)(VariableInfo + 1)
    172           );
    173     }
    174   } while (TRUE);
    175 
    176   FreePool (CommBuffer);
    177   return Status;
    178 }
    179 
    180 /**
    181   The user Entry Point for Application. The user code starts with this function
    182   as the real entry point for the image goes into a library that calls this
    183   function.
    184 
    185   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
    186   @param[in] SystemTable    A pointer to the EFI System Table.
    187 
    188   @retval EFI_SUCCESS       The entry point is executed successfully.
    189   @retval other             Some error occurs when executing this entry point.
    190 
    191 **/
    192 EFI_STATUS
    193 EFIAPI
    194 UefiMain (
    195   IN EFI_HANDLE        ImageHandle,
    196   IN EFI_SYSTEM_TABLE  *SystemTable
    197   )
    198 {
    199   EFI_STATUS            Status;
    200   VARIABLE_INFO_ENTRY   *VariableInfo;
    201   VARIABLE_INFO_ENTRY   *Entry;
    202 
    203   Status = EfiGetSystemConfigurationTable (&gEfiVariableGuid, (VOID **)&Entry);
    204   if (EFI_ERROR (Status) || (Entry == NULL)) {
    205     Status = EfiGetSystemConfigurationTable (&gEfiAuthenticatedVariableGuid, (VOID **)&Entry);
    206   }
    207 
    208   if (EFI_ERROR (Status) || (Entry == NULL)) {
    209     Status = PrintInfoFromSmm ();
    210     if (!EFI_ERROR (Status)) {
    211       return Status;
    212     }
    213   }
    214 
    215   if (!EFI_ERROR (Status) && (Entry != NULL)) {
    216     Print (L"Non-Volatile EFI Variables:\n");
    217     VariableInfo = Entry;
    218     do {
    219       if (!VariableInfo->Volatile) {
    220         Print (
    221           L"%g R%03d(%03d) W%03d D%03d:%s\n",
    222           &VariableInfo->VendorGuid,
    223           VariableInfo->ReadCount,
    224           VariableInfo->CacheCount,
    225           VariableInfo->WriteCount,
    226           VariableInfo->DeleteCount,
    227           VariableInfo->Name
    228           );
    229       }
    230 
    231       VariableInfo = VariableInfo->Next;
    232     } while (VariableInfo != NULL);
    233 
    234     Print (L"Volatile EFI Variables:\n");
    235     VariableInfo = Entry;
    236     do {
    237       if (VariableInfo->Volatile) {
    238         Print (
    239           L"%g R%03d(%03d) W%03d D%03d:%s\n",
    240           &VariableInfo->VendorGuid,
    241           VariableInfo->ReadCount,
    242           VariableInfo->CacheCount,
    243           VariableInfo->WriteCount,
    244           VariableInfo->DeleteCount,
    245           VariableInfo->Name
    246           );
    247       }
    248       VariableInfo = VariableInfo->Next;
    249     } while (VariableInfo != NULL);
    250 
    251   } else {
    252     Print (L"Warning: Variable Dxe driver doesn't enable the feature of statistical information!\n");
    253     Print (L"If you want to see this info, please:\n");
    254     Print (L"  1. Set PcdVariableCollectStatistics as TRUE\n");
    255     Print (L"  2. Rebuild Variable Dxe driver\n");
    256     Print (L"  3. Run \"VariableInfo\" cmd again\n");
    257   }
    258 
    259   return Status;
    260 }
    261