QemuVirtMemInfoPeiLibConstructor.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /** @file
  2. Copyright (c) 2014-2017, Linaro Limited. All rights reserved.
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. **/
  5. #include <Base.h>
  6. #include <Library/DebugLib.h>
  7. #include <Library/PcdLib.h>
  8. #include <libfdt.h>
  9. RETURN_STATUS
  10. EFIAPI
  11. QemuVirtMemInfoPeiLibConstructor (
  12. VOID
  13. )
  14. {
  15. VOID *DeviceTreeBase;
  16. INT32 Node, Prev;
  17. UINT64 NewBase, CurBase;
  18. UINT64 NewSize, CurSize;
  19. CONST CHAR8 *Type;
  20. INT32 Len;
  21. CONST UINT64 *RegProp;
  22. RETURN_STATUS PcdStatus;
  23. NewBase = 0;
  24. NewSize = 0;
  25. DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
  26. ASSERT (DeviceTreeBase != NULL);
  27. //
  28. // Make sure we have a valid device tree blob
  29. //
  30. ASSERT (fdt_check_header (DeviceTreeBase) == 0);
  31. //
  32. // Look for the lowest memory node
  33. //
  34. for (Prev = 0; ; Prev = Node) {
  35. Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
  36. if (Node < 0) {
  37. break;
  38. }
  39. //
  40. // Check for memory node
  41. //
  42. Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len);
  43. if (Type && (AsciiStrnCmp (Type, "memory", Len) == 0)) {
  44. //
  45. // Get the 'reg' property of this node. For now, we will assume
  46. // two 8 byte quantities for base and size, respectively.
  47. //
  48. RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
  49. if ((RegProp != 0) && (Len == (2 * sizeof (UINT64)))) {
  50. CurBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
  51. CurSize = fdt64_to_cpu (ReadUnaligned64 (RegProp + 1));
  52. DEBUG ((
  53. DEBUG_INFO,
  54. "%a: System RAM @ 0x%lx - 0x%lx\n",
  55. __FUNCTION__,
  56. CurBase,
  57. CurBase + CurSize - 1
  58. ));
  59. if ((NewBase > CurBase) || (NewBase == 0)) {
  60. NewBase = CurBase;
  61. NewSize = CurSize;
  62. }
  63. } else {
  64. DEBUG ((
  65. DEBUG_ERROR,
  66. "%a: Failed to parse FDT memory node\n",
  67. __FUNCTION__
  68. ));
  69. }
  70. }
  71. }
  72. //
  73. // Make sure the start of DRAM matches our expectation
  74. //
  75. ASSERT (FixedPcdGet64 (PcdSystemMemoryBase) == NewBase);
  76. PcdStatus = PcdSet64S (PcdSystemMemorySize, NewSize);
  77. ASSERT_RETURN_ERROR (PcdStatus);
  78. //
  79. // We need to make sure that the machine we are running on has at least
  80. // 128 MB of memory configured, and is currently executing this binary from
  81. // NOR flash. This prevents a device tree image in DRAM from getting
  82. // clobbered when our caller installs permanent PEI RAM, before we have a
  83. // chance of marking its location as reserved or copy it to a freshly
  84. // allocated block in the permanent PEI RAM in the platform PEIM.
  85. //
  86. ASSERT (NewSize >= SIZE_128MB);
  87. ASSERT (
  88. (((UINT64)PcdGet64 (PcdFdBaseAddress) +
  89. (UINT64)PcdGet32 (PcdFdSize)) <= NewBase) ||
  90. ((UINT64)PcdGet64 (PcdFdBaseAddress) >= (NewBase + NewSize))
  91. );
  92. return RETURN_SUCCESS;
  93. }