HighMemDxe.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /** @file
  2. * High memory node enumeration DXE driver for ARM Virtual Machines
  3. *
  4. * Copyright (c) 2015-2016, Linaro Ltd. All rights reserved.
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause-Patent
  7. *
  8. **/
  9. #include <Library/BaseLib.h>
  10. #include <Library/DebugLib.h>
  11. #include <Library/DxeServicesTableLib.h>
  12. #include <Library/PcdLib.h>
  13. #include <Library/UefiBootServicesTableLib.h>
  14. #include <Protocol/Cpu.h>
  15. #include <Protocol/FdtClient.h>
  16. EFI_STATUS
  17. EFIAPI
  18. InitializeHighMemDxe (
  19. IN EFI_HANDLE ImageHandle,
  20. IN EFI_SYSTEM_TABLE *SystemTable
  21. )
  22. {
  23. FDT_CLIENT_PROTOCOL *FdtClient;
  24. EFI_CPU_ARCH_PROTOCOL *Cpu;
  25. EFI_STATUS Status, FindNodeStatus;
  26. INT32 Node;
  27. CONST UINT32 *Reg;
  28. UINT32 RegSize;
  29. UINTN AddressCells, SizeCells;
  30. UINT64 CurBase;
  31. UINT64 CurSize;
  32. UINT64 Attributes;
  33. EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
  34. Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,
  35. (VOID **)&FdtClient);
  36. ASSERT_EFI_ERROR (Status);
  37. Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL,
  38. (VOID **)&Cpu);
  39. ASSERT_EFI_ERROR (Status);
  40. //
  41. // Check for memory node and add the memory spaces except the lowest one
  42. //
  43. for (FindNodeStatus = FdtClient->FindMemoryNodeReg (FdtClient, &Node,
  44. (CONST VOID **) &Reg, &AddressCells,
  45. &SizeCells, &RegSize);
  46. !EFI_ERROR (FindNodeStatus);
  47. FindNodeStatus = FdtClient->FindNextMemoryNodeReg (FdtClient, Node,
  48. &Node, (CONST VOID **) &Reg, &AddressCells,
  49. &SizeCells, &RegSize)) {
  50. ASSERT (AddressCells <= 2);
  51. ASSERT (SizeCells <= 2);
  52. while (RegSize > 0) {
  53. CurBase = SwapBytes32 (*Reg++);
  54. if (AddressCells > 1) {
  55. CurBase = (CurBase << 32) | SwapBytes32 (*Reg++);
  56. }
  57. CurSize = SwapBytes32 (*Reg++);
  58. if (SizeCells > 1) {
  59. CurSize = (CurSize << 32) | SwapBytes32 (*Reg++);
  60. }
  61. RegSize -= (AddressCells + SizeCells) * sizeof (UINT32);
  62. Status = gDS->GetMemorySpaceDescriptor (CurBase, &GcdDescriptor);
  63. if (EFI_ERROR (Status)) {
  64. DEBUG ((DEBUG_WARN,
  65. "%a: Region 0x%lx - 0x%lx not found in the GCD memory space map\n",
  66. __FUNCTION__, CurBase, CurBase + CurSize - 1));
  67. continue;
  68. }
  69. if (GcdDescriptor.GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
  70. Status = gDS->AddMemorySpace (EfiGcdMemoryTypeSystemMemory, CurBase,
  71. CurSize, EFI_MEMORY_WB);
  72. if (EFI_ERROR (Status)) {
  73. DEBUG ((EFI_D_ERROR,
  74. "%a: Failed to add System RAM @ 0x%lx - 0x%lx (%r)\n",
  75. __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));
  76. continue;
  77. }
  78. Status = gDS->SetMemorySpaceAttributes (CurBase, CurSize,
  79. EFI_MEMORY_WB);
  80. if (EFI_ERROR (Status)) {
  81. DEBUG ((DEBUG_WARN,
  82. "%a: gDS->SetMemorySpaceAttributes() failed on region 0x%lx - 0x%lx (%r)\n",
  83. __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));
  84. }
  85. //
  86. // Due to the ambiguous nature of the RO/XP GCD memory space attributes,
  87. // it is impossible to add a memory space with the XP attribute in a way
  88. // that does not result in the XP attribute being set on *all* UEFI
  89. // memory map entries that are carved from it, including code regions
  90. // that require executable permissions.
  91. //
  92. // So instead, we never set the RO/XP attributes in the GCD memory space
  93. // capabilities or attribute fields, and apply any protections directly
  94. // on the page table mappings by going through the cpu arch protocol.
  95. //
  96. Attributes = EFI_MEMORY_WB;
  97. if ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) &
  98. (1U << (UINT32)EfiConventionalMemory)) != 0) {
  99. Attributes |= EFI_MEMORY_XP;
  100. }
  101. Status = Cpu->SetMemoryAttributes (Cpu, CurBase, CurSize, Attributes);
  102. if (EFI_ERROR (Status)) {
  103. DEBUG ((EFI_D_ERROR,
  104. "%a: Failed to set System RAM @ 0x%lx - 0x%lx attribute (%r)\n",
  105. __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));
  106. } else {
  107. DEBUG ((EFI_D_INFO, "%a: Add System RAM @ 0x%lx - 0x%lx\n",
  108. __FUNCTION__, CurBase, CurBase + CurSize - 1));
  109. }
  110. }
  111. }
  112. }
  113. return EFI_SUCCESS;
  114. }