1 /** @file
2   Implementation of Legacy Region 2 Protocol based on Framework Legacy Region Protocol.
3 
4   Intel's Framework Legacy Region Protocol is replaced by Legacy Region 2 Protocol in PI 1.2.
5   This module produces PI Legacy Region 2 Protocol on top of Framework Legacy Region Protocol.
6 
7 Copyright (c) 2009 - 2010, 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 "LegacyRegion2OnLegacyRegionThunk.h"
19 
20 EFI_HANDLE   mLegacyRegion2Handle = NULL;
21 
22 EFI_LEGACY_REGION_PROTOCOL *mLegacyRegion;
23 
24 EFI_LEGACY_REGION2_PROTOCOL  mLegacyRegion2 = {
25   LegacyRegion2Decode,
26   LegacyRegion2Lock,
27   LegacyRegion2BootLock,
28   LegacyRegion2Unlock,
29   LegacyRegionGetInfo
30 };
31 
32 /**
33   Modify the hardware to allow (decode) or disallow (not decode) memory reads in a region.
34 
35   If the On parameter evaluates to TRUE, this function enables memory reads in the address range
36   Start to (Start + Length - 1).
37   If the On parameter evaluates to FALSE, this function disables memory reads in the address range
38   Start to (Start + Length - 1).
39 
40   @param  This[in]              Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
41   @param  Start[in]             The beginning of the physical address of the region whose attributes
42                                 should be modified.
43   @param  Length[in]            The number of bytes of memory whose attributes should be modified.
44                                 The actual number of bytes modified may be greater than the number
45                                 specified.
46   @param  Granularity[out]      The number of bytes in the last region affected. This may be less
47                                 than the total number of bytes affected if the starting address
48                                 was not aligned to a region's starting address or if the length
49                                 was greater than the number of bytes in the first region.
50   @param  On[in]                Decode / Non-Decode flag.
51 
52   @retval EFI_SUCCESS           The region's attributes were successfully modified.
53   @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
54 
55 **/
56 EFI_STATUS
57 EFIAPI
LegacyRegion2Decode(IN EFI_LEGACY_REGION2_PROTOCOL * This,IN UINT32 Start,IN UINT32 Length,OUT UINT32 * Granularity,IN BOOLEAN * On)58 LegacyRegion2Decode (
59   IN  EFI_LEGACY_REGION2_PROTOCOL  *This,
60   IN  UINT32                       Start,
61   IN  UINT32                       Length,
62   OUT UINT32                       *Granularity,
63   IN  BOOLEAN                      *On
64   )
65 {
66   if ((Start < 0xC0000) || ((Start + Length - 1) > 0xFFFFF)) {
67     return EFI_INVALID_PARAMETER;
68   }
69 
70   ASSERT (Granularity != NULL);
71   *Granularity = 0;
72 
73   return mLegacyRegion->Decode (
74                           mLegacyRegion,
75                           Start,
76                           Length,
77                           On
78                           );
79 }
80 
81 /**
82   Modify the hardware to disallow memory writes in a region.
83 
84   This function changes the attributes of a memory range to not allow writes.
85 
86   @param  This[in]              Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
87   @param  Start[in]             The beginning of the physical address of the region whose
88                                 attributes should be modified.
89   @param  Length[in]            The number of bytes of memory whose attributes should be modified.
90                                 The actual number of bytes modified may be greater than the number
91                                 specified.
92   @param  Granularity[out]      The number of bytes in the last region affected. This may be less
93                                 than the total number of bytes affected if the starting address was
94                                 not aligned to a region's starting address or if the length was
95                                 greater than the number of bytes in the first region.
96 
97   @retval EFI_SUCCESS           The region's attributes were successfully modified.
98   @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
99 
100 **/
101 EFI_STATUS
102 EFIAPI
LegacyRegion2Lock(IN EFI_LEGACY_REGION2_PROTOCOL * This,IN UINT32 Start,IN UINT32 Length,OUT UINT32 * Granularity)103 LegacyRegion2Lock (
104   IN  EFI_LEGACY_REGION2_PROTOCOL *This,
105   IN  UINT32                      Start,
106   IN  UINT32                      Length,
107   OUT UINT32                      *Granularity
108   )
109 {
110   if ((Start < 0xC0000) || ((Start + Length - 1) > 0xFFFFF)) {
111     return EFI_INVALID_PARAMETER;
112   }
113 
114   ASSERT (Granularity != NULL);
115 
116   return mLegacyRegion->Lock (
117                           mLegacyRegion,
118                           Start,
119                           Length,
120                           Granularity
121                           );
122 }
123 
124 /**
125   Modify the hardware to disallow memory attribute changes in a region.
126 
127   This function makes the attributes of a region read only. Once a region is boot-locked with this
128   function, the read and write attributes of that region cannot be changed until a power cycle has
129   reset the boot-lock attribute. Calls to Decode(), Lock() and Unlock() will have no effect.
130 
131   @param  This[in]              Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
132   @param  Start[in]             The beginning of the physical address of the region whose
133                                 attributes should be modified.
134   @param  Length[in]            The number of bytes of memory whose attributes should be modified.
135                                 The actual number of bytes modified may be greater than the number
136                                 specified.
137   @param  Granularity[out]      The number of bytes in the last region affected. This may be less
138                                 than the total number of bytes affected if the starting address was
139                                 not aligned to a region's starting address or if the length was
140                                 greater than the number of bytes in the first region.
141 
142   @retval EFI_SUCCESS           The region's attributes were successfully modified.
143   @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
144   @retval EFI_UNSUPPORTED       The chipset does not support locking the configuration registers in
145                                 a way that will not affect memory regions outside the legacy memory
146                                 region.
147 
148 **/
149 EFI_STATUS
150 EFIAPI
LegacyRegion2BootLock(IN EFI_LEGACY_REGION2_PROTOCOL * This,IN UINT32 Start,IN UINT32 Length,OUT UINT32 * Granularity)151 LegacyRegion2BootLock (
152   IN  EFI_LEGACY_REGION2_PROTOCOL         *This,
153   IN  UINT32                              Start,
154   IN  UINT32                              Length,
155   OUT UINT32                              *Granularity
156   )
157 {
158   if ((Start < 0xC0000) || ((Start + Length - 1) > 0xFFFFF)) {
159     return EFI_INVALID_PARAMETER;
160   }
161 
162   //
163   // PI Legacy Region 2 Protocol and Framework Legacy Region Protocol have different
164   // semantic of BootLock() API, so we cannot thunk to Framework Legacy Region Protocol
165   // to produce the functionality of PI version. In addition, this functionality is
166   // chipset dependent, so here we return EFI_UNSUPPORTED, which is a valid return status
167   // code specified by PI spec.
168   //
169   return EFI_UNSUPPORTED;
170 }
171 
172 /**
173   Modify the hardware to allow memory writes in a region.
174 
175   This function changes the attributes of a memory range to allow writes.
176 
177   @param  This[in]              Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
178   @param  Start[in]             The beginning of the physical address of the region whose
179                                 attributes should be modified.
180   @param  Length[in]            The number of bytes of memory whose attributes should be modified.
181                                 The actual number of bytes modified may be greater than the number
182                                 specified.
183   @param  Granularity[out]      The number of bytes in the last region affected. This may be less
184                                 than the total number of bytes affected if the starting address was
185                                 not aligned to a region's starting address or if the length was
186                                 greater than the number of bytes in the first region.
187 
188   @retval EFI_SUCCESS           The region's attributes were successfully modified.
189   @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
190 
191 **/
192 EFI_STATUS
193 EFIAPI
LegacyRegion2Unlock(IN EFI_LEGACY_REGION2_PROTOCOL * This,IN UINT32 Start,IN UINT32 Length,OUT UINT32 * Granularity)194 LegacyRegion2Unlock (
195   IN  EFI_LEGACY_REGION2_PROTOCOL  *This,
196   IN  UINT32                       Start,
197   IN  UINT32                       Length,
198   OUT UINT32                       *Granularity
199   )
200 {
201   if ((Start < 0xC0000) || ((Start + Length - 1) > 0xFFFFF)) {
202     return EFI_INVALID_PARAMETER;
203   }
204 
205   ASSERT (Granularity != NULL);
206 
207   return mLegacyRegion->UnLock (
208                           mLegacyRegion,
209                           Start,
210                           Length,
211                           Granularity
212                           );
213 }
214 
215 /**
216   Get region information for the attributes of the Legacy Region.
217 
218   This function is used to discover the granularity of the attributes for the memory in the legacy
219   region. Each attribute may have a different granularity and the granularity may not be the same
220   for all memory ranges in the legacy region.
221 
222   @param  This[in]              Indicates the EFI_LEGACY_REGION2_PROTOCOL instance.
223   @param  DescriptorCount[out]  The number of region descriptor entries returned in the Descriptor
224                                 buffer.
225   @param  Descriptor[out]       A pointer to a pointer used to return a buffer where the legacy
226                                 region information is deposited. This buffer will contain a list of
227                                 DescriptorCount number of region descriptors.  This function will
228                                 provide the memory for the buffer.
229 
230   @retval EFI_SUCCESS           The information structure was returned.
231   @retval EFI_UNSUPPORTED       This function is not supported.
232 
233 **/
234 EFI_STATUS
235 EFIAPI
LegacyRegionGetInfo(IN EFI_LEGACY_REGION2_PROTOCOL * This,OUT UINT32 * DescriptorCount,OUT EFI_LEGACY_REGION_DESCRIPTOR ** Descriptor)236 LegacyRegionGetInfo (
237   IN  EFI_LEGACY_REGION2_PROTOCOL   *This,
238   OUT UINT32                        *DescriptorCount,
239   OUT EFI_LEGACY_REGION_DESCRIPTOR  **Descriptor
240   )
241 {
242   return EFI_UNSUPPORTED;
243 }
244 
245 /**
246   The user Entry Point for module LegacyRegionDxe.  The user code starts with this function.
247 
248   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
249   @param[in] SystemTable    A pointer to the EFI System Table.
250 
251   @retval EFI_SUCCESS       The entry point is executed successfully.
252 
253 **/
254 EFI_STATUS
255 EFIAPI
LegacyRegion2OnLegacyRegionThunkInitialize(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)256 LegacyRegion2OnLegacyRegionThunkInitialize (
257   IN EFI_HANDLE        ImageHandle,
258   IN EFI_SYSTEM_TABLE  *SystemTable
259   )
260 {
261   EFI_STATUS  Status;
262 
263   //
264   // Make sure the Legacy Region 2 Protocol is not already installed in the system
265   //
266   ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiLegacyRegion2ProtocolGuid);
267 
268   //
269   // Locate and cache Framework Legacy Region Protocol.
270   //
271   Status = gBS->LocateProtocol (
272                   &gEfiLegacyRegionProtocolGuid,
273                   NULL,
274                   (VOID **) &mLegacyRegion
275                   );
276   ASSERT_EFI_ERROR (Status);
277 
278   //
279   // Install the protocol on a new handle.
280   //
281   Status = gBS->InstallMultipleProtocolInterfaces (
282                   &mLegacyRegion2Handle,
283                   &gEfiLegacyRegion2ProtocolGuid, &mLegacyRegion2,
284                   NULL
285                   );
286   ASSERT_EFI_ERROR (Status);
287 
288   return Status;
289 }
290