Exemple #1
0
/**
  Sort memory map entries based upon PhysicalStart, from low to high.

  @param  MemoryMap              A pointer to the buffer in which firmware places
                                 the current memory map.
  @param  MemoryMapSize          Size, in bytes, of the MemoryMap buffer.
  @param  DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
**/
STATIC
VOID
SortMemoryMap (
  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
  IN UINTN                      MemoryMapSize,
  IN UINTN                      DescriptorSize
  )
{
  EFI_MEMORY_DESCRIPTOR       *MemoryMapEntry;
  EFI_MEMORY_DESCRIPTOR       *NextMemoryMapEntry;
  EFI_MEMORY_DESCRIPTOR       *MemoryMapEnd;
  EFI_MEMORY_DESCRIPTOR       TempMemoryMap;

  MemoryMapEntry = MemoryMap;
  NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
  MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize);
  while (MemoryMapEntry < MemoryMapEnd) {
    while (NextMemoryMapEntry < MemoryMapEnd) {
      if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart) {
        CopyMem (&TempMemoryMap, MemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));
        CopyMem (MemoryMapEntry, NextMemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));
        CopyMem (NextMemoryMapEntry, &TempMemoryMap, sizeof(EFI_MEMORY_DESCRIPTOR));
      }

      NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
    }

    MemoryMapEntry      = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
    NextMemoryMapEntry  = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
  }
}
Exemple #2
0
/**
  Merge adjacent memory map entries if they use the same memory protection policy

  @param[in, out]  MemoryMap              A pointer to the buffer in which firmware places
                                          the current memory map.
  @param[in, out]  MemoryMapSize          A pointer to the size, in bytes, of the
                                          MemoryMap buffer. On input, this is the size of
                                          the current memory map.  On output,
                                          it is the size of new memory map after merge.
  @param[in]       DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
**/
STATIC
VOID
MergeMemoryMapForProtectionPolicy (
  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
  IN OUT UINTN                  *MemoryMapSize,
  IN UINTN                      DescriptorSize
  )
{
  EFI_MEMORY_DESCRIPTOR       *MemoryMapEntry;
  EFI_MEMORY_DESCRIPTOR       *MemoryMapEnd;
  UINT64                      MemoryBlockLength;
  EFI_MEMORY_DESCRIPTOR       *NewMemoryMapEntry;
  EFI_MEMORY_DESCRIPTOR       *NextMemoryMapEntry;
  UINT64                      Attributes;

  SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize);

  MemoryMapEntry = MemoryMap;
  NewMemoryMapEntry = MemoryMap;
  MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + *MemoryMapSize);
  while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
    CopyMem (NewMemoryMapEntry, MemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));
    NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);

    do {
      MemoryBlockLength = (UINT64) (EFI_PAGES_TO_SIZE((UINTN)MemoryMapEntry->NumberOfPages));
      Attributes = GetPermissionAttributeForMemoryType (MemoryMapEntry->Type);

      if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&
          Attributes == GetPermissionAttributeForMemoryType (NextMemoryMapEntry->Type) &&
          ((MemoryMapEntry->PhysicalStart + MemoryBlockLength) == NextMemoryMapEntry->PhysicalStart)) {
        MemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;
        if (NewMemoryMapEntry != MemoryMapEntry) {
          NewMemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;
        }

        NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
        continue;
      } else {
        MemoryMapEntry = PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
        break;
      }
    } while (TRUE);

    MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
    NewMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry, DescriptorSize);
  }

  *MemoryMapSize = (UINTN)NewMemoryMapEntry - (UINTN)MemoryMap;

  return ;
}
Exemple #3
0
/**
  Merge continous memory map entries whose have same attributes.

  @param  MemoryMap              A pointer to the buffer in which firmware places
                                 the current memory map.
  @param  MemoryMapSize          A pointer to the size, in bytes, of the
                                 MemoryMap buffer. On input, this is the size of
                                 the current memory map.  On output,
                                 it is the size of new memory map after merge.
  @param  DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
**/
STATIC
VOID
MergeMemoryMap (
  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
  IN OUT UINTN                  *MemoryMapSize,
  IN UINTN                      DescriptorSize
  )
{
  EFI_MEMORY_DESCRIPTOR       *MemoryMapEntry;
  EFI_MEMORY_DESCRIPTOR       *MemoryMapEnd;
  UINT64                      MemoryBlockLength;
  EFI_MEMORY_DESCRIPTOR       *NewMemoryMapEntry;
  EFI_MEMORY_DESCRIPTOR       *NextMemoryMapEntry;

  MemoryMapEntry = MemoryMap;
  NewMemoryMapEntry = MemoryMap;
  MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + *MemoryMapSize);
  while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
    CopyMem (NewMemoryMapEntry, MemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));
    NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);

    do {
      MemoryBlockLength = (UINT64) (EfiPagesToSize (MemoryMapEntry->NumberOfPages));
      if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&
          (MemoryMapEntry->Type == NextMemoryMapEntry->Type) &&
          (MemoryMapEntry->Attribute == NextMemoryMapEntry->Attribute) &&
          ((MemoryMapEntry->PhysicalStart + MemoryBlockLength) == NextMemoryMapEntry->PhysicalStart)) {
        MemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;
        if (NewMemoryMapEntry != MemoryMapEntry) {
          NewMemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;
        }

        NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
        continue;
      } else {
        MemoryMapEntry = PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
        break;
      }
    } while (TRUE);

    MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
    NewMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry, DescriptorSize);
  }

  *MemoryMapSize = (UINTN)NewMemoryMapEntry - (UINTN)MemoryMap;

  return ;
}
Exemple #4
0
/**
  Enforce memory map attributes.
  This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.

  @param  MemoryMap              A pointer to the buffer in which firmware places
                                 the current memory map.
  @param  MemoryMapSize          Size, in bytes, of the MemoryMap buffer.
  @param  DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
**/
STATIC
VOID
EnforceMemoryMapAttribute (
  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
  IN UINTN                      MemoryMapSize,
  IN UINTN                      DescriptorSize
  )
{
  EFI_MEMORY_DESCRIPTOR       *MemoryMapEntry;
  EFI_MEMORY_DESCRIPTOR       *MemoryMapEnd;

  MemoryMapEntry = MemoryMap;
  MemoryMapEnd   = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize);
  while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
    switch (MemoryMapEntry->Type) {
    case EfiRuntimeServicesCode:
      // do nothing
      break;
    case EfiRuntimeServicesData:
    case EfiMemoryMappedIO:
    case EfiMemoryMappedIOPortSpace:
      MemoryMapEntry->Attribute |= EFI_MEMORY_XP;
      break;
    case EfiReservedMemoryType:
    case EfiACPIMemoryNVS:
      break;
    }

    MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
  }

  return ;
}
Exemple #5
0
VOID EFIAPI
PrintMemMap(
	IN UINTN			MemoryMapSize,
	IN EFI_MEMORY_DESCRIPTOR	*MemoryMap,
	IN UINTN			DescriptorSize,
	IN UINT32			DescriptorVersion
)
{
	UINTN				NumEntries;
	UINTN				Index;
	UINT64				Bytes;
	EFI_MEMORY_DESCRIPTOR		*Desc;
	
	Desc = MemoryMap;
	NumEntries = MemoryMapSize / DescriptorSize;
	PRINT("MEMMAP: Size=%d, Addr=%p, DescSize=%d, DescVersion: 0x%x\n", MemoryMapSize, MemoryMap, DescriptorSize, DescriptorVersion);
	PRINT("Type       Start            End       VStart               # Pages          Attributes\n");
	for (Index = 0; Index < NumEntries; Index++) {
		Bytes = (((UINTN) Desc->NumberOfPages) * EFI_PAGE_SIZE);
		PRINT("%-12s %lX-%lX %lX  %lX %lX\n",
			EfiMemoryTypeDesc[Desc->Type],
			Desc->PhysicalStart,
			Desc->PhysicalStart + Bytes - 1,
			Desc->VirtualStart,
			Desc->NumberOfPages,
			Desc->Attribute
		);
		Desc = NEXT_MEMORY_DESCRIPTOR(Desc, DescriptorSize);
		//if ((Index + 1) % 16 == 0) {
		//	WaitForKeyPress(L"press a key to continue\n");
		//}
	}
	//WaitForKeyPress(L"End: press a key to continue\n");
}
Exemple #6
0
/**
  Remove exec permissions from all regions whose type is identified by
  PcdDxeNxMemoryProtectionPolicy.
**/
STATIC
VOID
InitializeDxeNxMemoryProtectionPolicy (
  VOID
  )
{
  UINTN                             MemoryMapSize;
  UINTN                             MapKey;
  UINTN                             DescriptorSize;
  UINT32                            DescriptorVersion;
  EFI_MEMORY_DESCRIPTOR             *MemoryMap;
  EFI_MEMORY_DESCRIPTOR             *MemoryMapEntry;
  EFI_MEMORY_DESCRIPTOR             *MemoryMapEnd;
  EFI_STATUS                        Status;
  UINT64                            Attributes;
  LIST_ENTRY                        *Link;
  EFI_GCD_MAP_ENTRY                 *Entry;
  EFI_PEI_HOB_POINTERS              Hob;
  EFI_HOB_MEMORY_ALLOCATION         *MemoryHob;
  EFI_PHYSICAL_ADDRESS              StackBase;

  //
  // Get the EFI memory map.
  //
  MemoryMapSize = 0;
  MemoryMap     = NULL;

  Status = gBS->GetMemoryMap (
                  &MemoryMapSize,
                  MemoryMap,
                  &MapKey,
                  &DescriptorSize,
                  &DescriptorVersion
                  );
  ASSERT (Status == EFI_BUFFER_TOO_SMALL);
  do {
    MemoryMap = (EFI_MEMORY_DESCRIPTOR *) AllocatePool (MemoryMapSize);
    ASSERT (MemoryMap != NULL);
    Status = gBS->GetMemoryMap (
                    &MemoryMapSize,
                    MemoryMap,
                    &MapKey,
                    &DescriptorSize,
                    &DescriptorVersion
                    );
    if (EFI_ERROR (Status)) {
      FreePool (MemoryMap);
    }
  } while (Status == EFI_BUFFER_TOO_SMALL);
  ASSERT_EFI_ERROR (Status);

  StackBase = 0;
  if (PcdGetBool (PcdCpuStackGuard)) {
    //
    // Get the base of stack from Hob.
    //
    Hob.Raw = GetHobList ();
    while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {
      MemoryHob = Hob.MemoryAllocation;
      if (CompareGuid(&gEfiHobMemoryAllocStackGuid, &MemoryHob->AllocDescriptor.Name)) {
        DEBUG ((
          DEBUG_INFO,
          "%a: StackBase = 0x%016lx  StackSize = 0x%016lx\n",
          __FUNCTION__,
          MemoryHob->AllocDescriptor.MemoryBaseAddress,
          MemoryHob->AllocDescriptor.MemoryLength
          ));

        StackBase = MemoryHob->AllocDescriptor.MemoryBaseAddress;
        //
        // Ensure the base of the stack is page-size aligned.
        //
        ASSERT ((StackBase & EFI_PAGE_MASK) == 0);
        break;
      }
      Hob.Raw = GET_NEXT_HOB (Hob);
    }

    //
    // Ensure the base of stack can be found from Hob when stack guard is
    // enabled.
    //
    ASSERT (StackBase != 0);
  }

  DEBUG ((
    DEBUG_INFO,
    "%a: applying strict permissions to active memory regions\n",
    __FUNCTION__
    ));

  MergeMemoryMapForProtectionPolicy (MemoryMap, &MemoryMapSize, DescriptorSize);

  MemoryMapEntry = MemoryMap;
  MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize);
  while ((UINTN) MemoryMapEntry < (UINTN) MemoryMapEnd) {

    Attributes = GetPermissionAttributeForMemoryType (MemoryMapEntry->Type);
    if (Attributes != 0) {
      SetUefiImageMemoryAttributes (
        MemoryMapEntry->PhysicalStart,
        LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT),
        Attributes);

      //
      // Add EFI_MEMORY_RP attribute for page 0 if NULL pointer detection is
      // enabled.
      //
      if (MemoryMapEntry->PhysicalStart == 0 &&
          PcdGet8 (PcdNullPointerDetectionPropertyMask) != 0) {

        ASSERT (MemoryMapEntry->NumberOfPages > 0);
        SetUefiImageMemoryAttributes (
          0,
          EFI_PAGES_TO_SIZE (1),
          EFI_MEMORY_RP | Attributes);
      }

      //
      // Add EFI_MEMORY_RP attribute for the first page of the stack if stack
      // guard is enabled.
      //
      if (StackBase != 0 &&
          (StackBase >= MemoryMapEntry->PhysicalStart &&
           StackBase <  MemoryMapEntry->PhysicalStart +
                        LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT)) &&
          PcdGetBool (PcdCpuStackGuard)) {

        SetUefiImageMemoryAttributes (
          StackBase,
          EFI_PAGES_TO_SIZE (1),
          EFI_MEMORY_RP | Attributes);
      }

    }
    MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
  }
  FreePool (MemoryMap);

  //
  // Apply the policy for RAM regions that we know are present and
  // accessible, but have not been added to the UEFI memory map (yet).
  //
  if (GetPermissionAttributeForMemoryType (EfiConventionalMemory) != 0) {
    DEBUG ((
      DEBUG_INFO,
      "%a: applying strict permissions to inactive memory regions\n",
      __FUNCTION__
      ));

    CoreAcquireGcdMemoryLock ();

    Link = mGcdMemorySpaceMap.ForwardLink;
    while (Link != &mGcdMemorySpaceMap) {

      Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);

      if (Entry->GcdMemoryType == EfiGcdMemoryTypeReserved &&
          Entry->EndAddress < MAX_ADDRESS &&
          (Entry->Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==
            (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)) {

        Attributes = GetPermissionAttributeForMemoryType (EfiConventionalMemory) |
                     (Entry->Attributes & CACHE_ATTRIBUTE_MASK);

        DEBUG ((DEBUG_INFO,
          "Untested GCD memory space region: - 0x%016lx - 0x%016lx (0x%016lx)\n",
          Entry->BaseAddress, Entry->EndAddress - Entry->BaseAddress + 1,
          Attributes));

        ASSERT(gCpu != NULL);
        gCpu->SetMemoryAttributes (gCpu, Entry->BaseAddress,
          Entry->EndAddress - Entry->BaseAddress + 1, Attributes);
      }

      Link = Link->ForwardLink;
    }
    CoreReleaseGcdMemoryLock ();
  }
}
Exemple #7
0
/**
  This function returns a copy of the current memory map. The map is an array of
  memory descriptors, each of which describes a contiguous block of memory.

  @param  MemoryMapSize          A pointer to the size, in bytes, of the
                                 MemoryMap buffer. On input, this is the size of
                                 the buffer allocated by the caller.  On output,
                                 it is the size of the buffer returned by the
                                 firmware  if the buffer was large enough, or the
                                 size of the buffer needed  to contain the map if
                                 the buffer was too small.
  @param  MemoryMap              A pointer to the buffer in which firmware places
                                 the current memory map.
  @param  MapKey                 A pointer to the location in which firmware
                                 returns the key for the current memory map.
  @param  DescriptorSize         A pointer to the location in which firmware
                                 returns the size, in bytes, of an individual
                                 EFI_MEMORY_DESCRIPTOR.
  @param  DescriptorVersion      A pointer to the location in which firmware
                                 returns the version number associated with the
                                 EFI_MEMORY_DESCRIPTOR.

  @retval EFI_SUCCESS            The memory map was returned in the MemoryMap
                                 buffer.
  @retval EFI_BUFFER_TOO_SMALL   The MemoryMap buffer was too small. The current
                                 buffer size needed to hold the memory map is
                                 returned in MemoryMapSize.
  @retval EFI_INVALID_PARAMETER  One of the parameters has an invalid value.

**/
EFI_STATUS
EFIAPI
CoreGetMemoryMap (
  IN OUT UINTN                  *MemoryMapSize,
  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
  OUT UINTN                     *MapKey,
  OUT UINTN                     *DescriptorSize,
  OUT UINT32                    *DescriptorVersion
  )
{
  EFI_STATUS                        Status;
  UINTN                             Size;
  UINTN                             BufferSize;
  UINTN                             NumberOfRuntimeEntries;
  LIST_ENTRY                        *Link;
  MEMORY_MAP                        *Entry;
  EFI_GCD_MAP_ENTRY                 *GcdMapEntry;
  EFI_MEMORY_TYPE                   Type;

  //
  // Make sure the parameters are valid
  //
  if (MemoryMapSize == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  CoreAcquireGcdMemoryLock ();

  //
  // Count the number of Reserved and MMIO entries that are marked for runtime use
  //
  NumberOfRuntimeEntries = 0;
  for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) {
    GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
    if ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) ||
        (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo)) {
      if ((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) {
        NumberOfRuntimeEntries++;
      }
    }
  }

  Size = sizeof (EFI_MEMORY_DESCRIPTOR);

  //
  // Make sure Size != sizeof(EFI_MEMORY_DESCRIPTOR). This will
  // prevent people from having pointer math bugs in their code.
  // now you have to use *DescriptorSize to make things work.
  //
  Size += sizeof(UINT64) - (Size % sizeof (UINT64));

  if (DescriptorSize != NULL) {
    *DescriptorSize = Size;
  }

  if (DescriptorVersion != NULL) {
    *DescriptorVersion = EFI_MEMORY_DESCRIPTOR_VERSION;
  }

  CoreAcquireMemoryLock ();

  //
  // Compute the buffer size needed to fit the entire map
  //
  BufferSize = Size * NumberOfRuntimeEntries;
  for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
    BufferSize += Size;
  }

  if (*MemoryMapSize < BufferSize) {
    Status = EFI_BUFFER_TOO_SMALL;
    goto Done;
  }

  if (MemoryMap == NULL) {
    Status = EFI_INVALID_PARAMETER;
    goto Done;
  }

  //
  // Build the map
  //
  ZeroMem (MemoryMap, BufferSize);
  for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
    Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
    ASSERT (Entry->VirtualStart == 0);

    //
    // Convert internal map into an EFI_MEMORY_DESCRIPTOR
    //
    MemoryMap->Type           = Entry->Type;
    MemoryMap->PhysicalStart  = Entry->Start;
    MemoryMap->VirtualStart   = Entry->VirtualStart;
    MemoryMap->NumberOfPages  = RShiftU64 (Entry->End - Entry->Start + 1, EFI_PAGE_SHIFT);
    //
    // If the memory type is EfiConventionalMemory, then determine if the range is part of a
    // memory type bin and needs to be converted to the same memory type as the rest of the
    // memory type bin in order to minimize EFI Memory Map changes across reboots.  This
    // improves the chances for a successful S4 resume in the presence of minor page allocation
    // differences across reboots.
    //
    if (MemoryMap->Type == EfiConventionalMemory) {
      for (Type = (EFI_MEMORY_TYPE) 0; Type < EfiMaxMemoryType; Type++) {
        if (mMemoryTypeStatistics[Type].Special                        &&
            mMemoryTypeStatistics[Type].NumberOfPages > 0              &&
            Entry->Start >= mMemoryTypeStatistics[Type].BaseAddress    &&
            Entry->End   <= mMemoryTypeStatistics[Type].MaximumAddress) {
          MemoryMap->Type = Type;
        }
      }
    }
    MemoryMap->Attribute = Entry->Attribute;
    if (mMemoryTypeStatistics[MemoryMap->Type].Runtime) {
      MemoryMap->Attribute |= EFI_MEMORY_RUNTIME;
    }

    MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, Size);
  }

  for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) {
    GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
    if ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) ||
        (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo)) {
      if ((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) {
        // 
        // Create EFI_MEMORY_DESCRIPTOR for every Reserved and MMIO GCD entries
        // that are marked for runtime use
        //
        MemoryMap->PhysicalStart = GcdMapEntry->BaseAddress;
        MemoryMap->VirtualStart  = 0;
        MemoryMap->NumberOfPages = RShiftU64 ((GcdMapEntry->EndAddress - GcdMapEntry->BaseAddress + 1), EFI_PAGE_SHIFT);
        MemoryMap->Attribute     = GcdMapEntry->Attributes & ~EFI_MEMORY_PORT_IO;

        if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) {
          MemoryMap->Type = EfiReservedMemoryType;
        } else if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {
          if ((GcdMapEntry->Attributes & EFI_MEMORY_PORT_IO) == EFI_MEMORY_PORT_IO) {
            MemoryMap->Type = EfiMemoryMappedIOPortSpace;
          } else {
            MemoryMap->Type = EfiMemoryMappedIO;
          }
        }

        MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, Size);
      }
    }
  }

  Status = EFI_SUCCESS;

