1a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel/** @file
2a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel*
3a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel*  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
4a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel*  Copyright (c) 2014, Linaro Limited. All rights reserved.
5a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel*
6a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel*  This program and the accompanying materials
7a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel*  are licensed and made available under the terms and conditions of the BSD License
8a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel*  which accompanies this distribution.  The full text of the license may be found at
9a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel*  http://opensource.org/licenses/bsd-license.php
10a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel*
11a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel*
14a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel**/
15a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel
16a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel#include <PiPei.h>
17a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel
18a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel#include <Library/ArmPlatformLib.h>
19a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel#include <Library/DebugLib.h>
20a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel#include <Library/HobLib.h>
21a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel#include <Library/MemoryAllocationLib.h>
22a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel#include <Library/PcdLib.h>
23e1d529909966027d2d6a2b0095dcb7a8b0886fa5Ard Biesheuvel#include <Library/CacheMaintenanceLib.h>
24a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel
25a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard BiesheuvelVOID
26a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard BiesheuvelBuildMemoryTypeInformationHob (
27a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  VOID
28a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  );
29a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel
30a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard BiesheuvelVOID
31a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard BiesheuvelInitMmu (
32a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  VOID
33a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  )
34a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel{
35a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  ARM_MEMORY_REGION_DESCRIPTOR  *MemoryTable;
36a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  VOID                          *TranslationTableBase;
37a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  UINTN                         TranslationTableSize;
38a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  RETURN_STATUS                 Status;
39a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel
40a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  // Get Virtual Memory Map from the Platform Library
41a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  ArmPlatformGetVirtualMemoryMap (&MemoryTable);
42a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel
43a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  //Note: Because we called PeiServicesInstallPeiMemory() before to call InitMmu() the MMU Page Table resides in
44a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  //      DRAM (even at the top of DRAM as it is the first permanent memory allocation)
45a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  Status = ArmConfigureMmu (MemoryTable, &TranslationTableBase, &TranslationTableSize);
46a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  if (EFI_ERROR (Status)) {
47a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel    DEBUG ((EFI_D_ERROR, "Error: Failed to enable MMU\n"));
48a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  }
49a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel}
50a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel
51a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard BiesheuvelEFI_STATUS
52a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard BiesheuvelEFIAPI
53a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard BiesheuvelMemoryPeim (
54a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  IN EFI_PHYSICAL_ADDRESS               UefiMemoryBase,
55a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  IN UINT64                             UefiMemorySize
56a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  )
57a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel{
58a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttributes;
5972daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel  UINT64                      SystemMemoryTop;
60a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel
61a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  // Ensure PcdSystemMemorySize has been set
62a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  ASSERT (PcdGet64 (PcdSystemMemorySize) != 0);
63a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel
64a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  //
65a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  // Now, the permanent memory has been installed, we can call AllocatePages()
66a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  //
67a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  ResourceAttributes = (
68a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel      EFI_RESOURCE_ATTRIBUTE_PRESENT |
69a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel      EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
70a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel      EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
71a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel      EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
72a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel      EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
73a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel      EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
74a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel      EFI_RESOURCE_ATTRIBUTE_TESTED
75a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  );
76a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel
7772daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel  SystemMemoryTop = PcdGet64 (PcdSystemMemoryBase) +
7872daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel                    PcdGet64 (PcdSystemMemorySize);
7972daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel
8072daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel  if (SystemMemoryTop - 1 > MAX_ADDRESS) {
8172daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel    BuildResourceDescriptorHob (
8272daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel        EFI_RESOURCE_SYSTEM_MEMORY,
8372daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel        ResourceAttributes,
8472daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel        PcdGet64 (PcdSystemMemoryBase),
8572daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel        (UINT64)MAX_ADDRESS - PcdGet64 (PcdSystemMemoryBase) + 1
8672daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel        );
8772daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel    BuildResourceDescriptorHob (
8872daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel        EFI_RESOURCE_SYSTEM_MEMORY,
8972daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel        ResourceAttributes,
9072daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel        (UINT64)MAX_ADDRESS + 1,
9172daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel        SystemMemoryTop - MAX_ADDRESS - 1
9272daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel        );
9372daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel  } else {
9472daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel    BuildResourceDescriptorHob (
9572daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel        EFI_RESOURCE_SYSTEM_MEMORY,
9672daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel        ResourceAttributes,
9772daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel        PcdGet64 (PcdSystemMemoryBase),
9872daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel        PcdGet64 (PcdSystemMemorySize)
9972daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel        );
10072daeed8cfbbbf801c88412cf31cfef61ef59b6cArd Biesheuvel  }
101a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel
102e1d529909966027d2d6a2b0095dcb7a8b0886fa5Ard Biesheuvel  //
103e1d529909966027d2d6a2b0095dcb7a8b0886fa5Ard Biesheuvel  // When running under virtualization, the PI/UEFI memory region may be
104e1d529909966027d2d6a2b0095dcb7a8b0886fa5Ard Biesheuvel  // clean but not invalidated in system caches or in lower level caches
105e1d529909966027d2d6a2b0095dcb7a8b0886fa5Ard Biesheuvel  // on other CPUs. So invalidate the region by virtual address, to ensure
106e1d529909966027d2d6a2b0095dcb7a8b0886fa5Ard Biesheuvel  // that the contents we put there with the caches and MMU off will still
107e1d529909966027d2d6a2b0095dcb7a8b0886fa5Ard Biesheuvel  // be visible after turning them on.
108e1d529909966027d2d6a2b0095dcb7a8b0886fa5Ard Biesheuvel  //
109e1d529909966027d2d6a2b0095dcb7a8b0886fa5Ard Biesheuvel  InvalidateDataCacheRange ((VOID*)(UINTN)UefiMemoryBase, UefiMemorySize);
110e1d529909966027d2d6a2b0095dcb7a8b0886fa5Ard Biesheuvel
111a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  // Build Memory Allocation Hob
112a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  InitMmu ();
113a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel
114a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  if (FeaturePcdGet (PcdPrePiProduceMemoryTypeInformationHob)) {
115a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel    // Optional feature that helps prevent EFI memory map fragmentation.
116a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel    BuildMemoryTypeInformationHob ();
117a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  }
118a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel
119a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel  return EFI_SUCCESS;
120a1bcf5c3d00474b8e3ed84c22624127ab548fd04Ard Biesheuvel}
121