]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Csm/CsmSupportLib/LegacyRegion.c
OvmfPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / OvmfPkg / Csm / CsmSupportLib / LegacyRegion.c
CommitLineData
8016da21 1/** @file\r
2 Legacy Region Support\r
3\r
db27e9f3 4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
8016da21 5\r
b26f0cf9 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
8016da21 7\r
8**/\r
9\r
10#include "LegacyRegion.h"\r
11\r
12//\r
db27e9f3 13// 440/Q35 PAM map.\r
8016da21 14//\r
db27e9f3
RN
15// PAM Range Offset Bits Operation\r
16// 440 Q35\r
17// =============== ==== ==== ==== ===============================================================\r
18// 0xC0000-0xC3FFF 0x5a 0x91 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
19// 0xC4000-0xC7FFF 0x5a 0x91 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
20// 0xC8000-0xCBFFF 0x5b 0x92 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
21// 0xCC000-0xCFFFF 0x5b 0x92 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
22// 0xD0000-0xD3FFF 0x5c 0x93 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
23// 0xD4000-0xD7FFF 0x5c 0x93 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
24// 0xD8000-0xDBFFF 0x5d 0x94 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
25// 0xDC000-0xDFFFF 0x5d 0x94 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
26// 0xE0000-0xE3FFF 0x5e 0x95 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
27// 0xE4000-0xE7FFF 0x5e 0x95 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
28// 0xE8000-0xEBFFF 0x5f 0x96 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
29// 0xEC000-0xEFFFF 0x5f 0x96 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
30// 0xF0000-0xFFFFF 0x59 0x90 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
8016da21 31//\r
32STATIC LEGACY_MEMORY_SECTION_INFO mSectionArray[] = {\r
33 {0xC0000, SIZE_16KB, FALSE, FALSE},\r
34 {0xC4000, SIZE_16KB, FALSE, FALSE},\r
35 {0xC8000, SIZE_16KB, FALSE, FALSE},\r
36 {0xCC000, SIZE_16KB, FALSE, FALSE},\r
37 {0xD0000, SIZE_16KB, FALSE, FALSE},\r
38 {0xD4000, SIZE_16KB, FALSE, FALSE},\r
39 {0xD8000, SIZE_16KB, FALSE, FALSE},\r
40 {0xDC000, SIZE_16KB, FALSE, FALSE},\r
41 {0xE0000, SIZE_16KB, FALSE, FALSE},\r
42 {0xE4000, SIZE_16KB, FALSE, FALSE},\r
43 {0xE8000, SIZE_16KB, FALSE, FALSE},\r
44 {0xEC000, SIZE_16KB, FALSE, FALSE},\r
45 {0xF0000, SIZE_64KB, FALSE, FALSE}\r
46};\r
47\r
db27e9f3 48STATIC PAM_REGISTER_VALUE mRegisterValues440[] = {\r
ba1d245f
LE
49 {PMC_REGISTER_PIIX4 (PIIX4_PAM1), 0x01, 0x02},\r
50 {PMC_REGISTER_PIIX4 (PIIX4_PAM1), 0x10, 0x20},\r
51 {PMC_REGISTER_PIIX4 (PIIX4_PAM2), 0x01, 0x02},\r
52 {PMC_REGISTER_PIIX4 (PIIX4_PAM2), 0x10, 0x20},\r
53 {PMC_REGISTER_PIIX4 (PIIX4_PAM3), 0x01, 0x02},\r
54 {PMC_REGISTER_PIIX4 (PIIX4_PAM3), 0x10, 0x20},\r
55 {PMC_REGISTER_PIIX4 (PIIX4_PAM4), 0x01, 0x02},\r
56 {PMC_REGISTER_PIIX4 (PIIX4_PAM4), 0x10, 0x20},\r
57 {PMC_REGISTER_PIIX4 (PIIX4_PAM5), 0x01, 0x02},\r
58 {PMC_REGISTER_PIIX4 (PIIX4_PAM5), 0x10, 0x20},\r
59 {PMC_REGISTER_PIIX4 (PIIX4_PAM6), 0x01, 0x02},\r
60 {PMC_REGISTER_PIIX4 (PIIX4_PAM6), 0x10, 0x20},\r
61 {PMC_REGISTER_PIIX4 (PIIX4_PAM0), 0x10, 0x20}\r
8016da21 62};\r
63\r
db27e9f3 64STATIC PAM_REGISTER_VALUE mRegisterValuesQ35[] = {\r
ba1d245f
LE
65 {DRAMC_REGISTER_Q35 (MCH_PAM1), 0x01, 0x02},\r
66 {DRAMC_REGISTER_Q35 (MCH_PAM1), 0x10, 0x20},\r
67 {DRAMC_REGISTER_Q35 (MCH_PAM2), 0x01, 0x02},\r
68 {DRAMC_REGISTER_Q35 (MCH_PAM2), 0x10, 0x20},\r
69 {DRAMC_REGISTER_Q35 (MCH_PAM3), 0x01, 0x02},\r
70 {DRAMC_REGISTER_Q35 (MCH_PAM3), 0x10, 0x20},\r
71 {DRAMC_REGISTER_Q35 (MCH_PAM4), 0x01, 0x02},\r
72 {DRAMC_REGISTER_Q35 (MCH_PAM4), 0x10, 0x20},\r
73 {DRAMC_REGISTER_Q35 (MCH_PAM5), 0x01, 0x02},\r
74 {DRAMC_REGISTER_Q35 (MCH_PAM5), 0x10, 0x20},\r
75 {DRAMC_REGISTER_Q35 (MCH_PAM6), 0x01, 0x02},\r
76 {DRAMC_REGISTER_Q35 (MCH_PAM6), 0x10, 0x20},\r
77 {DRAMC_REGISTER_Q35 (MCH_PAM0), 0x10, 0x20}\r
db27e9f3
RN
78};\r
79\r
80STATIC PAM_REGISTER_VALUE *mRegisterValues;\r
81\r
8016da21 82//\r
83// Handle used to install the Legacy Region Protocol\r
84//\r
85STATIC EFI_HANDLE mHandle = NULL;\r
86\r
87//\r
88// Instance of the Legacy Region Protocol to install into the handle database\r
89//\r
90STATIC EFI_LEGACY_REGION2_PROTOCOL mLegacyRegion2 = {\r
91 LegacyRegion2Decode,\r
92 LegacyRegion2Lock,\r
93 LegacyRegion2BootLock,\r
94 LegacyRegion2Unlock,\r
95 LegacyRegionGetInfo\r
96};\r
97\r
98STATIC\r
99EFI_STATUS\r
100LegacyRegionManipulationInternal (\r
101 IN UINT32 Start,\r
102 IN UINT32 Length,\r
103 IN BOOLEAN *ReadEnable,\r
104 IN BOOLEAN *WriteEnable,\r
105 OUT UINT32 *Granularity\r
106 )\r
107{\r
108 UINT32 EndAddress;\r
109 UINTN Index;\r
110 UINTN StartIndex;\r
111\r
112 //\r
113 // Validate input parameters.\r
114 //\r
115 if (Length == 0 || Granularity == NULL) {\r
116 return EFI_INVALID_PARAMETER;\r
117 }\r
118 EndAddress = Start + Length - 1;\r
119 if ((Start < PAM_BASE_ADDRESS) || EndAddress > PAM_LIMIT_ADDRESS) {\r
120 return EFI_INVALID_PARAMETER;\r
121 }\r
122\r
123 //\r
124 // Loop to find the start PAM.\r
125 //\r
126 StartIndex = 0;\r
5a5025e4 127 for (Index = 0; Index < ARRAY_SIZE (mSectionArray); Index++) {\r
8016da21 128 if ((Start >= mSectionArray[Index].Start) && (Start < (mSectionArray[Index].Start + mSectionArray[Index].Length))) {\r
129 StartIndex = Index;\r
130 break;\r
131 }\r
132 }\r
5a5025e4 133 ASSERT (Index < ARRAY_SIZE (mSectionArray));\r
8016da21 134\r
135 //\r
136 // Program PAM until end PAM is encountered\r
137 //\r
5a5025e4 138 for (Index = StartIndex; Index < ARRAY_SIZE (mSectionArray); Index++) {\r
8016da21 139 if (ReadEnable != NULL) {\r
140 if (*ReadEnable) {\r
141 PciOr8 (\r
ba1d245f 142 mRegisterValues[Index].PAMRegPciLibAddress,\r
8016da21 143 mRegisterValues[Index].ReadEnableData\r
144 );\r
145 } else {\r
146 PciAnd8 (\r
ba1d245f 147 mRegisterValues[Index].PAMRegPciLibAddress,\r
8016da21 148 (UINT8) (~mRegisterValues[Index].ReadEnableData)\r
149 );\r
150 }\r
151 }\r
152 if (WriteEnable != NULL) {\r
153 if (*WriteEnable) {\r
154 PciOr8 (\r
ba1d245f 155 mRegisterValues[Index].PAMRegPciLibAddress,\r
8016da21 156 mRegisterValues[Index].WriteEnableData\r
157 );\r
158 } else {\r
159 PciAnd8 (\r
ba1d245f 160 mRegisterValues[Index].PAMRegPciLibAddress,\r
8016da21 161 (UINT8) (~mRegisterValues[Index].WriteEnableData)\r
162 );\r
163 }\r
164 }\r
165\r
166 //\r
167 // If the end PAM is encountered, record its length as granularity and jump out.\r
168 //\r
169 if ((EndAddress >= mSectionArray[Index].Start) && (EndAddress < (mSectionArray[Index].Start + mSectionArray[Index].Length))) {\r
170 *Granularity = mSectionArray[Index].Length;\r
171 break;\r
172 }\r
173 }\r
5a5025e4 174 ASSERT (Index < ARRAY_SIZE (mSectionArray));\r
8016da21 175\r
176 return EFI_SUCCESS;\r
177}\r
178\r
179STATIC\r
180EFI_STATUS\r
181LegacyRegionGetInfoInternal (\r
182 OUT UINT32 *DescriptorCount,\r
183 OUT LEGACY_MEMORY_SECTION_INFO **Descriptor\r
184 )\r
185{\r
186 UINTN Index;\r
187 UINT8 PamValue;\r
188\r
189 //\r
190 // Check input parameters\r
191 //\r
192 if (DescriptorCount == NULL || Descriptor == NULL) {\r
193 return EFI_INVALID_PARAMETER;\r
194 }\r
195\r
196 //\r
197 // Fill in current status of legacy region.\r
198 //\r
199 *DescriptorCount = sizeof(mSectionArray) / sizeof (mSectionArray[0]);\r
200 for (Index = 0; Index < *DescriptorCount; Index++) {\r
ba1d245f 201 PamValue = PciRead8 (mRegisterValues[Index].PAMRegPciLibAddress);\r
8016da21 202 mSectionArray[Index].ReadEnabled = FALSE;\r
203 if ((PamValue & mRegisterValues[Index].ReadEnableData) != 0) {\r
204 mSectionArray[Index].ReadEnabled = TRUE;\r
205 }\r
206 mSectionArray[Index].WriteEnabled = FALSE;\r
207 if ((PamValue & mRegisterValues[Index].WriteEnableData) != 0) {\r
208 mSectionArray[Index].WriteEnabled = TRUE;\r
209 }\r
210 }\r
211\r
212 *Descriptor = mSectionArray;\r
213 return EFI_SUCCESS;\r
214}\r
215\r
216/**\r
217 Modify the hardware to allow (decode) or disallow (not decode) memory reads in a region.\r
218\r
219 If the On parameter evaluates to TRUE, this function enables memory reads in the address range\r
220 Start to (Start + Length - 1).\r
221 If the On parameter evaluates to FALSE, this function disables memory reads in the address range\r
222 Start to (Start + Length - 1).\r
223\r
224 @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
225 @param Start[in] The beginning of the physical address of the region whose attributes\r
226 should be modified.\r
227 @param Length[in] The number of bytes of memory whose attributes should be modified.\r
228 The actual number of bytes modified may be greater than the number\r
229 specified.\r
230 @param Granularity[out] The number of bytes in the last region affected. This may be less\r
231 than the total number of bytes affected if the starting address\r
232 was not aligned to a region's starting address or if the length\r
233 was greater than the number of bytes in the first region.\r
234 @param On[in] Decode / Non-Decode flag.\r
235\r
236 @retval EFI_SUCCESS The region's attributes were successfully modified.\r
237 @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
238\r
239**/\r
240EFI_STATUS\r
241EFIAPI\r
242LegacyRegion2Decode (\r
243 IN EFI_LEGACY_REGION2_PROTOCOL *This,\r
244 IN UINT32 Start,\r
245 IN UINT32 Length,\r
246 OUT UINT32 *Granularity,\r
247 IN BOOLEAN *On\r
248 )\r
249{\r
250 return LegacyRegionManipulationInternal (Start, Length, On, NULL, Granularity);\r
251}\r
252\r
253\r
254/**\r
255 Modify the hardware to disallow memory attribute changes in a region.\r
256\r
257 This function makes the attributes of a region read only. Once a region is boot-locked with this\r
258 function, the read and write attributes of that region cannot be changed until a power cycle has\r
259 reset the boot-lock attribute. Calls to Decode(), Lock() and Unlock() will have no effect.\r
260\r
261 @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
262 @param Start[in] The beginning of the physical address of the region whose\r
263 attributes should be modified.\r
264 @param Length[in] The number of bytes of memory whose attributes should be modified.\r
265 The actual number of bytes modified may be greater than the number\r
266 specified.\r
267 @param Granularity[out] The number of bytes in the last region affected. This may be less\r
268 than the total number of bytes affected if the starting address was\r
269 not aligned to a region's starting address or if the length was\r
270 greater than the number of bytes in the first region.\r
271\r
272 @retval EFI_SUCCESS The region's attributes were successfully modified.\r
273 @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
274 @retval EFI_UNSUPPORTED The chipset does not support locking the configuration registers in\r
275 a way that will not affect memory regions outside the legacy memory\r
276 region.\r
277\r
278**/\r
279EFI_STATUS\r
280EFIAPI\r
281LegacyRegion2BootLock (\r
282 IN EFI_LEGACY_REGION2_PROTOCOL *This,\r
283 IN UINT32 Start,\r
284 IN UINT32 Length,\r
285 OUT UINT32 *Granularity\r
286 )\r
287{\r
288 if ((Start < 0xC0000) || ((Start + Length - 1) > 0xFFFFF)) {\r
289 return EFI_INVALID_PARAMETER;\r
290 }\r
291\r
292 return EFI_UNSUPPORTED;\r
293}\r
294\r
295\r
296/**\r
297 Modify the hardware to disallow memory writes in a region.\r
298\r
299 This function changes the attributes of a memory range to not allow writes.\r
300\r
301 @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
302 @param Start[in] The beginning of the physical address of the region whose\r
303 attributes should be modified.\r
304 @param Length[in] The number of bytes of memory whose attributes should be modified.\r
305 The actual number of bytes modified may be greater than the number\r
306 specified.\r
307 @param Granularity[out] The number of bytes in the last region affected. This may be less\r
308 than the total number of bytes affected if the starting address was\r
309 not aligned to a region's starting address or if the length was\r
310 greater than the number of bytes in the first region.\r
311\r
312 @retval EFI_SUCCESS The region's attributes were successfully modified.\r
313 @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
314\r
315**/\r
316EFI_STATUS\r
317EFIAPI\r
318LegacyRegion2Lock (\r
319 IN EFI_LEGACY_REGION2_PROTOCOL *This,\r
320 IN UINT32 Start,\r
321 IN UINT32 Length,\r
322 OUT UINT32 *Granularity\r
323 )\r
324{\r
325 BOOLEAN WriteEnable;\r
326\r
327 WriteEnable = FALSE;\r
328 return LegacyRegionManipulationInternal (Start, Length, NULL, &WriteEnable, Granularity);\r
329}\r
330\r
331\r
332/**\r
333 Modify the hardware to allow memory writes in a region.\r
334\r
335 This function changes the attributes of a memory range to allow writes.\r
336\r
337 @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
338 @param Start[in] The beginning of the physical address of the region whose\r
339 attributes should be modified.\r
340 @param Length[in] The number of bytes of memory whose attributes should be modified.\r
341 The actual number of bytes modified may be greater than the number\r
342 specified.\r
343 @param Granularity[out] The number of bytes in the last region affected. This may be less\r
344 than the total number of bytes affected if the starting address was\r
345 not aligned to a region's starting address or if the length was\r
346 greater than the number of bytes in the first region.\r
347\r
348 @retval EFI_SUCCESS The region's attributes were successfully modified.\r
349 @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
350\r
351**/\r
352EFI_STATUS\r
353EFIAPI\r
354LegacyRegion2Unlock (\r
355 IN EFI_LEGACY_REGION2_PROTOCOL *This,\r
356 IN UINT32 Start,\r
357 IN UINT32 Length,\r
358 OUT UINT32 *Granularity\r
359 )\r
360{\r
361 BOOLEAN WriteEnable;\r
362\r
363 WriteEnable = TRUE;\r
364 return LegacyRegionManipulationInternal (Start, Length, NULL, &WriteEnable, Granularity);\r
365}\r
366\r
367/**\r
368 Get region information for the attributes of the Legacy Region.\r
369\r
370 This function is used to discover the granularity of the attributes for the memory in the legacy\r
371 region. Each attribute may have a different granularity and the granularity may not be the same\r
372 for all memory ranges in the legacy region.\r
373\r
374 @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
375 @param DescriptorCount[out] The number of region descriptor entries returned in the Descriptor\r
376 buffer.\r
377 @param Descriptor[out] A pointer to a pointer used to return a buffer where the legacy\r
378 region information is deposited. This buffer will contain a list of\r
379 DescriptorCount number of region descriptors. This function will\r
380 provide the memory for the buffer.\r
381\r
382 @retval EFI_SUCCESS The region's attributes were successfully modified.\r
383 @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
384\r
385**/\r
386EFI_STATUS\r
387EFIAPI\r
388LegacyRegionGetInfo (\r
389 IN EFI_LEGACY_REGION2_PROTOCOL *This,\r
390 OUT UINT32 *DescriptorCount,\r
391 OUT EFI_LEGACY_REGION_DESCRIPTOR **Descriptor\r
392 )\r
393{\r
394 LEGACY_MEMORY_SECTION_INFO *SectionInfo;\r
395 UINT32 SectionCount;\r
396 EFI_LEGACY_REGION_DESCRIPTOR *DescriptorArray;\r
397 UINTN Index;\r
398 UINTN DescriptorIndex;\r
399\r
400 //\r
401 // Get section numbers and information\r
402 //\r
403 LegacyRegionGetInfoInternal (&SectionCount, &SectionInfo);\r
404\r
405 //\r
406 // Each section has 3 descriptors, corresponding to readability, writeability, and lock status.\r
407 //\r
408 DescriptorArray = AllocatePool (sizeof (EFI_LEGACY_REGION_DESCRIPTOR) * SectionCount * 3);\r
409 if (DescriptorArray == NULL) {\r
410 return EFI_OUT_OF_RESOURCES;\r
411 }\r
412\r
413 DescriptorIndex = 0;\r
414 for (Index = 0; Index < SectionCount; Index++) {\r
415 DescriptorArray[DescriptorIndex].Start = SectionInfo[Index].Start;\r
416 DescriptorArray[DescriptorIndex].Length = SectionInfo[Index].Length;\r
417 DescriptorArray[DescriptorIndex].Granularity = SectionInfo[Index].Length;\r
418 if (SectionInfo[Index].ReadEnabled) {\r
419 DescriptorArray[DescriptorIndex].Attribute = LegacyRegionDecoded;\r
420 } else {\r
421 DescriptorArray[DescriptorIndex].Attribute = LegacyRegionNotDecoded;\r
422 }\r
423 DescriptorIndex++;\r
424\r
425 //\r
426 // Create descriptor for writeability, according to lock status\r
427 //\r
428 DescriptorArray[DescriptorIndex].Start = SectionInfo[Index].Start;\r
429 DescriptorArray[DescriptorIndex].Length = SectionInfo[Index].Length;\r
430 DescriptorArray[DescriptorIndex].Granularity = SectionInfo[Index].Length;\r
431 if (SectionInfo[Index].WriteEnabled) {\r
432 DescriptorArray[DescriptorIndex].Attribute = LegacyRegionWriteEnabled;\r
433 } else {\r
434 DescriptorArray[DescriptorIndex].Attribute = LegacyRegionWriteDisabled;\r
435 }\r
436 DescriptorIndex++;\r
437\r
438 //\r
439 // Chipset does not support bootlock.\r
440 //\r
441 DescriptorArray[DescriptorIndex].Start = SectionInfo[Index].Start;\r
442 DescriptorArray[DescriptorIndex].Length = SectionInfo[Index].Length;\r
443 DescriptorArray[DescriptorIndex].Granularity = SectionInfo[Index].Length;\r
444 DescriptorArray[DescriptorIndex].Attribute = LegacyRegionNotLocked;\r
445 DescriptorIndex++;\r
446 }\r
447\r
448 *DescriptorCount = (UINT32) DescriptorIndex;\r
449 *Descriptor = DescriptorArray;\r
450\r
451 return EFI_SUCCESS;\r
452}\r
453\r
454/**\r
455 Initialize Legacy Region support\r
456\r
457 @retval EFI_SUCCESS Successfully initialized\r
458\r
459**/\r
460EFI_STATUS\r
461LegacyRegionInit (\r
462 VOID\r
463 )\r
464{\r
465 EFI_STATUS Status;\r
db27e9f3
RN
466 UINT16 HostBridgeDevId;\r
467\r
468 //\r
469 // Query Host Bridge DID to determine platform type\r
470 //\r
471 HostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);\r
472 switch (HostBridgeDevId) {\r
473 case INTEL_82441_DEVICE_ID:\r
474 mRegisterValues = mRegisterValues440;\r
475 break;\r
476 case INTEL_Q35_MCH_DEVICE_ID:\r
477 mRegisterValues = mRegisterValuesQ35;\r
478 break;\r
479 default:\r
480 DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",\r
481 __FUNCTION__, HostBridgeDevId));\r
482 ASSERT (FALSE);\r
483 return RETURN_UNSUPPORTED;\r
484 }\r
8016da21 485\r
486 //\r
487 // Install the Legacy Region Protocol on a new handle\r
488 //\r
489 Status = gBS->InstallMultipleProtocolInterfaces (\r
490 &mHandle,\r
491 &gEfiLegacyRegion2ProtocolGuid, &mLegacyRegion2,\r
492 NULL\r
493 );\r
494 ASSERT_EFI_ERROR (Status);\r
495\r
496 return Status;\r
497}\r
498\r