예제 #1
0
/**
  Compare two variable names, one of them may be inconsecutive.

  @param StoreInfo      Pointer to variable store info structure.
  @param Name1          Pointer to one variable name.
  @param Name2          Pointer to another variable name.
  @param NameSize       Variable name size.

  @retval TRUE          Name1 and Name2 are identical.
  @retval FALSE         Name1 and Name2 are not identical.

**/
BOOLEAN
CompareVariableName (
  IN VARIABLE_STORE_INFO    *StoreInfo,
  IN CONST CHAR16           *Name1,
  IN CONST CHAR16           *Name2,
  IN UINTN                  NameSize
  )
{
  EFI_PHYSICAL_ADDRESS  TargetAddress;
  EFI_PHYSICAL_ADDRESS  SpareAddress;
  UINTN                 PartialNameSize;

  if (StoreInfo->FtwLastWriteData != NULL) {
    TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
    SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
    if (((UINTN) Name1 < (UINTN) TargetAddress) && (((UINTN) Name1 + NameSize) > (UINTN) TargetAddress)) {
      //
      // Name1 is inconsecutive.
      //
      PartialNameSize = (UINTN) TargetAddress - (UINTN) Name1;
      //
      // Partial content is in NV storage.
      //
      if (CompareMem ((UINT8 *) Name1, (UINT8 *) Name2, PartialNameSize) == 0) {
        //
        // Another partial content is in spare block.
        //
        if (CompareMem ((UINT8 *) (UINTN) SpareAddress, (UINT8 *) Name2 + PartialNameSize, NameSize - PartialNameSize) == 0) {
          return TRUE;
        }
      }
      return FALSE;
    } else if (((UINTN) Name2 < (UINTN) TargetAddress) && (((UINTN) Name2 + NameSize) > (UINTN) TargetAddress)) {
      //
      // Name2 is inconsecutive.
      //
      PartialNameSize = (UINTN) TargetAddress - (UINTN) Name2;
      //
      // Partial content is in NV storage.
      //
      if (CompareMem ((UINT8 *) Name2, (UINT8 *) Name1, PartialNameSize) == 0) {
        //
        // Another partial content is in spare block.
        //
        if (CompareMem ((UINT8 *) (UINTN) SpareAddress, (UINT8 *) Name1 + PartialNameSize, NameSize - PartialNameSize) == 0) {
          return TRUE;
        }
      }
      return FALSE;
    }
  }

  //
  // Both Name1 and Name2 are consecutive.
  //
  if (CompareMem ((UINT8 *) Name1, (UINT8 *) Name2, NameSize) == 0) {
    return TRUE;
  }
  return FALSE;
}
/**
  Used to retrieve the list of legal Target IDs and LUNs for SCSI devices on a SCSI channel. These
  can either be the list SCSI devices that are actually present on the SCSI channel, or the list of legal
  Target Ids and LUNs for the SCSI channel. Regardless, the caller of this function must probe the
  Target ID and LUN returned to see if a SCSI device is actually present at that location on the SCSI
  channel.

  @param[in]       This    A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
  @param[in, out]  Target  On input, a pointer to the Target ID (an array of size
                           TARGET_MAX_BYTES) of a SCSI device present on the SCSI channel.
                           On output, a pointer to the Target ID (an array of
                           TARGET_MAX_BYTES) of the next SCSI device present on a SCSI
                           channel. An input value of 0xF(all bytes in the array are 0xF) in the
                           Target array retrieves the Target ID of the first SCSI device present on a
                           SCSI channel.
  @param[in, out]  Lun     On input, a pointer to the LUN of a SCSI device present on the SCSI
                           channel. On output, a pointer to the LUN of the next SCSI device present
                           on a SCSI channel.

  @retval EFI_SUCCESS           The Target ID and LUN of the next SCSI device on the SCSI
                                channel was returned in Target and Lun.
  @retval EFI_INVALID_PARAMETER Target array is not all 0xF, and Target and Lun were
                                not returned on a previous call to GetNextTargetLun().
  @retval EFI_NOT_FOUND         There are no more SCSI devices on this SCSI channel.
**/
EFI_STATUS
EFIAPI
IScsiExtScsiPassThruGetNextTargetLun (
  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL  *This,
  IN OUT UINT8                        **Target,
  IN OUT UINT64                       *Lun
  )
{
  ISCSI_DRIVER_DATA           *Private;
  ISCSI_SESSION_CONFIG_NVDATA *ConfigNvData;
  UINT8                       TargetId[TARGET_MAX_BYTES];

  Private       = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (This);
  ConfigNvData  = &Private->Session.ConfigData.NvData;

  if ((*Target)[0] == 0 && (CompareMem (Lun, ConfigNvData->BootLun, sizeof (UINT64)) == 0)) {
    //
    // Only one <Target, Lun> pair per iSCSI Driver instance.
    //
    return EFI_NOT_FOUND;
  }

  SetMem (TargetId, TARGET_MAX_BYTES, 0xFF);
  if (CompareMem (*Target, TargetId, TARGET_MAX_BYTES) == 0) {
    (*Target)[0] = 0;
    CopyMem (Lun, ConfigNvData->BootLun, sizeof (UINT64));

    return EFI_SUCCESS;
  }

  return EFI_INVALID_PARAMETER;
}
예제 #3
0
/**
  Check input Pci device info is changed from the default values
  @param PciDeviceInfo    Pointer to PCI_DEVICE_INFO
  @param UpdatePRT        Pointer to BOOLEAN
  @param UpdatePRW        Pointer to BOOLEAN

**/
VOID
SdtCheckPciDeviceInfoChanged (
  IN PCI_DEVICE_INFO        *PciDeviceInfo,
  IN BOOLEAN                *UpdatePRT,
  IN BOOLEAN                *UpdatePRW
  )
{
  UINTN Index = 0;

  if (mQNCPciInfo == NULL) {
    *UpdatePRT = FALSE;
    *UpdatePRW = FALSE;
    return;
  }

  *UpdatePRT = TRUE;
  *UpdatePRW = TRUE;

  for (Index = 0;Index < CURRENT_PCI_DEVICE_NUM; Index++) {
    if ((mQNCPciInfo[Index].BridgeAddress == PciDeviceInfo->BridgeAddress)
      && (mQNCPciInfo[Index].DeviceAddress == PciDeviceInfo->DeviceAddress)) {
      //
      // Find one matched entry
      //
      if (CompareMem (&(mQNCPciInfo[Index].INTA[0]), &PciDeviceInfo->INTA[0], 10) == 0) {
        *UpdatePRT = FALSE;
        *UpdatePRW = FALSE;
        //DEBUG ((EFI_D_ERROR, "Find one matched entry[%d] and no change\n", Index));
      } else {
        if (CompareMem (&(mQNCPciInfo[Index].INTA[0]), &PciDeviceInfo->INTA[0], 8) == 0)
          *UpdatePRT = FALSE;

        if (CompareMem (&(mQNCPciInfo[Index].GPEPin), &PciDeviceInfo->GPEPin, 2) == 0)
          *UpdatePRW = FALSE;

        if (*(UINT64 *)(&PciDeviceInfo->INTA[0]) == 0xFFFFFFFFFFFFFFFFULL)
          *UpdatePRT = FALSE;

        if (*(UINT16 *)(&PciDeviceInfo->GPEPin) == 0xFFFF)
          *UpdatePRW = FALSE;

        //DEBUG ((EFI_D_ERROR, "Find one matched entry[%d] and but need update PRT:0x%x PRW:0x%x\n", Index, *UpdatePRT, *UpdatePRW));
      }
      break;
    }
  }

  //if (Index == 42) {
  //  DEBUG ((EFI_D_ERROR, "Find No matched entry\n"));
  //}

  return;
}
예제 #4
0
파일: IScsiCHAP.c 프로젝트: jeppeter/vbox
/**
  The initator checks the CHAP response replied by target against its own
  calculation of the expected hash value.

  @param[in]   AuthData             iSCSI CHAP authentication data.
  @param[in]   TargetResponse       The response from target.

  @retval EFI_SUCCESS               The response from target passed authentication.
  @retval EFI_SECURITY_VIOLATION    The response from target was not expected value.
  @retval Others                    Other errors as indicated.

**/
EFI_STATUS
IScsiCHAPAuthTarget (
  IN  ISCSI_CHAP_AUTH_DATA  *AuthData,
  IN  UINT8                 *TargetResponse
  )
{
  EFI_STATUS  Status;
  UINT32      SecretSize;
  UINT8       VerifyRsp[ISCSI_CHAP_RSP_LEN];

  Status      = EFI_SUCCESS;

  SecretSize  = (UINT32) AsciiStrLen (AuthData->AuthConfig->ReverseCHAPSecret);
  Status = IScsiCHAPCalculateResponse (
             AuthData->OutIdentifier,
             AuthData->AuthConfig->ReverseCHAPSecret,
             SecretSize,
             AuthData->OutChallenge,
             AuthData->OutChallengeLength,
             VerifyRsp
             );

  if (CompareMem (VerifyRsp, TargetResponse, ISCSI_CHAP_RSP_LEN) != 0) {
    Status = EFI_SECURITY_VIOLATION;
  }

  return Status;
}
예제 #5
0
/**
  Searches Source for Search pattern of size SearchSize
  and replaces it with Replace up to MaxReplaces times.
 
  @param  Source      Source bytes that will be searched.
  @param  SourceSize  Number of bytes in Source region.
  @param  Search      Bytes to search for.
  @param  SearchSize  Number of bytes in Search.
  @param  Replace     Bytes that will replace found bytes in Source (size is SearchSize).
  @param  MaxReplaces Maximum number of replaces. If MaxReplaces <= 0, then there is no restriction.

  @retval Number of replaces done.

 **/