Done:

  CoreReleaseMemoryLock ();

  CoreReleaseGcdMemoryLock ();

  //
  // Update the map key finally
  //
  if (MapKey != NULL) {
    *MapKey = mMemoryMapKey;
  }

  *MemoryMapSize = BufferSize;

  return Status;
}
Exemple #8
0
VOID EFIAPI
FixMemMap(
	IN UINTN					MemoryMapSize,
	IN EFI_MEMORY_DESCRIPTOR	*MemoryMap,
	IN UINTN					DescriptorSize,
	IN UINT32					DescriptorVersion
)
{
	UINTN					NumEntries;
	UINTN					Index;
	EFI_MEMORY_DESCRIPTOR	*Desc;
	UINTN					BlockSize;
	UINTN					PhysicalEnd;

	DBG("FixMemMap: Size=%d, Addr=%p, DescSize=%d\n", MemoryMapSize, MemoryMap, DescriptorSize);
	DBGnvr("FixMemMap ...\n");
	
	Desc = MemoryMap;
	NumEntries = MemoryMapSize / DescriptorSize;
	
	for (Index = 0; Index < NumEntries; Index++) {
		BlockSize = EFI_PAGES_TO_SIZE((UINTN)Desc->NumberOfPages);
		PhysicalEnd = Desc->PhysicalStart + BlockSize;
		
		//
		// Some UEFIs end up with "reserved" area with EFI_MEMORY_RUNTIME flag set
		// when Intel HD3000 or HD4000 is used. We will remove that flag here.
		//
		if ((Desc->Attribute & EFI_MEMORY_RUNTIME) != 0 && Desc->Type == EfiReservedMemoryType) {
			DBGnvr(" %s as RT: %lx (0x%x) - Att: %lx",
				   EfiMemoryTypeDesc[Desc->Type], Desc->PhysicalStart, Desc->NumberOfPages, Desc->Attribute);
			Desc->Attribute = Desc->Attribute & (~EFI_MEMORY_RUNTIME);
			DBGnvr(" -> %lx\n", Desc->Attribute);
			
			/* This one is not working - blocks during DefragmentRuntimeServices()
			DBGnvr(" %s as RT: %lx (0x%x) - %s",
				EfiMemoryTypeDesc[Desc->Type], Desc->PhysicalStart, Desc->NumberOfPages, EfiMemoryTypeDesc[Desc->Type]);
			Desc->Type = EfiMemoryMappedIO;
			DBGnvr(" -> %s\n", EfiMemoryTypeDesc[Desc->Type]);
			*/
			
			/* Another possible solution - mark the range as MMIO.
			DBGnvr(" %s as RT: %lx (0x%x) - %s",
				EfiMemoryTypeDesc[Desc->Type], Desc->PhysicalStart, Desc->NumberOfPages, EfiMemoryTypeDesc[Desc->Type]);
			Desc->Type = EfiRuntimeServicesData;
			DBGnvr(" -> %s\n", EfiMemoryTypeDesc[Desc->Type]);
			*/
		}
        
		//
        // Fix by Slice - fixes sleep/wake on GB boards.
        //
		//    if ((Desc->PhysicalStart >= 0x9e000) && (Desc->PhysicalStart < 0xa0000)) {
		if ((Desc->PhysicalStart < 0xa0000) && (PhysicalEnd >= 0x9e000)) {
			Desc->Type = EfiACPIMemoryNVS;
			Desc->Attribute = 0;
		}
        
        
		//
		// Also do some checking
		//
		if ((Desc->Attribute & EFI_MEMORY_RUNTIME) != 0) {
			//
			// block with RT flag.
			// if it is not RT or MMIO, then report to log
			//
			if (Desc->Type != EfiRuntimeServicesCode
				&& Desc->Type != EfiRuntimeServicesData
				&& Desc->Type != EfiMemoryMappedIO
				&& Desc->Type != EfiMemoryMappedIOPortSpace
				)
			{
				DBGnvr(" %s with RT flag: %lx (0x%x) - ???\n", EfiMemoryTypeDesc[Desc->Type], Desc->PhysicalStart, Desc->NumberOfPages);
			}
		} else {
			//
			// block without RT flag.
			// if it is RT or MMIO, then report to log
			//
			if (Desc->Type == EfiRuntimeServicesCode
				|| Desc->Type == EfiRuntimeServicesData
				|| Desc->Type == EfiMemoryMappedIO
				|| Desc->Type == EfiMemoryMappedIOPortSpace
				)
			{
				DBGnvr(" %s without RT flag: %lx (0x%x) - ???\n", EfiMemoryTypeDesc[Desc->Type], Desc->PhysicalStart, Desc->NumberOfPages);
			}
		}
		
		Desc = NEXT_MEMORY_DESCRIPTOR(Desc, DescriptorSize);
	}
}
/*prints the memory status*/
void st_memmgr_print_stat(){
	uint16_t i;
	MEMORY_DESCRIPTOR *mem_desc;
	uint16_t free_space=0;
	uint16_t allocated_space=0;
	uint8_t allocation_overhead=0;
	uint16_t largest_free_block=0;
	uint16_t cont_free_space=0;
	/*BANK_0*/
	i=0;
	mem_desc=(MEMORY_DESCRIPTOR*)st_memory.BANK_0;
	printf("\n\n======================BANK 0==========================\n");
	while(i<BANK_0_SIZE){
		i+=(GET_BLOCK_OFFSET((*mem_desc))*BLOCK_SIZE);
		printMemoryDescriptorInfo((*mem_desc));
		if(IS_ALLOCATED((*mem_desc))){
			allocated_space+=(GET_BLOCK_OFFSET((*mem_desc))*BLOCK_SIZE);
			allocation_overhead+=sizeof(MEMORY_DESCRIPTOR);
			cont_free_space=0;
		}
		else{	
			free_space+=(GET_BLOCK_OFFSET((*mem_desc))*BLOCK_SIZE);
			cont_free_space+=(GET_BLOCK_OFFSET((*mem_desc))*BLOCK_SIZE);
			if(largest_free_block < cont_free_space)
				largest_free_block=cont_free_space;
		}
		mem_desc=NEXT_MEMORY_DESCRIPTOR(mem_desc);
	}



	/*BANK_1*/
	i=0;
	mem_desc=(MEMORY_DESCRIPTOR*)st_memory.BANK_1;
	printf("\n\n======================BANK 1==========================\n");
	while(i<BANK_1_SIZE){
		i+=(GET_BLOCK_OFFSET((*mem_desc))*BLOCK_SIZE);
		printMemoryDescriptorInfo((*mem_desc));
		if(IS_ALLOCATED((*mem_desc))){
			allocated_space+=(GET_BLOCK_OFFSET((*mem_desc))*BLOCK_SIZE);
			allocation_overhead+=sizeof(MEMORY_DESCRIPTOR);
			cont_free_space=0;
		}
		else{	
			free_space+=(GET_BLOCK_OFFSET((*mem_desc))*BLOCK_SIZE);
			cont_free_space+=(GET_BLOCK_OFFSET((*mem_desc))*BLOCK_SIZE);
			if(largest_free_block < cont_free_space)
				largest_free_block=cont_free_space;

		}

		mem_desc=NEXT_MEMORY_DESCRIPTOR(mem_desc);
	}

	printf("\n=================================================================================================");
	printf("\nTotal Allocated Space : %d bytes",allocated_space);
	printf("\nTotal Free Space : %d bytes",free_space);
	printf("\nCurrent Allocation Overhead : %d bytes",allocation_overhead);
	printf("\nActual Allocation : %d bytes approx. (Internal Fragmentation taken into account)",allocated_space-allocation_overhead);
	printf("\nPeak Memory Utilization : %d bytes",peak_memory_utilization);
	printf("\nLargest Serviceable memory : %d bytes",largest_free_block);
	printf("\nlast requested size : %d bytes",lastRequestSize);
	printf("\nlast request status : %s\n",lastRequestStatus?"SUCCESS":"FAILED");
	printf("=================================================================================================\n");

}
Exemple #10
0
/*
 * Make a e820 memory map
 */
