audk/MdePkg/Library/BaseLib/X86PatchInstruction.c
Michael D Kinney 9344f09215 MdePkg: Replace BSD License with BSD+Patent License
https://bugzilla.tianocore.org/show_bug.cgi?id=1373

Replace BSD 2-Clause License with BSD+Patent License.  This change is
based on the following emails:

  https://lists.01.org/pipermail/edk2-devel/2019-February/036260.html
  https://lists.01.org/pipermail/edk2-devel/2018-October/030385.html

RFCs with detailed process for the license change:

  V3: https://lists.01.org/pipermail/edk2-devel/2019-March/038116.html
  V2: https://lists.01.org/pipermail/edk2-devel/2019-March/037669.html
  V1: https://lists.01.org/pipermail/edk2-devel/2019-March/037500.html

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
2019-04-09 10:58:13 -07:00

84 lines
2.6 KiB
C

/** @file
IA-32/x64 PatchInstructionX86()
Copyright (C) 2018, Intel Corporation. All rights reserved.<BR>
Copyright (C) 2018, Red Hat, Inc.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "BaseLibInternals.h"
/**
Patch the immediate operand of an IA32 or X64 instruction such that the byte,
word, dword or qword operand is encoded at the end of the instruction's
binary representation.
This function should be used to update object code that was compiled with
NASM from assembly source code. Example:
NASM source code:
mov eax, strict dword 0 ; the imm32 zero operand will be patched
ASM_PFX(gPatchCr3):
mov cr3, eax
C source code:
X86_ASSEMBLY_PATCH_LABEL gPatchCr3;
PatchInstructionX86 (gPatchCr3, AsmReadCr3 (), 4);
@param[out] InstructionEnd Pointer right past the instruction to patch. The
immediate operand to patch is expected to
comprise the trailing bytes of the instruction.
If InstructionEnd is closer to address 0 than
ValueSize permits, then ASSERT().
@param[in] PatchValue The constant to write to the immediate operand.
The caller is responsible for ensuring that
PatchValue can be represented in the byte, word,
dword or qword operand (as indicated through
ValueSize); otherwise ASSERT().
@param[in] ValueSize The size of the operand in bytes; must be 1, 2,
4, or 8. ASSERT() otherwise.
**/
VOID
EFIAPI
PatchInstructionX86 (
OUT X86_ASSEMBLY_PATCH_LABEL *InstructionEnd,
IN UINT64 PatchValue,
IN UINTN ValueSize
)
{
//
// The equality ((UINTN)InstructionEnd == ValueSize) would assume a zero-size
// instruction at address 0; forbid it.
//
ASSERT ((UINTN)InstructionEnd > ValueSize);
switch (ValueSize) {
case 1:
ASSERT (PatchValue <= MAX_UINT8);
*((UINT8 *)(UINTN)InstructionEnd - 1) = (UINT8)PatchValue;
break;
case 2:
ASSERT (PatchValue <= MAX_UINT16);
WriteUnaligned16 ((UINT16 *)(UINTN)InstructionEnd - 1, (UINT16)PatchValue);
break;
case 4:
ASSERT (PatchValue <= MAX_UINT32);
WriteUnaligned32 ((UINT32 *)(UINTN)InstructionEnd - 1, (UINT32)PatchValue);
break;
case 8:
WriteUnaligned64 ((UINT64 *)(UINTN)InstructionEnd - 1, PatchValue);
break;
default:
ASSERT (FALSE);
}
}