Home | History | Annotate | Download | only in SmmAccessPei
      1 /** @file
      2 This is the driver that publishes the SMM Access Ppi
      3 instance for the Quark SOC.
      4 
      5 Copyright (c) 2013-2015 Intel Corporation.
      6 
      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 #include <PiPei.h>
     17 #include <Ppi/SmmAccess.h>
     18 #include <Guid/SmramMemoryReserve.h>
     19 #include <Library/BaseMemoryLib.h>
     20 #include <Library/MemoryAllocationLib.h>
     21 #include <Library/DebugLib.h>
     22 #include <Library/HobLib.h>
     23 #include <Library/PciLib.h>
     24 #include <Library/PeiServicesLib.h>
     25 #include <Library/QNCSmmLib.h>
     26 #include <QNCAccess.h>
     27 
     28 #define SMM_ACCESS_PRIVATE_DATA_FROM_THIS(a) \
     29   CR ( \
     30   a, \
     31   SMM_ACCESS_PRIVATE_DATA, \
     32   SmmAccess, \
     33   SMM_ACCESS_PRIVATE_DATA_SIGNATURE \
     34   )
     35 
     36 #define MAX_CPU_SOCKET      1
     37 #define MAX_SMRAM_RANGES    4
     38 
     39 typedef struct {
     40   UINTN                            Signature;
     41   EFI_HANDLE                       Handle;
     42   PEI_SMM_ACCESS_PPI               SmmAccess;
     43   UINTN                            NumberRegions;
     44   EFI_SMRAM_DESCRIPTOR             SmramDesc[MAX_SMRAM_RANGES];
     45   UINT8                            TsegSize;
     46   UINT8                            MaxBusNumber;
     47   UINT8                            SocketPopulated[MAX_CPU_SOCKET];
     48   UINT8                            SocketBusNum[MAX_CPU_SOCKET];
     49 } SMM_ACCESS_PRIVATE_DATA;
     50 
     51 #define  SMM_ACCESS_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('i', 's', 'm', 'a')
     52 
     53 
     54 EFI_STATUS
     55 EFIAPI
     56 Open (
     57   IN EFI_PEI_SERVICES           **PeiServices,
     58   IN PEI_SMM_ACCESS_PPI         *This,
     59   IN UINTN                      DescriptorIndex
     60   )
     61 /*++
     62 
     63 Routine Description:
     64 
     65   This routine accepts a request to "open" a region of SMRAM.  The
     66   region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.
     67   The use of "open" means that the memory is visible from all PEIM
     68   and SMM agents.
     69 
     70 Arguments:
     71 
     72   PeiServices      - General purpose services available to every PEIM.
     73   This             -  Pointer to the SMM Access Interface.
     74   DescriptorIndex  -  Region of SMRAM to Open.
     75 
     76 Returns:
     77 
     78   EFI_SUCCESS            -  The region was successfully opened.
     79   EFI_DEVICE_ERROR       -  The region could not be opened because locked by
     80                             chipset.
     81   EFI_INVALID_PARAMETER  -  The descriptor index was out of bounds.
     82 
     83 --*/
     84 {
     85   SMM_ACCESS_PRIVATE_DATA *SmmAccess;
     86 
     87   SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
     88 
     89   if (DescriptorIndex >= SmmAccess->NumberRegions) {
     90     return EFI_INVALID_PARAMETER;
     91   } else if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_LOCKED) {
     92     return EFI_DEVICE_ERROR;
     93   }
     94 
     95   //
     96   // Open TSEG
     97   //
     98   if (!QNCOpenSmramRegion ()) {
     99     SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED;
    100     return EFI_DEVICE_ERROR;
    101   }
    102 
    103   SmmAccess->SmramDesc[DescriptorIndex].RegionState &= ~(EFI_SMRAM_CLOSED | EFI_ALLOCATED);
    104   SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_OPEN;
    105   SmmAccess->SmmAccess.OpenState = TRUE;
    106 
    107   return EFI_SUCCESS;
    108 }
    109 
    110 EFI_STATUS
    111 EFIAPI
    112 Close (
    113   IN EFI_PEI_SERVICES        **PeiServices,
    114   IN PEI_SMM_ACCESS_PPI      *This,
    115   IN UINTN                   DescriptorIndex
    116   )
    117 /*++
    118 
    119 Routine Description:
    120 
    121   This routine accepts a request to "close" a region of SMRAM.  This is valid for
    122   compatible SMRAM region.
    123 
    124 Arguments:
    125 
    126   PeiServices      - General purpose services available to every PEIM.
    127   This             -  Pointer to the SMM Access Interface.
    128   DescriptorIndex  -  Region of SMRAM to Close.
    129 
    130 Returns:
    131 
    132   EFI_SUCCESS            -  The region was successfully closed.
    133   EFI_DEVICE_ERROR       -  The region could not be closed because locked by
    134                             chipset.
    135   EFI_INVALID_PARAMETER  -  The descriptor index was out of bounds.
    136 
    137 --*/
    138 {
    139   SMM_ACCESS_PRIVATE_DATA *SmmAccess;
    140   BOOLEAN                 OpenState;
    141   UINTN                   Index;
    142 
    143 
    144   SmmAccess     = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
    145 
    146   if (DescriptorIndex >= SmmAccess->NumberRegions) {
    147     return EFI_INVALID_PARAMETER;
    148   } else if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_LOCKED) {
    149     return EFI_DEVICE_ERROR;
    150   }
    151 
    152   if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_CLOSED) {
    153     return EFI_DEVICE_ERROR;
    154   }
    155 
    156   //
    157   // Close TSEG
    158   //
    159   if (!QNCCloseSmramRegion ()) {
    160     SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED;
    161     return EFI_DEVICE_ERROR;
    162   }
    163 
    164   SmmAccess->SmramDesc[DescriptorIndex].RegionState &= ~EFI_SMRAM_OPEN;
    165   SmmAccess->SmramDesc[DescriptorIndex].RegionState |= (EFI_SMRAM_CLOSED | EFI_ALLOCATED);
    166 
    167   //
    168   // Find out if any regions are still open
    169   //
    170   OpenState = FALSE;
    171   for (Index = 0; Index < SmmAccess->NumberRegions; Index++) {
    172     if ((SmmAccess->SmramDesc[Index].RegionState & EFI_SMRAM_OPEN) == EFI_SMRAM_OPEN) {
    173       OpenState = TRUE;
    174     }
    175   }
    176 
    177   SmmAccess->SmmAccess.OpenState = OpenState;
    178 
    179   return EFI_SUCCESS;
    180 }
    181 
    182 EFI_STATUS
    183 EFIAPI
    184 Lock (
    185   IN EFI_PEI_SERVICES          **PeiServices,
    186   IN PEI_SMM_ACCESS_PPI        *This,
    187   IN UINTN                     DescriptorIndex
    188   )
    189 /*++
    190 
    191 Routine Description:
    192 
    193   This routine accepts a request to "lock" SMRAM.  The
    194   region could be legacy AB or TSEG near top of physical memory.
    195   The use of "lock" means that the memory can no longer be opened
    196   to PEIM.
    197 
    198 Arguments:
    199 
    200   PeiServices      - General purpose services available to every PEIM.
    201   This             -  Pointer to the SMM Access Interface.
    202   DescriptorIndex  -  Region of SMRAM to Lock.
    203 
    204 Returns:
    205 
    206   EFI_SUCCESS            -  The region was successfully locked.
    207   EFI_DEVICE_ERROR       -  The region could not be locked because at least
    208                             one range is still open.
    209   EFI_INVALID_PARAMETER  -  The descriptor index was out of bounds.
    210 
    211 --*/
    212 {
    213   SMM_ACCESS_PRIVATE_DATA *SmmAccess;
    214 
    215   SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
    216 
    217   if (DescriptorIndex >= SmmAccess->NumberRegions) {
    218     return EFI_INVALID_PARAMETER;
    219   } else if (SmmAccess->SmmAccess.OpenState) {
    220     return EFI_DEVICE_ERROR;
    221   }
    222 
    223   SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED;
    224   SmmAccess->SmmAccess.LockState                     = TRUE;
    225 
    226   //
    227   // Lock TSEG
    228   //
    229   QNCLockSmramRegion ();
    230 
    231   return EFI_SUCCESS;
    232 }
    233 
    234 EFI_STATUS
    235 EFIAPI
    236 GetCapabilities (
    237   IN EFI_PEI_SERVICES                **PeiServices,
    238   IN PEI_SMM_ACCESS_PPI              *This,
    239   IN OUT UINTN                       *SmramMapSize,
    240   IN OUT EFI_SMRAM_DESCRIPTOR        *SmramMap
    241   )
    242 /*++
    243 
    244 Routine Description:
    245 
    246   This routine services a user request to discover the SMRAM
    247   capabilities of this platform.  This will report the possible
    248   ranges that are possible for SMRAM access, based upon the
    249   memory controller capabilities.
    250 
    251 Arguments:
    252 
    253   PeiServices   - General purpose services available to every PEIM.
    254   This          -  Pointer to the SMRAM Access Interface.
    255   SmramMapSize  -  Pointer to the variable containing size of the
    256                    buffer to contain the description information.
    257   SmramMap      -  Buffer containing the data describing the Smram
    258                    region descriptors.
    259 Returns:
    260 
    261   EFI_BUFFER_TOO_SMALL  -  The user did not provide a sufficient buffer.
    262   EFI_SUCCESS           -  The user provided a sufficiently-sized buffer.
    263 
    264 --*/
    265 {
    266   EFI_STATUS                Status;
    267   SMM_ACCESS_PRIVATE_DATA  *SmmAccess;
    268   UINTN                     BufferSize;
    269 
    270   SmmAccess           = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
    271   BufferSize          = SmmAccess->NumberRegions * sizeof (EFI_SMRAM_DESCRIPTOR);
    272 
    273   if (*SmramMapSize < BufferSize) {
    274     Status = EFI_BUFFER_TOO_SMALL;
    275   } else {
    276     CopyMem (SmramMap, SmmAccess->SmramDesc, *SmramMapSize);
    277     Status = EFI_SUCCESS;
    278   }
    279 
    280   *SmramMapSize = BufferSize;
    281 
    282   return Status;
    283 }
    284 
    285 
    286 EFI_STATUS
    287 EFIAPI
    288 SmmAccessPeiEntryPoint (
    289   IN       EFI_PEI_FILE_HANDLE  FileHandle,
    290   IN CONST EFI_PEI_SERVICES     **PeiServices
    291   )
    292 /*++
    293 
    294 Routine Description:
    295 
    296     This is the constructor for the SMM Access Ppi
    297 
    298 Arguments:
    299 
    300     FfsHeader       - FfsHeader.
    301     PeiServices     - General purpose services available to every PEIM.
    302 
    303 Returns:
    304 
    305   EFI_SUCCESS     -  Protocol successfully started and installed.
    306   EFI_UNSUPPORTED -  Protocol can't be started.
    307 --*/
    308 {
    309 
    310   EFI_STATUS                      Status;
    311   UINTN                           Index;
    312   EFI_SMRAM_HOB_DESCRIPTOR_BLOCK  *DescriptorBlock;
    313   SMM_ACCESS_PRIVATE_DATA         *SmmAccessPrivate;
    314   EFI_PEI_PPI_DESCRIPTOR          *PpiList;
    315   EFI_HOB_GUID_TYPE               *GuidHob;
    316 
    317   //
    318   // Initialize private data
    319   //
    320   SmmAccessPrivate = AllocatePool (sizeof(*SmmAccessPrivate));
    321   ASSERT(SmmAccessPrivate);
    322 
    323   PpiList = AllocatePool (sizeof(*PpiList));
    324   ASSERT (PpiList);
    325 
    326   //
    327   // Build SMM related information
    328   //
    329   SmmAccessPrivate->Signature = SMM_ACCESS_PRIVATE_DATA_SIGNATURE;
    330 
    331   //
    332   // Get Hob list
    333   //
    334   GuidHob    = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);
    335   DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);
    336   ASSERT (DescriptorBlock);
    337 
    338   // Get CPU Max bus number
    339 
    340   SmmAccessPrivate->MaxBusNumber = PCI_BUS_NUMBER_QNC;
    341   for (Index = 0; Index < MAX_CPU_SOCKET; Index++) {
    342     SmmAccessPrivate->SocketPopulated[Index] = TRUE;
    343     SmmAccessPrivate->SocketBusNum[Index]    = PCI_BUS_NUMBER_QNC;
    344   }
    345 
    346   //
    347   // Use the hob to publish SMRAM capabilities
    348   //
    349   ASSERT (DescriptorBlock->NumberOfSmmReservedRegions <= MAX_SMRAM_RANGES);
    350   for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) {
    351     SmmAccessPrivate->SmramDesc[Index].PhysicalStart = DescriptorBlock->Descriptor[Index].PhysicalStart;
    352     SmmAccessPrivate->SmramDesc[Index].CpuStart      = DescriptorBlock->Descriptor[Index].CpuStart;
    353     SmmAccessPrivate->SmramDesc[Index].PhysicalSize  = DescriptorBlock->Descriptor[Index].PhysicalSize;
    354     SmmAccessPrivate->SmramDesc[Index].RegionState   = DescriptorBlock->Descriptor[Index].RegionState;
    355   }
    356 
    357   SmmAccessPrivate->NumberRegions              = Index;
    358   SmmAccessPrivate->SmmAccess.Open             = Open;
    359   SmmAccessPrivate->SmmAccess.Close            = Close;
    360   SmmAccessPrivate->SmmAccess.Lock             = Lock;
    361   SmmAccessPrivate->SmmAccess.GetCapabilities  = GetCapabilities;
    362   SmmAccessPrivate->SmmAccess.LockState        = FALSE;
    363   SmmAccessPrivate->SmmAccess.OpenState        = FALSE;
    364 
    365   PpiList->Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
    366   PpiList->Guid  = &gPeiSmmAccessPpiGuid;
    367   PpiList->Ppi   = &SmmAccessPrivate->SmmAccess;
    368 
    369   Status      = (**PeiServices).InstallPpi (PeiServices, PpiList);
    370   ASSERT_EFI_ERROR(Status);
    371 
    372   DEBUG (
    373     (EFI_D_INFO, "SMM Base:Size %08X:%08X\n",
    374     (UINTN)(SmmAccessPrivate->SmramDesc[SmmAccessPrivate->NumberRegions-1].PhysicalStart),
    375     (UINTN)(SmmAccessPrivate->SmramDesc[SmmAccessPrivate->NumberRegions-1].PhysicalSize)
    376     ));
    377 
    378   SmmAccessPrivate->TsegSize = (UINT8)(SmmAccessPrivate->SmramDesc[SmmAccessPrivate->NumberRegions-1].PhysicalSize);
    379 
    380   return EFI_SUCCESS;
    381 }
    382 
    383