1 /** @file
2 
3   A DXE_DRIVER providing SMRAM access by producing EFI_SMM_ACCESS2_PROTOCOL.
4 
5   Q35 TSEG is expected to have been verified and set up by the SmmAccessPei
6   driver.
7 
8   Copyright (C) 2013, 2015, Red Hat, Inc.<BR>
9   Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
10 
11   SPDX-License-Identifier: BSD-2-Clause-Patent
12 
13 **/
14 
15 #include <Library/DebugLib.h>
16 #include <Library/PcdLib.h>
17 #include <Library/UefiBootServicesTableLib.h>
18 #include <Protocol/SmmAccess2.h>
19 
20 #include "SmramInternal.h"
21 
22 /**
23   Opens the SMRAM area to be accessible by a boot-service driver.
24 
25   This function "opens" SMRAM so that it is visible while not inside of SMM.
26   The function should return EFI_UNSUPPORTED if the hardware does not support
27   hiding of SMRAM. The function should return EFI_DEVICE_ERROR if the SMRAM
28   configuration is locked.
29 
30   @param[in] This           The EFI_SMM_ACCESS2_PROTOCOL instance.
31 
32   @retval EFI_SUCCESS       The operation was successful.
33   @retval EFI_UNSUPPORTED   The system does not support opening and closing of
34                             SMRAM.
35   @retval EFI_DEVICE_ERROR  SMRAM cannot be opened, perhaps because it is
36                             locked.
37 **/
38 STATIC
39 EFI_STATUS
40 EFIAPI
SmmAccess2DxeOpen(IN EFI_SMM_ACCESS2_PROTOCOL * This)41 SmmAccess2DxeOpen (
42   IN EFI_SMM_ACCESS2_PROTOCOL  *This
43   )
44 {
45   return SmramAccessOpen (&This->LockState, &This->OpenState);
46 }
47 
48 /**
49   Inhibits access to the SMRAM.
50 
51   This function "closes" SMRAM so that it is not visible while outside of SMM.
52   The function should return EFI_UNSUPPORTED if the hardware does not support
53   hiding of SMRAM.
54 
55   @param[in] This           The EFI_SMM_ACCESS2_PROTOCOL instance.
56 
57   @retval EFI_SUCCESS       The operation was successful.
58   @retval EFI_UNSUPPORTED   The system does not support opening and closing of
59                             SMRAM.
60   @retval EFI_DEVICE_ERROR  SMRAM cannot be closed.
61 **/
62 STATIC
63 EFI_STATUS
64 EFIAPI
SmmAccess2DxeClose(IN EFI_SMM_ACCESS2_PROTOCOL * This)65 SmmAccess2DxeClose (
66   IN EFI_SMM_ACCESS2_PROTOCOL  *This
67   )
68 {
69   return SmramAccessClose (&This->LockState, &This->OpenState);
70 }
71 
72 /**
73   Inhibits access to the SMRAM.
74 
75   This function prohibits access to the SMRAM region.  This function is usually
76   implemented such that it is a write-once operation.
77 
78   @param[in] This          The EFI_SMM_ACCESS2_PROTOCOL instance.
79 
80   @retval EFI_SUCCESS      The device was successfully locked.
81   @retval EFI_UNSUPPORTED  The system does not support locking of SMRAM.
82 **/
83 STATIC
84 EFI_STATUS
85 EFIAPI
SmmAccess2DxeLock(IN EFI_SMM_ACCESS2_PROTOCOL * This)86 SmmAccess2DxeLock (
87   IN EFI_SMM_ACCESS2_PROTOCOL  *This
88   )
89 {
90   return SmramAccessLock (&This->LockState, &This->OpenState);
91 }
92 
93 /**
94   Queries the memory controller for the possible regions that will support
95   SMRAM.
96 
97   @param[in]     This           The EFI_SMM_ACCESS2_PROTOCOL instance.
98   @param[in,out] SmramMapSize   A pointer to the size, in bytes, of the
99                                 SmramMemoryMap buffer.
100   @param[in,out] SmramMap       A pointer to the buffer in which firmware
101                                 places the current memory map.
102 
103   @retval EFI_SUCCESS           The chipset supported the given resource.
104   @retval EFI_BUFFER_TOO_SMALL  The SmramMap parameter was too small.  The
105                                 current buffer size needed to hold the memory
106                                 map is returned in SmramMapSize.
107 **/
108 STATIC
109 EFI_STATUS
110 EFIAPI
SmmAccess2DxeGetCapabilities(IN CONST EFI_SMM_ACCESS2_PROTOCOL * This,IN OUT UINTN * SmramMapSize,IN OUT EFI_SMRAM_DESCRIPTOR * SmramMap)111 SmmAccess2DxeGetCapabilities (
112   IN CONST EFI_SMM_ACCESS2_PROTOCOL  *This,
113   IN OUT UINTN                       *SmramMapSize,
114   IN OUT EFI_SMRAM_DESCRIPTOR        *SmramMap
115   )
116 {
117   return SmramAccessGetCapabilities (This->LockState, This->OpenState,
118            SmramMapSize, SmramMap);
119 }
120 
121 //
122 // LockState and OpenState will be filled in by the entry point.
123 //
124 STATIC EFI_SMM_ACCESS2_PROTOCOL mAccess2 = {
125   &SmmAccess2DxeOpen,
126   &SmmAccess2DxeClose,
127   &SmmAccess2DxeLock,
128   &SmmAccess2DxeGetCapabilities
129 };
130 
131 //
132 // Entry point of this driver.
133 //
134 EFI_STATUS
135 EFIAPI
SmmAccess2DxeEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)136 SmmAccess2DxeEntryPoint (
137   IN EFI_HANDLE       ImageHandle,
138   IN EFI_SYSTEM_TABLE *SystemTable
139   )
140 {
141   //
142   // This module should only be included if SMRAM support is required.
143   //
144   ASSERT (FeaturePcdGet (PcdSmmSmramRequire));
145 
146   InitQ35TsegMbytes ();
147   GetStates (&mAccess2.LockState, &mAccess2.OpenState);
148 
149   //
150   // SmramAccessLock() depends on "mQ35SmramAtDefaultSmbase"; init the latter
151   // just before exposing the former via EFI_SMM_ACCESS2_PROTOCOL.Lock().
152   //
153   InitQ35SmramAtDefaultSmbase ();
154 
155   return gBS->InstallMultipleProtocolInterfaces (&ImageHandle,
156                 &gEfiSmmAccess2ProtocolGuid, &mAccess2,
157                 NULL);
158 }
159