/* If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). */
VOID* EFIAPI WriteBackInvalidateDataCacheRange(IN VOID *Address, IN UINTN Length)
/* If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). */
VOID* EFIAPI WriteBackInvalidateDataCacheRange(IN VOID *Address, IN UINTN Length)
{
  UINT32  RegEbx;
  UINT32  RegEdx;
  UINTN   CacheLineSize;
  UINTN   Start;
  UINTN   End;
  if (Length == 0) {
    return Address;
  }
  ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN)Address));
  AsmCpuid (0x01, NULL, &RegEbx, NULL, &RegEdx);
  if ((RegEdx & BIT19) == 0) {
    AsmWbinvd ();
    return Address;
  }
  CacheLineSize = (RegEbx & 0xff00) >> 5;
  Start = (UINTN)Address;
  End    = (Start + Length + (CacheLineSize - 1)) & ~(CacheLineSize - 1);
  Start &= ~((UINTN)CacheLineSize - 1);
  do {
    Start = (UINTN)AsmFlushCacheLine ((VOID *)Start) + CacheLineSize;
  } while (Start != End);
  return Address;
}