void
e820_map_from_efi_map (struct e820_entry *e820_map,
		       int *e820_nr_map,
		       grub_efi_memory_descriptor_t *memory_map,
		       grub_efi_uintn_t desc_size,
		       grub_efi_uintn_t memory_map_size)
{
  grub_efi_memory_descriptor_t *desc;
  unsigned long long start = 0;
  unsigned long long end = 0;
  unsigned long long size = 0;
  grub_efi_memory_descriptor_t *memory_map_end;

  memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, memory_map_size);
  *e820_nr_map = 0;
  for (desc = memory_map;
       desc < memory_map_end;
       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
    {
      switch (desc->type)
	{
	case GRUB_EFI_ACPI_RECLAIM_MEMORY:
	  add_memory_region (e820_map, e820_nr_map,
			     desc->physical_start, desc->num_pages << 12,
			     E820_ACPI);
	  break;
	case GRUB_EFI_RUNTIME_SERVICES_CODE:
	case GRUB_EFI_RUNTIME_SERVICES_DATA:
	case GRUB_EFI_RESERVED_MEMORY_TYPE:
	case GRUB_EFI_MEMORY_MAPPED_IO:
	case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE:
	case GRUB_EFI_UNUSABLE_MEMORY:
	case GRUB_EFI_PAL_CODE:
	  add_memory_region (e820_map, e820_nr_map,
			     desc->physical_start, desc->num_pages << 12,
			     E820_RESERVED);
	  break;
	case GRUB_EFI_LOADER_CODE:
	case GRUB_EFI_LOADER_DATA:
	case GRUB_EFI_BOOT_SERVICES_CODE:
	case GRUB_EFI_BOOT_SERVICES_DATA:
	case GRUB_EFI_CONVENTIONAL_MEMORY:
	  start = desc->physical_start;
	  size = desc->num_pages << 12;
	  end = start + size;
	  if (start < 0x100000ULL && end > 0xA0000ULL)
	    {
	      if (start < 0xA0000ULL)
		add_memory_region (e820_map, e820_nr_map,
				   start, 0xA0000ULL-start,
				   E820_RAM);
	      if (end <= 0x100000ULL)
		continue;
	      start = 0x100000ULL;
	      size = end - start;
	    }
	  add_memory_region (e820_map, e820_nr_map,
			     start, size, E820_RAM);
	  break;
	case GRUB_EFI_ACPI_MEMORY_NVS:
	  add_memory_region (e820_map, e820_nr_map,
			     desc->physical_start, desc->num_pages << 12,
			     E820_NVS);
	  break;
	}
    }
}
Exemple #11
0
/**
  Dump out the EFI memory map

  Argv[0] - "memmap"

  @param  Argc   Number of command arguments in Argv
  @param  Argv   Array of strings that represent the parsed command line.
                 Argv[0] is the command name

  @return EFI_SUCCESS

**/
EFI_STATUS
EblMemMapCmd (
  IN UINTN  Argc,
  IN CHAR8  **Argv
  )
{
  EFI_STATUS            Status;
  EFI_MEMORY_DESCRIPTOR *MemMap;
  EFI_MEMORY_DESCRIPTOR *OrigMemMap;
  UINTN                 MemMapSize;
  UINTN                 MapKey;
  UINTN                 DescriptorSize;
  UINT32                DescriptorVersion;
  UINT64                PageCount[EfiMaxMemoryType];
  UINTN                 Index;
  UINT64                EntrySize;
  UINTN                 CurrentRow;
  UINT64                TotalMemory;

  ZeroMem (PageCount, sizeof (PageCount));

  AsciiPrint ("EFI Memory Map\n");

  // First call is to figure out how big the buffer needs to be
  MemMapSize = 0;
  MemMap     = NULL;
  Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);
  if (Status == EFI_BUFFER_TOO_SMALL) {
    // In case the AllocatPool changes the memory map we added in some extra descriptors
    MemMapSize += (DescriptorSize * 0x100);
    OrigMemMap = MemMap = AllocatePool (MemMapSize);
    if (OrigMemMap != NULL) {
      // 2nd time we get the data
      Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);
      if (!EFI_ERROR (Status)) {
        for (Index = 0, CurrentRow = 0; Index < MemMapSize/DescriptorSize; Index++) {
          EntrySize = LShiftU64 (MemMap->NumberOfPages, 12);
          AsciiPrint ("\n%a %016lx - %016lx: # %08lx %016lx", gMemMapType[MemMap->Type % EfiMaxMemoryType], MemMap->PhysicalStart, MemMap->PhysicalStart + EntrySize -1, MemMap->NumberOfPages, MemMap->Attribute);
          if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {
            break;
          }

          PageCount[MemMap->Type % EfiMaxMemoryType] += MemMap->NumberOfPages;
          MemMap = NEXT_MEMORY_DESCRIPTOR (MemMap, DescriptorSize);
        }
      }

      for (Index = 0, TotalMemory = 0; Index < EfiMaxMemoryType; Index++) {
        if (PageCount[Index] != 0) {
          AsciiPrint ("\n  %a %,7ld Pages (%,14ld)", gMemMapType[Index], PageCount[Index], LShiftU64 (PageCount[Index], 12));
          if (Index == EfiLoaderCode ||
              Index == EfiLoaderData ||
              Index == EfiBootServicesCode ||
              Index == EfiBootServicesData ||
              Index == EfiRuntimeServicesCode ||
              Index == EfiRuntimeServicesData ||
              Index == EfiConventionalMemory ||
              Index == EfiACPIReclaimMemory ||
              Index == EfiACPIMemoryNVS ||
              Index == EfiPalCode
          ) {
            // Count total memory
            TotalMemory += PageCount[Index];
          }
        }
      }

      AsciiPrint ("\nTotal Memory: %,ld MB (%,ld bytes)\n", RShiftU64 (TotalMemory, 8), LShiftU64 (TotalMemory, 12));

      FreePool (OrigMemMap);

    }
  }

  return EFI_SUCCESS;
}
Exemple #12
0
/**
  Split the memory map to new entries, according to one old entry,
  based upon PE code section and data section.

  @param  OldRecord              A pointer to one old memory map entry.
  @param  NewRecord              A pointer to several new memory map entries.
                                 The caller gurantee the buffer size be 1 +
                                 (SplitRecordCount * DescriptorSize) calculated
                                 below.
  @param  MaxSplitRecordCount    The max number of splitted entries
  @param  DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.

  @retval  0 no entry is splitted.
  @return  the real number of splitted record.
**/
STATIC
UINTN
SplitRecord (
  IN EFI_MEMORY_DESCRIPTOR     *OldRecord,
  IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord,
  IN UINTN                     MaxSplitRecordCount,
  IN UINTN                     DescriptorSize
  )
{
  EFI_MEMORY_DESCRIPTOR   TempRecord;
  IMAGE_PROPERTIES_RECORD *ImageRecord;
  IMAGE_PROPERTIES_RECORD *NewImageRecord;
  UINT64                  PhysicalStart;
  UINT64                  PhysicalEnd;
  UINTN                   NewRecordCount;
  UINTN                   TotalNewRecordCount;
  BOOLEAN                 IsLastRecordData;

  if (MaxSplitRecordCount == 0) {
    CopyMem (NewRecord, OldRecord, DescriptorSize);
    return 0;
  }

  TotalNewRecordCount = 0;

  //
  // Override previous record
  //
  CopyMem (&TempRecord, OldRecord, sizeof(EFI_MEMORY_DESCRIPTOR));
  PhysicalStart = TempRecord.PhysicalStart;
  PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize(TempRecord.NumberOfPages);

  ImageRecord = NULL;
  do {
    NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart);
    if (NewImageRecord == NULL) {
      //
      // No more image covered by this range, stop
      //
      if ((PhysicalEnd > PhysicalStart) && (ImageRecord != NULL)) {
        //
        // If this is still address in this record, need record.
        //
        NewRecord = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
        IsLastRecordData = FALSE;
        if (!mPropertiesTableEnable) {
          if ((NewRecord->Attribute & EFI_MEMORY_XP) != 0) {
            IsLastRecordData = TRUE;
          }
        } else {
          if (NewRecord->Type == EfiRuntimeServicesData) {
            IsLastRecordData = TRUE;
          }
        }
        if (IsLastRecordData) {
          //
          // Last record is DATA, just merge it.
          //
          NewRecord->NumberOfPages = EfiSizeToPages(PhysicalEnd - NewRecord->PhysicalStart);
        } else {
          //
          // Last record is CODE, create a new DATA entry.
          //
          NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
          if (!mPropertiesTableEnable) {
            NewRecord->Type = TempRecord.Type;
          } else {
            NewRecord->Type = EfiRuntimeServicesData;
          }
          NewRecord->PhysicalStart = TempRecord.PhysicalStart;
          NewRecord->VirtualStart  = 0;
          NewRecord->NumberOfPages = TempRecord.NumberOfPages;
          NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
          TotalNewRecordCount ++;
        }
      }
      break;
    }
    ImageRecord = NewImageRecord;

    //
    // Set new record
    //
    NewRecordCount = SetNewRecord (ImageRecord, NewRecord, &TempRecord, DescriptorSize);
    TotalNewRecordCount += NewRecordCount;
    NewRecord = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + NewRecordCount * DescriptorSize);

    //
    // Update PhysicalStart, in order to exclude the image buffer already splitted.
    //
    PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize;
    TempRecord.PhysicalStart = PhysicalStart;
    TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
  } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));

  return TotalNewRecordCount - 1;
}
Exemple #13
0
/**
  Set the memory map to new entries, according to one old entry,
  based upon PE code section and data section in image record

  @param  ImageRecord            An image record whose [ImageBase, ImageSize] covered
                                 by old memory map entry.
  @param  NewRecord              A pointer to several new memory map entries.
                                 The caller gurantee the buffer size be 1 +
                                 (SplitRecordCount * DescriptorSize) calculated
                                 below.
  @param  OldRecord              A pointer to one old memory map entry.
  @param  DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
**/
STATIC
UINTN
SetNewRecord (
  IN IMAGE_PROPERTIES_RECORD       *ImageRecord,
  IN OUT EFI_MEMORY_DESCRIPTOR     *NewRecord,
  IN EFI_MEMORY_DESCRIPTOR         *OldRecord,
  IN UINTN                         DescriptorSize
  )
{
  EFI_MEMORY_DESCRIPTOR                     TempRecord;
  IMAGE_PROPERTIES_RECORD_CODE_SECTION      *ImageRecordCodeSection;
  LIST_ENTRY                                *ImageRecordCodeSectionLink;
  LIST_ENTRY                                *ImageRecordCodeSectionEndLink;
  LIST_ENTRY                                *ImageRecordCodeSectionList;
  UINTN                                     NewRecordCount;
  UINT64                                    PhysicalEnd;
  UINT64                                    ImageEnd;

  CopyMem (&TempRecord, OldRecord, sizeof(EFI_MEMORY_DESCRIPTOR));
  PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize(TempRecord.NumberOfPages);
  NewRecordCount = 0;

  ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;

  ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;
  ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
  while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
    ImageRecordCodeSection = CR (
                               ImageRecordCodeSectionLink,
                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
                               Link,
                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
                               );
    ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;

    if (TempRecord.PhysicalStart <= ImageRecordCodeSection->CodeSegmentBase) {
      //
      // DATA
      //
      if (!mPropertiesTableEnable) {
        NewRecord->Type = TempRecord.Type;
      } else {
        NewRecord->Type = EfiRuntimeServicesData;
      }
      NewRecord->PhysicalStart = TempRecord.PhysicalStart;
      NewRecord->VirtualStart  = 0;
      NewRecord->NumberOfPages = EfiSizeToPages(ImageRecordCodeSection->CodeSegmentBase - NewRecord->PhysicalStart);
      NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
      if (NewRecord->NumberOfPages != 0) {
        NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
        NewRecordCount ++;
      }

      //
      // CODE
      //
      if (!mPropertiesTableEnable) {
        NewRecord->Type = TempRecord.Type;
      } else {
        NewRecord->Type = EfiRuntimeServicesCode;
      }
      NewRecord->PhysicalStart = ImageRecordCodeSection->CodeSegmentBase;
      NewRecord->VirtualStart  = 0;
      NewRecord->NumberOfPages = EfiSizeToPages(ImageRecordCodeSection->CodeSegmentSize);
      NewRecord->Attribute     = (TempRecord.Attribute & (~EFI_MEMORY_XP)) | EFI_MEMORY_RO;
      if (NewRecord->NumberOfPages != 0) {
        NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
        NewRecordCount ++;
      }

      TempRecord.PhysicalStart = ImageRecordCodeSection->CodeSegmentBase + EfiPagesToSize (EfiSizeToPages(ImageRecordCodeSection->CodeSegmentSize));
      TempRecord.NumberOfPages = EfiSizeToPages(PhysicalEnd - TempRecord.PhysicalStart);
      if (TempRecord.NumberOfPages == 0) {
        break;
      }
    }
  }

  ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize;

  //
  // Final DATA
  //
  if (TempRecord.PhysicalStart < ImageEnd) {
    if (!mPropertiesTableEnable) {
      NewRecord->Type = TempRecord.Type;
    } else {
      NewRecord->Type = EfiRuntimeServicesData;
    }
    NewRecord->PhysicalStart = TempRecord.PhysicalStart;
    NewRecord->VirtualStart  = 0;
    NewRecord->NumberOfPages = EfiSizeToPages (ImageEnd - TempRecord.PhysicalStart);
    NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
    NewRecordCount ++;
  }

  return NewRecordCount;
}
Exemple #14
0
/**

  Determines the new virtual address that is to be used on subsequent memory accesses.


  @param DebugDisposition Supplies type information for the pointer being converted.
  @param ConvertAddress  A pointer to a pointer that is to be fixed to be the value needed
                         for the new virtual address mappings being applied.

  @retval  EFI_SUCCESS              The pointer pointed to by Address was modified.
  @retval  EFI_NOT_FOUND            The pointer pointed to by Address was not found to be part
                                    of the current memory map. This is normally fatal.
  @retval  EFI_INVALID_PARAMETER    One of the parameters has an invalid value.

**/
EFI_STATUS
EFIAPI
RuntimeDriverConvertPointer (
    IN     UINTN  DebugDisposition,
    IN OUT VOID   **ConvertAddress
)
{
    UINTN                 Address;
    UINT64                VirtEndOfRange;
    EFI_MEMORY_DESCRIPTOR *VirtEntry;
    UINTN                 Index;

    //
    // Make sure ConvertAddress is a valid pointer
    //
    if (ConvertAddress == NULL) {
        return EFI_INVALID_PARAMETER;
    }
    //
    // Get the address to convert
    //
    Address = (UINTN) *ConvertAddress;

    //
    // If this is a null pointer, return if it's allowed
    //
    if (Address == 0) {
        if ((DebugDisposition & EFI_OPTIONAL_PTR) != 0) {
            return EFI_SUCCESS;
        }

        return EFI_INVALID_PARAMETER;
    }

    VirtEntry = mVirtualMap;
    for (Index = 0; Index < mVirtualMapMaxIndex; Index++) {
        //
        //  To prevent the inclusion of 64-bit math functions a UINTN was placed in
        //  front of VirtEntry->NumberOfPages to cast it to a 32-bit thing on IA-32
        //  platforms. If you get this ASSERT remove the UINTN and do a 64-bit
        //  multiply.
        //
        ASSERT (((UINTN) VirtEntry->NumberOfPages < 0xffffffff) || (sizeof (UINTN) > 4));

        if ((VirtEntry->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) {
            if (Address >= VirtEntry->PhysicalStart) {
                VirtEndOfRange = VirtEntry->PhysicalStart + (((UINTN) VirtEntry->NumberOfPages) * EFI_PAGE_SIZE);
                if (Address < VirtEndOfRange) {
                    //
                    // Compute new address
                    //
                    *ConvertAddress = (VOID *) (Address - (UINTN) VirtEntry->PhysicalStart + (UINTN) VirtEntry->VirtualStart);
                    return EFI_SUCCESS;
                }
            }
        }

        VirtEntry = NEXT_MEMORY_DESCRIPTOR (VirtEntry, mVirtualMapDescriptorSize);
    }

    return EFI_NOT_FOUND;
}
/*attempts to allocate the requested number bytes, as a contigous chunk of memory, returns the pointer to the first byte on success
* or returns NULL on failure*/
void* st_memmgr_alloc(uint16_t size){
	MEMORY_DESCRIPTOR *mem_desc;
	uint8_t bank_visit_counter=0;
	uint16_t i;
	uint16_t cont_free_block_size;
	void* return_addr=NULL;

	size+=sizeof(MEMORY_DESCRIPTOR);	//account for the memory descriptor

	if(size > BANK_1_SIZE)	//if size is greater than the size of BANK_1 then allocation will fail
		goto RETURN_ALLOCATE;
	if(size<=MEM_REQUEST_SMALL)
		goto MEMORY_BANK_0;
	else
		goto MEMORY_BANK_1;
MEMORY_BANK_0:;
	bank_visit_counter++;
	if(bank_visit_counter==MAX_ATTEMPTS)	//all banks visited
		goto RETURN_ALLOCATE;
	i=0;
	cont_free_block_size=0;
	mem_desc=(MEMORY_DESCRIPTOR*)st_memory.BANK_0;	//start of BANK_0

	while(i<BANK_0_SIZE){	//search till the end of BANK_0 boundary
		if(IS_ALLOCATED((*mem_desc))){	//this bank is allocated
			i+=(GET_BLOCK_OFFSET((*mem_desc))*BLOCK_SIZE);
			mem_desc=NEXT_MEMORY_DESCRIPTOR(mem_desc);
			cont_free_block_size=0;
			continue;
		}else{
			cont_free_block_size+=(GET_BLOCK_OFFSET((*mem_desc))*BLOCK_SIZE);
			if(cont_free_block_size >= size)
				break; //found a free block large enough to satisfy memory request
			i+=(GET_BLOCK_OFFSET((*mem_desc))*BLOCK_SIZE);
			mem_desc=NEXT_MEMORY_DESCRIPTOR(mem_desc);
		}
	}

	if(i>=BANK_0_SIZE)	//failed to satisfy request in MEMORY_BANK_0
		goto MEMORY_BANK_1;

	/*free block found, allocate whatever is required and make the rest space as a free block*/
	if(calculateBlockOffset(size) < calculateBlockOffset(cont_free_block_size)){
		mem_desc=(MEMORY_DESCRIPTOR*)(((uint8_t*)NEXT_MEMORY_DESCRIPTOR(mem_desc))-cont_free_block_size);
		SET_ALLOCATED((*mem_desc));
		SET_BLOCK_OFFSET((*mem_desc),calculateBlockOffset(size));
		return_addr=((void*)mem_desc)+sizeof(MEMORY_DESCRIPTOR);	//actual data to be stored here

		/*make a new free block*/
		mem_desc=NEXT_MEMORY_DESCRIPTOR(mem_desc);
		CLEAR_ALLOCATED((*mem_desc));
		SET_BLOCK_OFFSET((*mem_desc), (calculateBlockOffset(cont_free_block_size)-calculateBlockOffset(size)));
	}else{		
		mem_desc=(MEMORY_DESCRIPTOR*)(((uint8_t*)NEXT_MEMORY_DESCRIPTOR(mem_desc))-cont_free_block_size);
		SET_ALLOCATED((*mem_desc));
		SET_BLOCK_OFFSET((*mem_desc),calculateBlockOffset(size));
		return_addr=((void*)mem_desc)+sizeof(MEMORY_DESCRIPTOR);	//actual data to be stored here
	}
	goto RETURN_ALLOCATE;
MEMORY_BANK_1:;
	bank_visit_counter++;
	if(bank_visit_counter==MAX_ATTEMPTS)	//all banks visited
		goto RETURN_ALLOCATE;
	i=0;
	cont_free_block_size=0;
	mem_desc=(MEMORY_DESCRIPTOR*)st_memory.BANK_1;	//start of BANK_1

	while(i<BANK_1_SIZE){	//search till the end of BANK_0 boundary
		if(IS_ALLOCATED((*mem_desc))){	//this bank is allocated
			i+=(GET_BLOCK_OFFSET((*mem_desc))*BLOCK_SIZE);
			mem_desc=NEXT_MEMORY_DESCRIPTOR(mem_desc);
			cont_free_block_size=0;
			continue;
		}else{
			cont_free_block_size+=(GET_BLOCK_OFFSET((*mem_desc))*BLOCK_SIZE);
			if(cont_free_block_size >= size)
				break; //found a free block large enough to satisfy memory request
			i+=(GET_BLOCK_OFFSET((*mem_desc))*BLOCK_SIZE);
			mem_desc=NEXT_MEMORY_DESCRIPTOR(mem_desc);
		}
	}

	if(i>=BANK_1_SIZE)	//failed to satisfy request in MEMORY_BANK_1
		goto MEMORY_BANK_0;

	/*free block found, allocate whatever is required and make the rest space as a free block*/
	if(calculateBlockOffset(size) < calculateBlockOffset(cont_free_block_size)){
		mem_desc=(MEMORY_DESCRIPTOR*)(((uint8_t*)NEXT_MEMORY_DESCRIPTOR(mem_desc))-cont_free_block_size);
		SET_ALLOCATED((*mem_desc));
		SET_BLOCK_OFFSET((*mem_desc),calculateBlockOffset(size));
		return_addr=((void*)mem_desc)+sizeof(MEMORY_DESCRIPTOR);	//actual data to be stored here
		/*make a new free block*/
		mem_desc=NEXT_MEMORY_DESCRIPTOR(mem_desc);
		CLEAR_ALLOCATED((*mem_desc));
		SET_BLOCK_OFFSET((*mem_desc), (calculateBlockOffset(cont_free_block_size)-calculateBlockOffset(size)));
	}else{		
		mem_desc=(MEMORY_DESCRIPTOR*)(((uint8_t*)NEXT_MEMORY_DESCRIPTOR(mem_desc))-cont_free_block_size);
		SET_ALLOCATED((*mem_desc));
		SET_BLOCK_OFFSET((*mem_desc),calculateBlockOffset(size));
		return_addr=((void*)mem_desc)+sizeof(MEMORY_DESCRIPTOR);	//actual data to be stored here
	}
	goto RETURN_ALLOCATE;

RETURN_ALLOCATE:;
	lastRequestSize=size;
	if(return_addr!=NULL){
		actual_memory_utilization+=size;
		lastRequestStatus=1;
		if(actual_memory_utilization>peak_memory_utilization)
			peak_memory_utilization=actual_memory_utilization;
	}else
		lastRequestStatus=0;
	return return_addr;
}	
Exemple #16
0
VOID EFIAPI
ShrinkMemMap(
	IN UINTN			*MemoryMapSize,
	IN EFI_MEMORY_DESCRIPTOR	*MemoryMap,
	IN UINTN			DescriptorSize,
	IN UINT32			DescriptorVersion
)
{
	UINTN				SizeFromDescToEnd;
	UINT64				Bytes;
	EFI_MEMORY_DESCRIPTOR		*PrevDesc;
	EFI_MEMORY_DESCRIPTOR		*Desc;
	BOOLEAN				CanBeJoined;
	BOOLEAN				HasEntriesToRemove;
	
	PrevDesc = MemoryMap;
	Desc = NEXT_MEMORY_DESCRIPTOR(PrevDesc, DescriptorSize);
	SizeFromDescToEnd = *MemoryMapSize - DescriptorSize;
	*MemoryMapSize = DescriptorSize;
	HasEntriesToRemove = FALSE;
	while (SizeFromDescToEnd > 0) {
		Bytes = (((UINTN) PrevDesc->NumberOfPages) * EFI_PAGE_SIZE);
		CanBeJoined = FALSE;
		if ((Desc->Attribute == PrevDesc->Attribute) && (PrevDesc->PhysicalStart + Bytes == Desc->PhysicalStart)) {
			if (Desc->Type == EfiBootServicesCode
				|| Desc->Type == EfiBootServicesData
				//|| Desc->Type == EfiConventionalMemory
				//|| Desc->Type == EfiLoaderCode
				//|| Desc->Type == EfiLoaderData
				)
			{
				CanBeJoined = PrevDesc->Type == EfiBootServicesCode
					|| PrevDesc->Type == EfiBootServicesData
					//|| PrevDesc->Type == EfiConventionalMemory
					//|| PrevDesc->Type == EfiLoaderCode
					//|| PrevDesc->Type == EfiLoaderData
					;
			}
		}
		
		if (CanBeJoined) {
			// two entries are the same/similar - join them
			PrevDesc->NumberOfPages += Desc->NumberOfPages;
			HasEntriesToRemove = TRUE;
		} else {
			// can not be joined - we need to move to next
			*MemoryMapSize += DescriptorSize;
			PrevDesc = NEXT_MEMORY_DESCRIPTOR(PrevDesc, DescriptorSize);
			if (HasEntriesToRemove) {
				// have entries between PrevDesc and Desc which are joined to PrevDesc
				// we need to copy [Desc, end of list] to PrevDesc + 1
				CopyMem(PrevDesc, Desc, SizeFromDescToEnd);
				Desc = PrevDesc;
			}
			HasEntriesToRemove = FALSE;
		}
		// move to next
		Desc = NEXT_MEMORY_DESCRIPTOR(Desc, DescriptorSize);
		SizeFromDescToEnd -= DescriptorSize;
	}
}
Exemple #17
0
grub_err_t
grub_machine_mmap_iterate (grub_memory_hook_t hook)
{
  grub_efi_uintn_t mmap_size = 0;
  grub_efi_memory_descriptor_t *map_buf = 0;
  grub_efi_uintn_t map_key = 0;
  grub_efi_uintn_t desc_size = 0;
  grub_efi_uint32_t desc_version = 0;
  grub_efi_memory_descriptor_t *desc;

  if (grub_efi_get_memory_map (&mmap_size, map_buf,
			       &map_key, &desc_size,
			       &desc_version) < 0)
    return grub_errno;

  map_buf = grub_malloc (mmap_size);
  if (! map_buf)
    return grub_errno;

  if (grub_efi_get_memory_map (&mmap_size, map_buf,
			       &map_key, &desc_size,
			       &desc_version) <= 0)
    {
      grub_free (map_buf);
      return grub_errno;
    }

  for (desc = map_buf;
       desc < NEXT_MEMORY_DESCRIPTOR (map_buf, mmap_size);
       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
    {
      grub_dprintf ("mmap", "EFI memory region 0x%llx-0x%llx: %d\n",
		    (unsigned long long) desc->physical_start,
		    (unsigned long long) desc->physical_start
		    + desc->num_pages * 4096, desc->type);
      switch (desc->type)
	{
	case GRUB_EFI_RUNTIME_SERVICES_CODE:
	  hook (desc->physical_start, desc->num_pages * 4096,
		GRUB_MEMORY_CODE);
	  break;

	case GRUB_EFI_UNUSABLE_MEMORY:
	  hook (desc->physical_start, desc->num_pages * 4096,
		GRUB_MEMORY_BADRAM);
	  break;

	default:
	  grub_printf ("Unknown memory type %d, considering reserved\n",
		       desc->type);

	case GRUB_EFI_RESERVED_MEMORY_TYPE:
	case GRUB_EFI_RUNTIME_SERVICES_DATA:
	case GRUB_EFI_MEMORY_MAPPED_IO:
	case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE:
	case GRUB_EFI_PAL_CODE:
	  hook (desc->physical_start, desc->num_pages * 4096,
		GRUB_MEMORY_RESERVED);
	  break;

	case GRUB_EFI_LOADER_CODE:
	case GRUB_EFI_LOADER_DATA:
	case GRUB_EFI_BOOT_SERVICES_CODE:
	case GRUB_EFI_BOOT_SERVICES_DATA:
	case GRUB_EFI_CONVENTIONAL_MEMORY:
	  hook (desc->physical_start, desc->num_pages * 4096,
		GRUB_MEMORY_AVAILABLE);
	  break;

	case GRUB_EFI_ACPI_RECLAIM_MEMORY:
	  hook (desc->physical_start, desc->num_pages * 4096,
		GRUB_MEMORY_ACPI);
	  break;

	case GRUB_EFI_ACPI_MEMORY_NVS:
	  hook (desc->physical_start, desc->num_pages * 4096,
		GRUB_MEMORY_NVS);
	  break;
	}
    }

  return GRUB_ERR_NONE;
}
Exemple #18
0
/** Alloctes Pages from the top of mem, up to address specified in Memory. Returns allocated address in Memory. */
EFI_STATUS
EFIAPI
AllocatePagesFromTop(
	IN EFI_MEMORY_TYPE		MemoryType,
	IN UINTN			Pages,
	IN OUT EFI_PHYSICAL_ADDRESS	*Memory
)
{
	EFI_STATUS			Status;
	UINTN				MemoryMapSize;
	EFI_MEMORY_DESCRIPTOR		*MemoryMap;
	UINTN				MapKey;
	UINTN				DescriptorSize;
	UINT32				DescriptorVersion;
	EFI_MEMORY_DESCRIPTOR		*MemoryMapEnd;
	EFI_MEMORY_DESCRIPTOR		*Desc;
	
	
	Status = GetMemoryMapAlloc(gBS->GetMemoryMap, &MemoryMapSize, &MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion);
	
	if (EFI_ERROR(Status)) {
		return Status;
	}
	
	Status = EFI_NOT_FOUND;
	
	//PRINT("Search for Pages=%x, TopAddr=%lx\n", Pages, *Memory);
	//PRINT("MEMMAP: Size=%d, Addr=%p, DescSize=%d, DescVersion: 0x%x\n", MemoryMapSize, MemoryMap, DescriptorSize, DescriptorVersion);
	//PRINT("Type       Start            End       VStart               # Pages          Attributes\n");
	MemoryMapEnd = NEXT_MEMORY_DESCRIPTOR(MemoryMap, MemoryMapSize);
	Desc = PREV_MEMORY_DESCRIPTOR(MemoryMapEnd, DescriptorSize);
	for ( ; Desc >= MemoryMap; Desc = PREV_MEMORY_DESCRIPTOR(Desc, DescriptorSize)) {
		/*
		PRINT("%-12s %lX-%lX %lX  %lX %lX\n",
			EfiMemoryTypeDesc[Desc->Type],
			Desc->PhysicalStart,
			Desc->PhysicalStart + EFI_PAGES_TO_SIZE(Desc->NumberOfPages) - 1,
			Desc->VirtualStart,
			Desc->NumberOfPages,
			Desc->Attribute
		);
		*/
		if (   (Desc->Type == EfiConventionalMemory)						// free mem
			&& (Pages <= Desc->NumberOfPages)								// contains enough space
			&& (Desc->PhysicalStart + EFI_PAGES_TO_SIZE(Pages) <= *Memory)	// contains space below specified Memory
		)
		{
			// free block found
			if (Desc->PhysicalStart + EFI_PAGES_TO_SIZE((UINTN)Desc->NumberOfPages) <= *Memory) {
				// the whole block is unded Memory - allocate from the top of the block
				*Memory = Desc->PhysicalStart + EFI_PAGES_TO_SIZE((UINTN)Desc->NumberOfPages - Pages);
				//PRINT("found the whole block under top mem, allocating at %lx\n", *Memory);
			} else {
				// the block contains enough pages under Memory, but spans above it - allocate below Memory.
				*Memory = *Memory - EFI_PAGES_TO_SIZE(Pages);
				//PRINT("found the whole block under top mem, allocating at %lx\n", *Memory);
			}
			Status = gBS->AllocatePages(AllocateAddress,
										MemoryType,
										Pages,
										Memory);
			//PRINT("Alloc Pages=%x, Addr=%lx, Status=%r\n", Pages, *Memory, Status);
			break;
		}
	}
	
	// release mem
	FreePool(MemoryMap);
	
	return Status;
}
Exemple #19
0
/**
  return the UEFI memory information.

  @param[out] Below4GMemoryLimit  The below 4GiB memory limit
  @param[out] Above4GMemoryLimit  The above 4GiB memory limit
**/
VOID
ReturnUefiMemoryMap (
  OUT UINT64   *Below4GMemoryLimit,
  OUT UINT64   *Above4GMemoryLimit
  )
{
  EFI_STATUS                  Status;
  EFI_MEMORY_DESCRIPTOR       *EfiMemoryMap;
  EFI_MEMORY_DESCRIPTOR       *EfiMemoryMapEnd;
  EFI_MEMORY_DESCRIPTOR       *EfiEntry;
  EFI_MEMORY_DESCRIPTOR       *NextEfiEntry;
  EFI_MEMORY_DESCRIPTOR       TempEfiEntry;
  UINTN                       EfiMemoryMapSize;
  UINTN                       EfiMapKey;
  UINTN                       EfiDescriptorSize;
  UINT32                      EfiDescriptorVersion;
  UINT64                      MemoryBlockLength;

  *Below4GMemoryLimit = 0;
  *Above4GMemoryLimit = 0;

  //
  // Get the EFI memory map.
  //
  EfiMemoryMapSize  = 0;
  EfiMemoryMap      = NULL;
  Status = gBS->GetMemoryMap (
                  &EfiMemoryMapSize,
                  EfiMemoryMap,
                  &EfiMapKey,
                  &EfiDescriptorSize,
                  &EfiDescriptorVersion
                  );
  ASSERT (Status == EFI_BUFFER_TOO_SMALL);

  do {
    //
    // Use size returned back plus 1 descriptor for the AllocatePool.
    // We don't just multiply by 2 since the "for" loop below terminates on
    // EfiMemoryMapEnd which is dependent upon EfiMemoryMapSize. Otherwize
    // we process bogus entries and create bogus E820 entries.
    //
    EfiMemoryMap = (EFI_MEMORY_DESCRIPTOR *) AllocatePool (EfiMemoryMapSize);
    ASSERT (EfiMemoryMap != NULL);
    Status = gBS->GetMemoryMap (
                    &EfiMemoryMapSize,
                    EfiMemoryMap,
                    &EfiMapKey,
                    &EfiDescriptorSize,
                    &EfiDescriptorVersion
                    );
    if (EFI_ERROR (Status)) {
      FreePool (EfiMemoryMap);
    }
  } while (Status == EFI_BUFFER_TOO_SMALL);

  ASSERT_EFI_ERROR (Status);

  //
  // Sort memory map from low to high
  //
  EfiEntry        = EfiMemoryMap;
  NextEfiEntry    = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);
  EfiMemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + EfiMemoryMapSize);
  while (EfiEntry < EfiMemoryMapEnd) {
    while (NextEfiEntry < EfiMemoryMapEnd) {
      if (EfiEntry->PhysicalStart > NextEfiEntry->PhysicalStart) {
        CopyMem (&TempEfiEntry, EfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
        CopyMem (EfiEntry, NextEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
        CopyMem (NextEfiEntry, &TempEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
      }

      NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (NextEfiEntry, EfiDescriptorSize);
    }

    EfiEntry      = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);
    NextEfiEntry  = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);
  }

  //
  //
  //
  DEBUG ((DEBUG_INFO, "MemoryMap:\n"));
  EfiEntry        = EfiMemoryMap;
  EfiMemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + EfiMemoryMapSize);
  while (EfiEntry < EfiMemoryMapEnd) {
    MemoryBlockLength = (UINT64) (LShiftU64 (EfiEntry->NumberOfPages, 12));
    DEBUG ((DEBUG_INFO, "Entry(0x%02x) 0x%016lx - 0x%016lx\n", EfiEntry->Type, EfiEntry->PhysicalStart, EfiEntry->PhysicalStart + MemoryBlockLength));
    switch (EfiEntry->Type) {
    case EfiLoaderCode:
    case EfiLoaderData:
    case EfiBootServicesCode:
    case EfiBootServicesData:
    case EfiConventionalMemory:
    case EfiRuntimeServicesCode:
    case EfiRuntimeServicesData:
    case EfiACPIReclaimMemory:
    case EfiACPIMemoryNVS:
    case EfiReservedMemoryType:
      if ((EfiEntry->PhysicalStart + MemoryBlockLength) <= BASE_1MB) {
        //
        // Skip the memory block is under 1MB
        //
      } else if (EfiEntry->PhysicalStart >= BASE_4GB) {
        if (*Above4GMemoryLimit < EfiEntry->PhysicalStart + MemoryBlockLength) {
          *Above4GMemoryLimit = EfiEntry->PhysicalStart + MemoryBlockLength;
        }
      } else {
        if (*Below4GMemoryLimit < EfiEntry->PhysicalStart + MemoryBlockLength) {
          *Below4GMemoryLimit = EfiEntry->PhysicalStart + MemoryBlockLength;
        }
      }
      break;
    }
    EfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);
  }

  FreePool (EfiMemoryMap);

  DEBUG ((DEBUG_INFO, "Result:\n"));
  DEBUG ((DEBUG_INFO, "Below4GMemoryLimit:  0x%016lx\n", *Below4GMemoryLimit));
  DEBUG ((DEBUG_INFO, "Above4GMemoryLimit:  0x%016lx\n", *Above4GMemoryLimit));

  return ;
}