]>
Commit | Line | Data |
---|---|---|
8596c140 LE |
1 | /** @file\r |
2 | IA-32/x64 PatchInstructionX86()\r | |
3 | \r | |
4 | Copyright (C) 2018, Intel Corporation. All rights reserved.<BR>\r | |
5 | Copyright (C) 2018, Red Hat, Inc.\r | |
6 | \r | |
9344f092 | 7 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
8596c140 LE |
8 | **/\r |
9 | \r | |
10 | #include "BaseLibInternals.h"\r | |
11 | \r | |
12 | /**\r | |
13 | Patch the immediate operand of an IA32 or X64 instruction such that the byte,\r | |
14 | word, dword or qword operand is encoded at the end of the instruction's\r | |
15 | binary representation.\r | |
16 | \r | |
17 | This function should be used to update object code that was compiled with\r | |
18 | NASM from assembly source code. Example:\r | |
19 | \r | |
20 | NASM source code:\r | |
21 | \r | |
22 | mov eax, strict dword 0 ; the imm32 zero operand will be patched\r | |
23 | ASM_PFX(gPatchCr3):\r | |
24 | mov cr3, eax\r | |
25 | \r | |
26 | C source code:\r | |
27 | \r | |
28 | X86_ASSEMBLY_PATCH_LABEL gPatchCr3;\r | |
29 | PatchInstructionX86 (gPatchCr3, AsmReadCr3 (), 4);\r | |
30 | \r | |
31 | @param[out] InstructionEnd Pointer right past the instruction to patch. The\r | |
32 | immediate operand to patch is expected to\r | |
33 | comprise the trailing bytes of the instruction.\r | |
34 | If InstructionEnd is closer to address 0 than\r | |
35 | ValueSize permits, then ASSERT().\r | |
36 | \r | |
37 | @param[in] PatchValue The constant to write to the immediate operand.\r | |
38 | The caller is responsible for ensuring that\r | |
39 | PatchValue can be represented in the byte, word,\r | |
40 | dword or qword operand (as indicated through\r | |
41 | ValueSize); otherwise ASSERT().\r | |
42 | \r | |
43 | @param[in] ValueSize The size of the operand in bytes; must be 1, 2,\r | |
44 | 4, or 8. ASSERT() otherwise.\r | |
45 | **/\r | |
46 | VOID\r | |
47 | EFIAPI\r | |
48 | PatchInstructionX86 (\r | |
49 | OUT X86_ASSEMBLY_PATCH_LABEL *InstructionEnd,\r | |
50 | IN UINT64 PatchValue,\r | |
51 | IN UINTN ValueSize\r | |
52 | )\r | |
53 | {\r | |
54 | //\r | |
55 | // The equality ((UINTN)InstructionEnd == ValueSize) would assume a zero-size\r | |
56 | // instruction at address 0; forbid it.\r | |
57 | //\r | |
58 | ASSERT ((UINTN)InstructionEnd > ValueSize);\r | |
59 | \r | |
60 | switch (ValueSize) {\r | |
61 | case 1:\r | |
62 | ASSERT (PatchValue <= MAX_UINT8);\r | |
63 | *((UINT8 *)(UINTN)InstructionEnd - 1) = (UINT8)PatchValue;\r | |
64 | break;\r | |
65 | \r | |
66 | case 2:\r | |
67 | ASSERT (PatchValue <= MAX_UINT16);\r | |
68 | WriteUnaligned16 ((UINT16 *)(UINTN)InstructionEnd - 1, (UINT16)PatchValue);\r | |
69 | break;\r | |
70 | \r | |
71 | case 4:\r | |
72 | ASSERT (PatchValue <= MAX_UINT32);\r | |
73 | WriteUnaligned32 ((UINT32 *)(UINTN)InstructionEnd - 1, (UINT32)PatchValue);\r | |
74 | break;\r | |
75 | \r | |
76 | case 8:\r | |
77 | WriteUnaligned64 ((UINT64 *)(UINTN)InstructionEnd - 1, PatchValue);\r | |
78 | break;\r | |
79 | \r | |
80 | default:\r | |
81 | ASSERT (FALSE);\r | |
82 | }\r | |
83 | }\r |