UINTN
VideoBiosPatchSearchAndReplace (
  IN  UINT8       *Source,
  IN  UINTN       SourceSize,
  IN  UINT8       *Search,
  IN  UINTN       SearchSize,
  IN  UINT8       *Replace,
  IN  INTN        MaxReplaces
  )
{
  UINTN     NumReplaces = 0;
  BOOLEAN   NoReplacesRestriction = MaxReplaces <= 0;
  UINT8     *End = Source + SourceSize;
  
  DBG ("VideoBiosPatchSearchAndReplace:");
  while (Source < End && (NoReplacesRestriction || MaxReplaces > 0)) {
    if (CompareMem(Source, Search, SearchSize) == 0) {
      CopyMem(Source, Replace, SearchSize);
      NumReplaces++;
      MaxReplaces--;
      DBG (" offset = 0x%x.", Source);
      Source += SearchSize;
    } else {
      Source++;
    }
  }
  DBG ("\n");
  return NumReplaces;
}
예제 #6
0
VOID
AsusAICPUPMPatch (
    UINT8   *Driver,
    UINT32  DriverSize,
    CHAR8   *InfoPlist,
    UINT32  InfoPlistSize
)
{
    UINTN   Index1;
    UINTN   Index2;
    UINTN   Count;

    Count = 0;

    //TODO: we should scan only __text __TEXT
    for (Index1 = 0; Index1 < DriverSize; Index1++) {
        // search for MovlE2ToEcx
        if (CompareMem ((Driver + Index1), MovlE2ToEcx, sizeof (MovlE2ToEcx)) == 0) {
            // search for wrmsr in next few bytes
            for (Index2 = (Index1 + sizeof (MovlE2ToEcx)); Index2 < (Index1 + sizeof (MovlE2ToEcx) + 16); Index2++) {
                if ((Driver[Index2] == Wrmsr[0]) && (Driver[Index2 + 1] == Wrmsr[1])) {
                    // found it - patch it with nops
                    Count++;
                    Driver[Index2] = 0x90;
                    Driver[Index2 + 1] = 0x90;
                }
            }
        }
    }
}
예제 #7
0
//
// Searches Source for Search pattern of size SearchSize
// and replaces it with Replace up to MaxReplaces times.
// If MaxReplaces <= 0, then there is no restriction on number of replaces.
// Replace should have the same size as Search.
// Returns number of replaces done.
//
UINTN
SearchAndReplace (
    UINT8   *Source,
    UINT32  SourceSize,
    CHAR8   *Search,
    UINTN   SearchSize,
    CHAR8   *Replace,
    INTN    MaxReplaces
)
{
    UINTN     NumReplaces;
    BOOLEAN   NoReplacesRestriction;
    UINT8     *End;

    NumReplaces = 0;
    NoReplacesRestriction = MaxReplaces <= 0;
    End = Source + SourceSize;

    while (Source < End && (NoReplacesRestriction || MaxReplaces > 0)) {
        if (CompareMem (Source, Search, SearchSize) == 0) {
            CopyMem (Source, Replace, SearchSize);
            NumReplaces++;
            MaxReplaces--;
            Source += SearchSize;
        } else {
            Source++;
        }
    }
    return NumReplaces;
}
예제 #8
0
파일: Match.c 프로젝트: AshleyDeSimone/edk2
/**
  Find the matching PAD with Indexer.

  @param[in] PadId      The pointer to the EFI_IPSEC_PAD_ID structure.
  @param[in] Data       The pointer to the EFI_IPSEC_PAD_DATA structure.
  @param[in] Indexer    The pointer to the SPD_ENTRY_INDEXER structure.

  @retval TRUE     The matched PAD is found.
  @retval FALSE    The matched PAD is not found.
**/
BOOLEAN
MatchPadEntry (
  IN EFI_IPSEC_PAD_ID      *PadId,
  IN EFI_IPSEC_PAD_DATA    *Data,
  IN PAD_ENTRY_INDEXER     *Indexer
  )
{
  BOOLEAN                       Match;

  Match = FALSE;
  if (!IsMemoryZero (&Indexer->PadId, sizeof (EFI_IPSEC_PAD_ID))) {
    Match = (BOOLEAN) ((Indexer->PadId.PeerIdValid == PadId->PeerIdValid) &&
                       ((PadId->PeerIdValid &&
                         (StrCmp (
                            (CONST CHAR16 *) Indexer->PadId.Id.PeerId,
                            (CONST CHAR16 *) PadId->Id.PeerId
                            ) == 0)) ||
                        ((!PadId->PeerIdValid) &&
                         (Indexer->PadId.Id.IpAddress.PrefixLength == PadId->Id.IpAddress.PrefixLength) &&
                         (CompareMem (
                            &Indexer->PadId.Id.IpAddress.Address,
                            &PadId->Id.IpAddress.Address,
                            sizeof (EFI_IP_ADDRESS)
                            ) == 0))));
  } else {
    if (Indexer->Index == 0) {
      Match = TRUE;
    }

    Indexer->Index--;
  }

  return Match;
}
예제 #9
0
/**
  This function compares a variable with variable entries in database.

  @param  Variable      Pointer to the variable in our database
  @param  VariableName  Name of the variable to compare to 'Variable'
  @param  VendorGuid    GUID of the variable to compare to 'Variable'
  @param  PtrTrack      Variable Track Pointer structure that contains Variable Information.

  @retval EFI_SUCCESS    Found match variable
  @retval EFI_NOT_FOUND  Variable not found

**/
EFI_STATUS
CompareWithValidVariable (
    IN  VARIABLE_HEADER               *Variable,
    IN  CONST CHAR16                  *VariableName,
    IN  CONST EFI_GUID                *VendorGuid,
    OUT VARIABLE_POINTER_TRACK        *PtrTrack
)
{
    VOID  *Point;

    if (VariableName[0] == 0) {
        PtrTrack->CurrPtr = Variable;
        return EFI_SUCCESS;
    } else {
        //
        // Don't use CompareGuid function here for performance reasons.
        // Instead we compare the GUID a UINT32 at a time and branch
        // on the first failed comparison.
        //
        if ((((INT32 *) VendorGuid)[0] == ((INT32 *) &Variable->VendorGuid)[0]) &&
                (((INT32 *) VendorGuid)[1] == ((INT32 *) &Variable->VendorGuid)[1]) &&
                (((INT32 *) VendorGuid)[2] == ((INT32 *) &Variable->VendorGuid)[2]) &&
                (((INT32 *) VendorGuid)[3] == ((INT32 *) &Variable->VendorGuid)[3])
           ) {
            ASSERT (NameSizeOfVariable (Variable) != 0);
            Point = (VOID *) GetVariableNamePtr (Variable);
            if (CompareMem (VariableName, Point, NameSizeOfVariable (Variable)) == 0) {
                PtrTrack->CurrPtr = Variable;
                return EFI_SUCCESS;
            }
        }
    }

    return EFI_NOT_FOUND;
}
예제 #10
0
void tp_draw_logo(EFI_GRAPHICS_OUTPUT_PROTOCOL* gop)
{
    if (NULL == gop){

        return;
    }

    acpi_bgrt = NULL;

    for (UINTN i = 0; gST->NumberOfTableEntries > i; ++i){

        EFI_GUID* guid = &(gST->ConfigurationTable[i].VendorGuid);
        UINT8* table = (UINT8*)(gST->ConfigurationTable[i].VendorTable);

        if (0 == CompareMem(guid, &gEfiAcpiTableGuid, sizeof(EFI_GUID))){

            tp_get_bgrt(table);

            if (NULL == acpi_bgrt){

                return;
            }

            tp_draw_logo2(gop);

            break;
        }
    }
}
예제 #11
0
/**
  Check whether the DevicePath is in the device path forbid list 
  (mAccessInfo.LoadForbid).

  @param[in]  DevicePath           Points to device path.
  
  @retval TRUE     The DevicePath is in the device path forbid list.
  @retval FALSE    The DevicePath is not in the device path forbid list.

**/
BOOLEAN
IsLoadForbidden (
  IN  EFI_DEVICE_PATH_PROTOCOL                  *DevicePath
  )
{
  UINTN                     OffSet;
  UINTN                     DPSize;
  UINTN                     Size;
  EFI_DEVICE_PATH_PROTOCOL  *Dp;

  OffSet = 0;
  Size   = GetDevicePathSize (DevicePath);
  //
  // Check each device path.
  //
  while (OffSet < mAccessInfo.LoadForbidLen) {
    Dp      = (EFI_DEVICE_PATH_PROTOCOL *) (mAccessInfo.LoadForbid + OffSet);
    DPSize  = GetDevicePathSize (Dp);
    //
    // Compare device path.
    //
    if ((DPSize == Size) && (CompareMem (DevicePath, Dp, Size) == 0)) {
      return TRUE;
    }
    OffSet += DPSize;
  }
  return FALSE;
}
예제 #12
0
EFI_STATUS
InternalCompareBlock (
  IN  EFI_PHYSICAL_ADDRESS        BaseAddress,
  IN  UINT8                       *Buffer
  )
{
  EFI_STATUS                              Status;
  VOID                                    *CompareBuffer;
  UINT32                                  NumBytes;
  INTN                                    CompareResult;

  NumBytes = BLOCK_SIZE;
  CompareBuffer = AllocatePool (NumBytes);
  if (CompareBuffer == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Done;
  }

  Status = SpiFlashRead ((UINTN) BaseAddress, &NumBytes, CompareBuffer);
  if (EFI_ERROR (Status)) {
    goto Done;
  }
  CompareResult = CompareMem (CompareBuffer, Buffer, BLOCK_SIZE);
  if (CompareResult != 0) {
    Status = EFI_VOLUME_CORRUPTED;
  }

Done:
  if (CompareBuffer != NULL) {
    FreePool (CompareBuffer);
  }

  return Status;
}
예제 #13
0
/**
  Check the integrity of firmware volume header

  @param[in]  FwVolHeader   A pointer to a firmware volume header

  @retval     TRUE          The firmware volume is consistent
  @retval     FALSE         The firmware volume has corrupted.

**/
STATIC
BOOLEAN
IsFvHeaderValid (
  IN EFI_FIRMWARE_VOLUME_HEADER    *FwVolHeader
  )
{
  UINT16 Checksum;

  // Skip nv storage fv
  if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid, sizeof(EFI_GUID)) != 0 ) {
    return FALSE;
  }

  if ( (FwVolHeader->Revision != EFI_FVH_REVISION)   ||
     (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
     (FwVolHeader->FvLength == ((UINTN) -1))       ||
     ((FwVolHeader->HeaderLength & 0x01 ) !=0) )  {
    return FALSE;
  }

  Checksum = CalculateCheckSum16 ((UINT16 *) FwVolHeader, FwVolHeader->HeaderLength);
  if (Checksum != 0) {
    DEBUG (( DEBUG_ERROR,
              "ERROR - Invalid Firmware Volume Header Checksum, change 0x%04x to 0x%04x\r\n",
              FwVolHeader->Checksum,
              (UINT16)( Checksum + FwVolHeader->Checksum )));
    return FALSE;
  }

  return TRUE;
}
예제 #14
0
void __fastcall TScreenSpy::GetNext()
{
    TRect rt;
    TPoint pt;
    int i, l, t;
    FmsScr->Clear();
    for (i = 0; i < BNUMS; i++)
    {
        FFlag1[i] = FFocus[i] > 0;
        FFlag2[i] = false;
    }
    GetCursorPos(&pt);
    FFlag1[pt.x / FBWidth + pt.y / FBHeight * BSIZE] = true;
    FDC = GetDC(0);
    i = 0;
    while (i < BNUMS)
    {
        if (FFlag1[i] && (!FFlag2[i])) 
        {
            FFlag2[i] = true;
            l = (i % BSIZE) * FBWidth;
            t = (i / BSIZE) * FBHeight;
            FBmps[BNUMS]->Canvas->Lock();
            try
            {
                BitBlt(FBmps[BNUMS]->Canvas->Handle, 0, 0, FBWidth, FBHeight, FDC, l, t, SRCCOPY);
            }
            __finally
            {
                FBmps[BNUMS]->Canvas->Unlock();
            }
            if (CompareMem(FBmps[i]->ScanLine[FBHeight - 1], FBmps[BNUMS]->ScanLine[FBHeight - 1], FSize))
                FFocus[i] = Max(FFocus[i] - 1, 0);
            else
            {
                FBmps[i]->Canvas->Lock();
                try
                {
                    BitBlt(FBmps[i]->Canvas->Handle, 0, 0, FBWidth, FBHeight, FDC, l, t, SRCCOPY);
                }
                __finally
                {
                    FBmps[i]->Canvas->Unlock();
                }
                FFocus[i] = 5;
                SetRect(&rt, l, t, l +  FBWidth, t + FBHeight);
                FmsScr->WriteBuffer(&rt, sizeof(rt));
                FBmps[i]->SaveToStream(FmsScr);
                if ((i - BSIZE) >= 0) FFlag1[i - BSIZE] = true;
                if ((i + BSIZE) <= (BNUMS - 1)) FFlag1[i + BSIZE] = true;
                if ((i % BSIZE) != 0) FFlag1[i - 1] = true;
                if ((i % BSIZE) != (BSIZE - 1)) FFlag1[i + 1] = true;
                i = Max(Min(i - BSIZE, i - 1), 0);
                continue;
            }
        }
        i++;
    }
예제 #15
0
파일: dumpsb.c 프로젝트: alexpilotti/pesign
EFI_STATUS
show_signature_support(EFI_SYSTEM_TABLE *systab, UINTN showguid)
{
	EFI_STATUS rc = EFI_SUCCESS;
	char *data = NULL;
	UINTN data_size = 0;
	UINTN found = 0;
	EFI_GUID *guid;
	int i, j;

	struct {
		EFI_GUID *guid;
		CHAR16 *name;
		int required;
	} hashes[] = {
		{ &gEfiCertSha1Guid, L"SHA-1", 1 },
		{ &gEfiCertSha256Guid, L"SHA-256", 0 },
		{ &gEfiCertRsa2048Guid, L"RSA-2048", 0 },
		{ &gEfiCertRsa2048Sha1Guid, L"RSA-2048 + SHA-1", 0 },
		{ &gEfiCertRsa2048Sha256Guid, L"RSA-2048 + SHA-256", 0 },
		{ &gEfiCertX509Guid, L"X509", 1 },
		{ &gEfiCertPkcs7Guid, L"PKCS-7", 0 },
		{ NULL, L"" }
	};

	data = LibGetVariableAndSize(L"SignatureSupport", &EfiGlobalVariable,
				&data_size);
	guid = (EFI_GUID *)data;
	Print(L"Supported hashes:\n");
	for (i = 0; i < data_size / sizeof(*guid); i++, guid++) {
		found = 0;
		for (j = 0; hashes[j].guid != NULL; j++) {
			if (!CompareMem(hashes[j].guid, guid, sizeof(*guid))) {
 				if (showguid)
					Print(L"        %s (%g)\n", hashes[j].name, guid);
				else
					Print(L"        %s\n", hashes[j].name);
				hashes[j].required = 0;
				found = 1;
				continue;
			}
		}
		if (!found) {
			Print(L"        Unknown hash (%g)\n", guid);
		}
	}

	for (j = 0; hashes[j].guid != NULL; j++) {
		if (hashes[j].required) {
			Print(L"ERROR: Did not find required hash \"%s\"\n",
				hashes[j].name);
			rc = EFI_NOT_FOUND;
		}
	}

	FreePool(data);
	return rc;
}
예제 #16
0
파일: MemLibGuid.c 프로젝트: B-Rich/edk2
/**
  Compares two GUIDs.

  This function compares Guid1 to Guid2.  If the GUIDs are identical then TRUE is returned.
  If there are any bit differences in the two GUIDs, then FALSE is returned.
  
  If Guid1 is NULL, then ASSERT().
  If Guid2 is NULL, then ASSERT().

  @param  Guid1       A pointer to a 128 bit GUID.
  @param  Guid2       A pointer to a 128 bit GUID.

  @retval TRUE        Guid1 and Guid2 are identical.
  @retval FALSE       Guid1 and Guid2 are not identical.

**/
BOOLEAN
EFIAPI
CompareGuid (
  IN CONST GUID  *Guid1,
  IN CONST GUID  *Guid2
  )
{
  return (CompareMem(Guid1, Guid2, sizeof(GUID) == 0)) ? TRUE : FALSE;
}
예제 #17
0
/**
  Check whether the DevicePath2 is identical with DevicePath1, or identical with
  DevicePath1's child device path.

  If DevicePath2 is identical with DevicePath1, or with DevicePath1's child device
  path, then TRUE returned. Otherwise, FALSE is returned.
  
  If DevicePath1 is NULL, then ASSERT().
  If DevicePath2 is NULL, then ASSERT().

  @param[in]  DevicePath1   A pointer to a device path.
  @param[in]  DevicePath2   A pointer to a device path.

  @retval     TRUE          Two device paths are identical , or DevicePath2 is 
                            DevicePath1's child device path.
  @retval     FALSE         Two device paths are not identical, and DevicePath2 
                            is not DevicePath1's child device path.

**/
BOOLEAN
CheckDevicePath (
  IN  CONST EFI_DEVICE_PATH_PROTOCOL          *DevicePath1,
  IN  CONST EFI_DEVICE_PATH_PROTOCOL          *DevicePath2
  )
{
  EFI_STATUS                            Status;
  EFI_STRING                            DevicePathStr1;
  EFI_STRING                            DevicePathStr2;
  UINTN                                 StrLen1;
  UINTN                                 StrLen2;
  EFI_DEVICE_PATH_TO_TEXT_PROTOCOL      *DevicePathText;
  BOOLEAN                               DevicePathEqual;

  ASSERT (DevicePath1 != NULL);
  ASSERT (DevicePath2 != NULL);
  
  DevicePathEqual = FALSE;
  DevicePathText  = NULL;
  Status = gBS->LocateProtocol ( 
                  &gEfiDevicePathToTextProtocolGuid,
                  NULL,
                  (VOID **) &DevicePathText
                  );
  ASSERT (Status == EFI_SUCCESS);
  
  //
  // Get first device path string.
  //
  DevicePathStr1 = DevicePathText->ConvertDevicePathToText (DevicePath1, TRUE, TRUE);
  ConvertDPStr (DevicePathStr1);
  //
  // Get second device path string.
  //
  DevicePathStr2 = DevicePathText->ConvertDevicePathToText (DevicePath2, TRUE, TRUE);
  ConvertDPStr (DevicePathStr2);
  
  //
  // Compare device path string.
  //
  StrLen1 = StrSize (DevicePathStr1);
  StrLen2 = StrSize (DevicePathStr2);
  if (StrLen1 > StrLen2) {
    DevicePathEqual = FALSE;
    goto Done;
  }
  
  if (CompareMem (DevicePathStr1, DevicePathStr2, StrLen1) == 0) {
    DevicePathEqual = TRUE;
  }

Done:
  FreePool (DevicePathStr1);
  FreePool (DevicePathStr2);
  return DevicePathEqual;
}
예제 #18
0
/**
  This routine is used to get the current station and broadcast MAC addresses, and to change the
  current station MAC address.

  @param  CdbPtr               Pointer to the command descriptor block.
  @param  AdapterInfo          Pointer to the NIC data structure information which
                               the UNDI driver is layering on..

  @return None

**/
VOID
UNDI_StnAddr (
  IN  PXE_CDB           *CdbPtr,
  IN  NIC_DATA_INSTANCE *AdapterInfo
  )
{
  PXE_CPB_STATION_ADDRESS *CpbPtr;
  PXE_DB_STATION_ADDRESS  *DbPtr;
  UINT16                  Index;

  if (CdbPtr->OpFlags == PXE_OPFLAGS_STATION_ADDRESS_RESET) {
    //
    // configure the permanent address.
    // change the AdapterInfo->CurrentNodeAddress field.
    //
    if (CompareMem (
          &AdapterInfo->CurrentNodeAddress[0],
          &AdapterInfo->PermNodeAddress[0],
          PXE_MAC_LENGTH
          ) != 0) {
      for (Index = 0; Index < PXE_MAC_LENGTH; Index++) {
        AdapterInfo->CurrentNodeAddress[Index] = AdapterInfo->PermNodeAddress[Index];
      }

      E100bSetupIAAddr (AdapterInfo);
    }
  }

  if (CdbPtr->CPBaddr != (UINT64) 0) {
    CpbPtr = (PXE_CPB_STATION_ADDRESS *) (UINTN) (CdbPtr->CPBaddr);
    //
    // configure the new address
    //
    for (Index = 0; Index < PXE_MAC_LENGTH; Index++) {
      AdapterInfo->CurrentNodeAddress[Index] = CpbPtr->StationAddr[Index];
    }

    E100bSetupIAAddr (AdapterInfo);
  }

  if (CdbPtr->DBaddr != (UINT64) 0) {
    DbPtr = (PXE_DB_STATION_ADDRESS *) (UINTN) (CdbPtr->DBaddr);
    //
    // fill it with the new values
    //
    for (Index = 0; Index < PXE_MAC_LENGTH; Index++) {
      DbPtr->StationAddr[Index]   = AdapterInfo->CurrentNodeAddress[Index];
      DbPtr->BroadcastAddr[Index] = AdapterInfo->BroadcastNodeAddress[Index];
      DbPtr->PermanentAddr[Index] = AdapterInfo->PermNodeAddress[Index];
    }
  }

  return ;
}
예제 #19
0
파일: AddBGRT.c 프로젝트: MattDevo/edk2
static ACPI_BGRT* HandleAcpiTables(ACPI_BGRT* bgrt) {
  int i;

  for (i = 0; i < gST->NumberOfTableEntries; i++) {
    EFI_GUID* vendor_guid = &gST->ConfigurationTable[i].VendorGuid;
    ACPI_20_RSDP *rsdp;
    ACPI_SDT_HEADER *xsdt;
    UINT64 *entry_arr;
    UINT32 entry_arr_length;

    if (!CompareGuid(vendor_guid, &gEfiAcpiTableGuid) && !CompareGuid(vendor_guid, &gEfiAcpi20TableGuid)) {
      continue;
    }
    rsdp = (ACPI_20_RSDP *) gST->ConfigurationTable[i].VendorTable;
    if (CompareMem(rsdp->signature, "RSD PTR ", 8) != 0 || rsdp->revision < 2 || !VerifyAcpiRsdp2Checksums(rsdp)) {
      continue;
    }
    DEBUG ((EFI_D_INFO, "RSDP: revision = %d, OEM ID = %s\n", rsdp->revision, TmpStr(rsdp->oem_id, 6)));

    xsdt = (ACPI_SDT_HEADER *) (UINTN) rsdp->xsdt_address;
    if (!xsdt || CompareMem(xsdt->signature, "XSDT", 4) != 0 || !VerifyAcpiSdtChecksum(xsdt)) {
      DEBUG ((EFI_D_INFO, "* XSDT: missing or invalid\n"));
      continue;
    }
    entry_arr = (UINT64*)&xsdt[1];
    entry_arr_length = (xsdt->length - sizeof(*xsdt)) / sizeof(UINT64);

    DEBUG ((EFI_D_INFO, "* XSDT: OEM ID = %s, entry count = %d\n", TmpStr(xsdt->oem_id, 6), entry_arr_length));

    if (bgrt) {
      DEBUG ((EFI_D_INFO, " - Adding missing BGRT.\n"));
      xsdt = CreateXsdt(xsdt, entry_arr_length + 1);
      entry_arr = (UINT64*)&xsdt[1];
      entry_arr[entry_arr_length++] = (UINTN) bgrt;
      rsdp->xsdt_address = (UINTN) xsdt;
      SetAcpiRsdp2Checksums(rsdp);
    }
    SetAcpiSdtChecksum(xsdt);
  }
  return bgrt;
}
예제 #20
0
파일: RdRand.c 프로젝트: B-Rich/edk2
/**
  Determines whether or not RDRAND instruction is supported by the host hardware.

  @retval EFI_SUCCESS          RDRAND instruction supported.
  @retval EFI_UNSUPPORTED      RDRAND instruction not supported.

**/
EFI_STATUS
EFIAPI
IsRdRandSupported (
  VOID
  )
{
  EFI_STATUS  Status;
  UINT32      RegEax;
  UINT32      RegEbx;
  UINT32      RegEcx;
  UINT32      RegEdx;
  BOOLEAN     IsIntelCpu;

  Status     = EFI_UNSUPPORTED;
  IsIntelCpu = FALSE;
  
  //
  // Checks whether the current processor is an Intel product by CPUID.
  //
  AsmCpuid (0, &RegEax, &RegEbx, &RegEcx, &RegEdx);
  if ((CompareMem ((CHAR8 *)(&RegEbx), "Genu", 4) == 0) &&
      (CompareMem ((CHAR8 *)(&RegEdx), "ineI", 4) == 0) &&
      (CompareMem ((CHAR8 *)(&RegEcx), "ntel", 4) == 0)) {
    IsIntelCpu = TRUE;
  }

  if (IsIntelCpu) {
    //
    // Determine RDRAND support by examining bit 30 of the ECX register returned by CPUID.
    // A value of 1 indicates that processor supports RDRAND instruction.
    //
    AsmCpuid (1, 0, 0, &RegEcx, 0);

    if ((RegEcx & RDRAND_MASK) == RDRAND_MASK) {
      Status = EFI_SUCCESS;
    }
  }

  return Status;
}
예제 #21
0
/**
  Return the index of the load option in the load option array.

  The function consider two load options are equal when the 
  OptionType, Attributes, Description, FilePath and OptionalData are equal.

  @param Key    Pointer to the load option to be found.
  @param Array  Pointer to the array of load options to be found.
  @param Count  Number of entries in the Array.

  @retval -1          Key wasn't found in the Array.
  @retval 0 ~ Count-1 The index of the Key in the Array.
**/
INTN
PlatformFindLoadOption (
  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
  IN UINTN                              Count
  )
{
  UINTN                             Index;

  for (Index = 0; Index < Count; Index++) {
    if ((Key->OptionType == Array[Index].OptionType) &&
        (Key->Attributes == Array[Index].Attributes) &&
        (StrCmp (Key->Description, Array[Index].Description) == 0) &&
        (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&
        (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&
        (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {
      return (INTN) Index;
    }
  }

  return -1;
}
예제 #22
0
파일: showpart.c 프로젝트: JrCs/gptsync
static INTN FindMem(VOID *Buffer, UINTN BufferLength, VOID *SearchString, UINTN SearchStringLength)
{
    UINT8 *BufferPtr;
    UINTN Offset;
    
    BufferPtr = Buffer;
    BufferLength -= SearchStringLength;
    for (Offset = 0; Offset < BufferLength; Offset++, BufferPtr++) {
        if (CompareMem(BufferPtr, SearchString, SearchStringLength) == 0)
            return (INTN)Offset;
    }
    
    return -1;
}
/**
  Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
  Pe/Coff image based on the authenticode image hashing in PE/COFF Specification
  8.0 Appendix A

  Caution: This function may receive untrusted input.
  PE/COFF image is external input, so this function will validate its data structure
  within this image buffer before use.

  @param[in]  AuthData            Pointer to the Authenticode Signature retrieved from signed image.
  @param[in]  AuthDataSize        Size of the Authenticode Signature in bytes.
  
  @retval EFI_UNSUPPORTED             Hash algorithm is not supported.
  @retval EFI_SUCCESS                 Hash successfully.

**/
EFI_STATUS
HashPeImageByType (
  IN UINT8              *AuthData,
  IN UINTN              AuthDataSize
  )
{
  UINT8                     Index;

  for (Index = 0; Index < HASHALG_MAX; Index++) {
    //
    // Check the Hash algorithm in PE/COFF Authenticode.
    //    According to PKCS#7 Definition:
    //        SignedData ::= SEQUENCE {
    //            version Version,
    //            digestAlgorithms DigestAlgorithmIdentifiers,
    //            contentInfo ContentInfo,
    //            .... }
    //    The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
    //    This field has the fixed offset (+32) in final Authenticode ASN.1 data.
    //    Fixed offset (+32) is calculated based on two bytes of length encoding.
    //
    if ((*(AuthData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
      //
      // Only support two bytes of Long Form of Length Encoding.
      //
      continue;
    }

    if (AuthDataSize < 32 + mHash[Index].OidLength) {
      return EFI_UNSUPPORTED;
    }

    if (CompareMem (AuthData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {
      break;
    }
  }

  if (Index == HASHALG_MAX) {
    return EFI_UNSUPPORTED;
  }

  //
  // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
  //
  if (!HashPeImage(Index)) {
    return EFI_UNSUPPORTED;
  }

  return EFI_SUCCESS;
}
예제 #24
0
/**
  Process (load and execute) the load option.

  @param LoadOption  Pointer to the load option.

  @retval EFI_INVALID_PARAMETER  The load option type is invalid, 
                                 or the load option file path doesn't point to a valid file.
  @retval EFI_UNSUPPORTED        The load option type is of LoadOptionTypeBoot.
  @retval EFI_SUCCESS            The load option is inactive, or successfully loaded and executed.
**/
EFI_STATUS
EFIAPI
EfiBootManagerProcessLoadOption (
  IN EFI_BOOT_MANAGER_LOAD_OPTION       *LoadOption
  )
{
  EFI_STATUS                        Status;
  EFI_DEVICE_PATH_PROTOCOL          *FilePath;
  EFI_HANDLE                        ImageHandle;
  EFI_LOADED_IMAGE_PROTOCOL         *ImageInfo;
  VOID                              *FileBuffer;
  UINTN                             FileSize;

  if ((UINT32) LoadOption->OptionType >= LoadOptionTypeMax) {
    return EFI_INVALID_PARAMETER;
  }

  if (LoadOption->OptionType == LoadOptionTypeBoot) {
    return EFI_UNSUPPORTED;
  }

  //
  // If a load option is not marked as LOAD_OPTION_ACTIVE,
  // the boot manager will not automatically load the option.
  //
  if ((LoadOption->Attributes & LOAD_OPTION_ACTIVE) == 0) {
    return EFI_SUCCESS;
  }

  Status = EFI_INVALID_PARAMETER;

  //
  // Load and start the load option.
  //
  DEBUG ((
    DEBUG_INFO | DEBUG_LOAD, "Process Load Option (%s%04x) ...\n",
    mBmLoadOptionName[LoadOption->OptionType], LoadOption->OptionNumber
    ));
  ImageHandle = NULL;
  FileBuffer = BmGetLoadOptionBuffer (LoadOption->FilePath, &FilePath, &FileSize);
  DEBUG_CODE (
    if (FileBuffer != NULL && CompareMem (LoadOption->FilePath, FilePath, GetDevicePathSize (FilePath)) != 0) {
      DEBUG ((EFI_D_INFO, "[Bds] DevicePath expand: "));
      BmPrintDp (LoadOption->FilePath);
      DEBUG ((EFI_D_INFO, " -> "));
      BmPrintDp (FilePath);
      DEBUG ((EFI_D_INFO, "\n"));
    }
  );
예제 #25
0
/**
  Read EDID information from I2C Bus on CirrusLogic.

  @param  Private             Pointer to VBOX_VGA_PRIVATE_DATA.
  @param  EdidDataBlock       Pointer to EDID data block.
  @param  EdidSize            Returned EDID block size.

  @retval EFI_UNSUPPORTED
  @retval EFI_SUCCESS

**/
EFI_STATUS
ReadEdidData (
  VBOX_VGA_PRIVATE_DATA     *Private,
  UINT8                              **EdidDataBlock,
  UINTN                              *EdidSize
  )
{
  UINTN             Index;
  UINT8             EdidData[EDID_BLOCK_SIZE * 2];
  UINT8             *ValidEdid;
  UINT64            Signature;

  for (Index = 0; Index < EDID_BLOCK_SIZE * 2; Index ++) {
    I2cReadByte (Private->PciIo, 0xa0, (UINT8)Index, &EdidData[Index]);
  }

  //
  // Search for the EDID signature
  //
  ValidEdid = &EdidData[0];
  Signature = 0x00ffffffffffff00ull;
  for (Index = 0; Index < EDID_BLOCK_SIZE * 2; Index ++, ValidEdid ++) {
    if (CompareMem (ValidEdid, &Signature, 8) == 0) {
      break;
    }
  }

  if (Index == 256) {
    //
    // No EDID signature found
    //
    return EFI_UNSUPPORTED;
  }

  *EdidDataBlock = AllocateCopyPool (
                     sizeof (EDID_BLOCK_SIZE),
                     ValidEdid
                     );
  if (*EdidDataBlock == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  //
  // Currently only support EDID 1.x
  //
  *EdidSize = EDID_BLOCK_SIZE;

  return EFI_SUCCESS;
}
예제 #26
0
/**
  Check the integrity of firmware volume header

  @param[in]  FwVolHeader   A pointer to a firmware volume header

  @retval     TRUE          The firmware volume is consistent
  @retval     FALSE         The firmware volume has corrupted.

**/
STATIC
BOOLEAN
IsFvHeaderValid (
  IN       EFI_PHYSICAL_ADDRESS          FvBase,
  IN CONST EFI_FIRMWARE_VOLUME_HEADER    *FwVolHeader
  )
{
  UINT16 Checksum;

  if (FvBase == PcdGet32(PcdFlashNvStorageVariableBase)) {
    if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid, sizeof(EFI_GUID)) != 0 ) {
      return FALSE;
    }
  } else {
    if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid, sizeof(EFI_GUID)) != 0 ) {
      return FALSE;
    }
  }
  if ((FwVolHeader->Revision != EFI_FVH_REVISION)   ||
       (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
       (FwVolHeader->FvLength == ((UINTN) -1))       ||
       ((FwVolHeader->HeaderLength & 0x01 ) !=0)) {
    return FALSE;
  }

  Checksum = CalculateCheckSum16 ((UINT16 *) FwVolHeader, FwVolHeader->HeaderLength);
  if (Checksum != 0) {
    DEBUG (( DEBUG_ERROR,
              "ERROR - Invalid Firmware Volume Header Checksum, change 0x%04x to 0x%04x\r\n",
              FwVolHeader->Checksum,
              (UINT16)( Checksum + FwVolHeader->Checksum )));
    return FALSE;
  }

  return TRUE;
}
예제 #27
0
/**
  Check to see if it is a valid work space.


  @param WorkingHeader   Pointer of working block header

  @retval TRUE          The work space is valid.
  @retval FALSE         The work space is invalid.

**/
BOOLEAN
IsValidWorkSpace (
  IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
  )
{
  if (WorkingHeader == NULL) {
    return FALSE;
  }

  if (CompareMem (WorkingHeader, &mWorkingBlockHeader, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)) == 0) {
    return TRUE;
  }

  DEBUG ((EFI_D_INFO, "Ftw: Work block header check mismatch\n"));
  return FALSE;
}
예제 #28
0
EFI_STATUS
find_in_esl(UINT8 *Data, UINTN DataSize, UINT8 *key, UINTN keylen)
{
	EFI_SIGNATURE_LIST *CertList;

	certlist_for_each_certentry(CertList, Data, DataSize, DataSize) {
		if (CertList->SignatureSize != keylen + sizeof(EFI_GUID))
			continue;
		EFI_SIGNATURE_DATA *Cert;

		certentry_for_each_cert(Cert, CertList)
			if (CompareMem (Cert->SignatureData, key, keylen) == 0)
				return EFI_SUCCESS;
	}
	return EFI_NOT_FOUND;
}
예제 #29
0
/**
  Validate whether the options received in the server's OACK packet is valid.
  The options are valid only if:
  1. The server doesn't include options not requested by us.
  2. The server can only use smaller blksize than that is requested.
  3. The server can only use the same timeout as requested.
  4. The server doesn't change its multicast channel.

  @param[in]  Instance              The pointer to the Mtftp6 instance.
  @param[in]  ReplyInfo             The pointer to options information in reply packet.
  @param[in]  RequestInfo           The pointer to requested options info.

  @retval     TRUE                  If the option in the OACK is valid.
  @retval     FALSE                 If the option is invalid.

**/
BOOLEAN
Mtftp6RrqOackValid (
  IN MTFTP6_INSTANCE           *Instance,
  IN MTFTP6_EXT_OPTION_INFO    *ReplyInfo,
  IN MTFTP6_EXT_OPTION_INFO    *RequestInfo
  )
{
  //
  // It is invalid for server to return options we don't request
  //
  if ((ReplyInfo->BitMap & ~RequestInfo->BitMap) != 0) {
    return FALSE;
  }

  //
  // Server can only specify a smaller block size to be used and
  // return the timeout matches that requested.
  //
  if ((((ReplyInfo->BitMap & MTFTP6_OPT_BLKSIZE_BIT) != 0) && (ReplyInfo->BlkSize > RequestInfo->BlkSize)) ||
      (((ReplyInfo->BitMap & MTFTP6_OPT_TIMEOUT_BIT) != 0) && (ReplyInfo->Timeout != RequestInfo->Timeout))
      ) {
    return FALSE;
  }

  //
  // The server can send ",,master" to client to change its master
  // setting. But if it use the specific multicast channel, it can't
  // change the setting.
  //
  if (((ReplyInfo->BitMap & MTFTP6_OPT_MCAST_BIT) != 0) && !NetIp6IsUnspecifiedAddr (&Instance->McastIp)) {

    if (!NetIp6IsUnspecifiedAddr (&ReplyInfo->McastIp) && CompareMem (
                                                            &ReplyInfo->McastIp,
                                                            &Instance->McastIp,
                                                            sizeof (EFI_IPv6_ADDRESS)
                                                            ) != 0) {
      return FALSE;
    }

    if ((ReplyInfo->McastPort != 0) && (ReplyInfo->McastPort != Instance->McastPort)) {
      return FALSE;
    }
  }

  return TRUE;
}
예제 #30
0
파일: BdsMisc.c 프로젝트: jief666/clover
EFIAPI
BdsLibDelPartMatchInstance (
  IN     EFI_DEVICE_PATH_PROTOCOL  *Multi,
  IN     EFI_DEVICE_PATH_PROTOCOL  *Single
  )
{
  EFI_DEVICE_PATH_PROTOCOL  *Instance;
  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
  EFI_DEVICE_PATH_PROTOCOL  *TempNewDevicePath;
  UINTN                     InstanceSize;
  UINTN                     SingleDpSize;
  UINTN                     Size;

  NewDevicePath     = NULL;
  TempNewDevicePath = NULL;

  if (Multi == NULL || Single == NULL) {
    return Multi;
  }

  Instance        =  GetNextDevicePathInstance (&Multi, &InstanceSize);
  SingleDpSize    =  GetDevicePathSize (Single) - END_DEVICE_PATH_LENGTH;
  InstanceSize    -= END_DEVICE_PATH_LENGTH;

  while (Instance != NULL) {

    Size = (SingleDpSize < InstanceSize) ? SingleDpSize : InstanceSize;

    if ((CompareMem (Instance, Single, Size) != 0)) {
      //
      // Append the device path instance which does not match with Single
      //
      TempNewDevicePath = NewDevicePath;
      NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance);
      if (TempNewDevicePath != NULL) {
        FreePool(TempNewDevicePath);
      }
    }
    FreePool(Instance);
    Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);
    InstanceSize  -= END_DEVICE_PATH_LENGTH;
  }

  return NewDevicePath;
}