Home | History | Annotate | Download | only in PropertiesTableAttributesDxe
      1 /** @file
      2   This module sets default policy for attributes of EfiACPIMemoryNVS and EfiReservedMemoryType.
      3 
      4   This module sets EFI_MEMORY_XP for attributes of EfiACPIMemoryNVS and EfiReservedMemoryType
      5   in UEFI memory map, if and only of PropertiesTable is published and has BIT0 set.
      6 
      7 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
      8 This program and the accompanying materials
      9 are licensed and made available under the terms and conditions of the BSD License
     10 which accompanies this distribution.  The full text of the license may be found at
     11 http://opensource.org/licenses/bsd-license.php
     12 
     13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     15 
     16 **/
     17 
     18 #include <Uefi.h>
     19 #include <Library/DebugLib.h>
     20 #include <Library/UefiBootServicesTableLib.h>
     21 #include <Library/DxeServicesTableLib.h>
     22 #include <Library/UefiLib.h>
     23 #include <Library/MemoryAllocationLib.h>
     24 #include <Guid/EventGroup.h>
     25 #include <Guid/PropertiesTable.h>
     26 
     27 /**
     28   Converts a number of EFI_PAGEs to a size in bytes.
     29 
     30   NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.
     31 
     32   @param  Pages     The number of EFI_PAGES.
     33 
     34   @return  The number of bytes associated with the number of EFI_PAGEs specified
     35            by Pages.
     36 **/
     37 UINT64
     38 EfiPagesToSize (
     39   IN UINT64 Pages
     40   )
     41 {
     42   return LShiftU64 (Pages, EFI_PAGE_SHIFT);
     43 }
     44 
     45 /**
     46   Set memory attributes according to default policy.
     47 
     48   @param  MemoryMap        A pointer to the buffer in which firmware places the current memory map.
     49   @param  MemoryMapSize    Size, in bytes, of the MemoryMap buffer.
     50   @param  DescriptorSize   size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
     51 **/
     52 VOID
     53 SetMemorySpaceAttributesDefault (
     54   IN EFI_MEMORY_DESCRIPTOR  *MemoryMap,
     55   IN UINTN                  MemoryMapSize,
     56   IN UINTN                  DescriptorSize
     57   )
     58 {
     59   EFI_MEMORY_DESCRIPTOR       *MemoryMapEntry;
     60   EFI_MEMORY_DESCRIPTOR       *MemoryMapEnd;
     61   EFI_STATUS                  Status;
     62 
     63   DEBUG ((EFI_D_INFO, "SetMemorySpaceAttributesDefault\n"));
     64 
     65   MemoryMapEntry = MemoryMap;
     66   MemoryMapEnd   = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize);
     67   while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
     68     if (MemoryMapEntry->PhysicalStart < BASE_1MB) {
     69       //
     70       // Do not touch memory space below 1MB
     71       //
     72       MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
     73       continue;
     74     }
     75     switch (MemoryMapEntry->Type) {
     76     case EfiRuntimeServicesCode:
     77     case EfiRuntimeServicesData:
     78       //
     79       // should be handled later;
     80       //
     81       break;
     82     case EfiReservedMemoryType:
     83     case EfiACPIMemoryNVS:
     84       //
     85       // Handle EfiReservedMemoryType and EfiACPIMemoryNVS, because there might be firmware executable there.
     86       //
     87       DEBUG ((EFI_D_INFO, "SetMemorySpaceAttributes - %016lx - %016lx (%016lx) ...\n",
     88         MemoryMapEntry->PhysicalStart,
     89         MemoryMapEntry->PhysicalStart + EfiPagesToSize (MemoryMapEntry->NumberOfPages),
     90         MemoryMapEntry->Attribute
     91         ));
     92       Status = gDS->SetMemorySpaceCapabilities (
     93                       MemoryMapEntry->PhysicalStart,
     94                       EfiPagesToSize (MemoryMapEntry->NumberOfPages),
     95                       MemoryMapEntry->Attribute | EFI_MEMORY_XP
     96                       );
     97       DEBUG ((EFI_D_INFO, "SetMemorySpaceCapabilities - %r\n", Status));
     98       break;
     99     }
    100 
    101     MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
    102   }
    103 
    104   return ;
    105 }
    106 
    107 /**
    108   Update memory attributes according to default policy.
    109 
    110   @param[in]  Event     The Event this notify function registered to.
    111   @param[in]  Context   Pointer to the context data registered to the Event.
    112 **/
    113 VOID
    114 EFIAPI
    115 UpdateMemoryAttributesDefault (
    116   EFI_EVENT                               Event,
    117   VOID                                    *Context
    118   )
    119 {
    120   EFI_STATUS                  Status;
    121   EFI_MEMORY_DESCRIPTOR       *MemoryMap;
    122   UINTN                       MemoryMapSize;
    123   UINTN                       MapKey;
    124   UINTN                       DescriptorSize;
    125   UINT32                      DescriptorVersion;
    126   EFI_PROPERTIES_TABLE        *PropertiesTable;
    127 
    128   DEBUG ((EFI_D_INFO, "UpdateMemoryAttributesDefault\n"));
    129   Status = EfiGetSystemConfigurationTable (&gEfiPropertiesTableGuid, (VOID **) &PropertiesTable);
    130   if (EFI_ERROR (Status)) {
    131     goto Done;
    132   }
    133 
    134   ASSERT (PropertiesTable != NULL);
    135 
    136   DEBUG ((EFI_D_INFO, "MemoryProtectionAttribute - 0x%016lx\n", PropertiesTable->MemoryProtectionAttribute));
    137   if ((PropertiesTable->MemoryProtectionAttribute & EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) == 0) {
    138     goto Done;
    139   }
    140 
    141   //
    142   // Get the EFI memory map.
    143   //
    144   MemoryMapSize  = 0;
    145   MemoryMap      = NULL;
    146   Status = gBS->GetMemoryMap (
    147                   &MemoryMapSize,
    148                   MemoryMap,
    149                   &MapKey,
    150                   &DescriptorSize,
    151                   &DescriptorVersion
    152                   );
    153   ASSERT (Status == EFI_BUFFER_TOO_SMALL);
    154   do {
    155     MemoryMap = (EFI_MEMORY_DESCRIPTOR *) AllocatePool (MemoryMapSize);
    156     ASSERT (MemoryMap != NULL);
    157     Status = gBS->GetMemoryMap (
    158                     &MemoryMapSize,
    159                     MemoryMap,
    160                     &MapKey,
    161                     &DescriptorSize,
    162                     &DescriptorVersion
    163                     );
    164     if (EFI_ERROR (Status)) {
    165       FreePool (MemoryMap);
    166     }
    167   } while (Status == EFI_BUFFER_TOO_SMALL);
    168   ASSERT_EFI_ERROR (Status);
    169 
    170   SetMemorySpaceAttributesDefault (MemoryMap, MemoryMapSize, DescriptorSize);
    171 
    172 Done:
    173   gBS->CloseEvent (Event);
    174 
    175   return ;
    176 }
    177 
    178 /**
    179   The entrypoint of properties table attribute driver.
    180 
    181   @param  ImageHandle    The firmware allocated handle for the EFI image.
    182   @param  SystemTable    A pointer to the EFI System Table.
    183 
    184   @retval EFI_SUCCESS    It always returns EFI_SUCCESS.
    185 
    186 **/
    187 EFI_STATUS
    188 EFIAPI
    189 InitializePropertiesTableAttributesDxe (
    190   IN EFI_HANDLE        ImageHandle,
    191   IN EFI_SYSTEM_TABLE  *SystemTable
    192   )
    193 {
    194   EFI_STATUS  Status;
    195   EFI_EVENT   ReadyToBootEvent;
    196 
    197   Status = gBS->CreateEventEx (
    198                   EVT_NOTIFY_SIGNAL,
    199                   TPL_CALLBACK,
    200                   UpdateMemoryAttributesDefault,
    201                   NULL,
    202                   &gEfiEventReadyToBootGuid,
    203                   &ReadyToBootEvent
    204                   );
    205   ASSERT_EFI_ERROR (Status);
    206 
    207   return EFI_SUCCESS;
    208 }
    209