+/** @file\r
+ IA-32/x64 PatchInstructionX86()\r
+\r
+ Copyright (C) 2018, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (C) 2018, Red Hat, Inc.\r
+\r
+ This program and the accompanying materials are licensed and made available\r
+ under the terms and conditions of the BSD License which accompanies this\r
+ distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#include "BaseLibInternals.h"\r
+\r
+/**\r
+ Patch the immediate operand of an IA32 or X64 instruction such that the byte,\r
+ word, dword or qword operand is encoded at the end of the instruction's\r
+ binary representation.\r
+\r
+ This function should be used to update object code that was compiled with\r
+ NASM from assembly source code. Example:\r
+\r
+ NASM source code:\r
+\r
+ mov eax, strict dword 0 ; the imm32 zero operand will be patched\r
+ ASM_PFX(gPatchCr3):\r
+ mov cr3, eax\r
+\r
+ C source code:\r
+\r
+ X86_ASSEMBLY_PATCH_LABEL gPatchCr3;\r
+ PatchInstructionX86 (gPatchCr3, AsmReadCr3 (), 4);\r
+\r
+ @param[out] InstructionEnd Pointer right past the instruction to patch. The\r
+ immediate operand to patch is expected to\r
+ comprise the trailing bytes of the instruction.\r
+ If InstructionEnd is closer to address 0 than\r
+ ValueSize permits, then ASSERT().\r
+\r
+ @param[in] PatchValue The constant to write to the immediate operand.\r
+ The caller is responsible for ensuring that\r
+ PatchValue can be represented in the byte, word,\r
+ dword or qword operand (as indicated through\r
+ ValueSize); otherwise ASSERT().\r
+\r
+ @param[in] ValueSize The size of the operand in bytes; must be 1, 2,\r
+ 4, or 8. ASSERT() otherwise.\r
+**/\r
+VOID\r
+EFIAPI\r
+PatchInstructionX86 (\r
+ OUT X86_ASSEMBLY_PATCH_LABEL *InstructionEnd,\r
+ IN UINT64 PatchValue,\r
+ IN UINTN ValueSize\r
+ )\r
+{\r
+ //\r
+ // The equality ((UINTN)InstructionEnd == ValueSize) would assume a zero-size\r
+ // instruction at address 0; forbid it.\r
+ //\r
+ ASSERT ((UINTN)InstructionEnd > ValueSize);\r
+\r
+ switch (ValueSize) {\r
+ case 1:\r
+ ASSERT (PatchValue <= MAX_UINT8);\r
+ *((UINT8 *)(UINTN)InstructionEnd - 1) = (UINT8)PatchValue;\r
+ break;\r
+\r
+ case 2:\r
+ ASSERT (PatchValue <= MAX_UINT16);\r
+ WriteUnaligned16 ((UINT16 *)(UINTN)InstructionEnd - 1, (UINT16)PatchValue);\r
+ break;\r
+\r
+ case 4:\r
+ ASSERT (PatchValue <= MAX_UINT32);\r
+ WriteUnaligned32 ((UINT32 *)(UINTN)InstructionEnd - 1, (UINT32)PatchValue);\r
+ break;\r
+\r
+ case 8:\r
+ WriteUnaligned64 ((UINT64 *)(UINTN)InstructionEnd - 1, PatchValue);\r
+ break;\r
+\r
+ default:\r
+ ASSERT (FALSE);\r
+ }\r
+}\r