]>
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 | |
7 | This program and the accompanying materials are licensed and made available\r | |
8 | under the terms and conditions of the BSD License which accompanies this\r | |
9 | distribution. The full text of the license may be found at\r | |
10 | http://opensource.org/licenses/bsd-license.php.\r | |
11 | \r | |
12 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r | |
13 | WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
14 | **/\r | |
15 | \r | |
16 | #include "BaseLibInternals.h"\r | |
17 | \r | |
18 | /**\r | |
19 | Patch the immediate operand of an IA32 or X64 instruction such that the byte,\r | |
20 | word, dword or qword operand is encoded at the end of the instruction's\r | |
21 | binary representation.\r | |
22 | \r | |
23 | This function should be used to update object code that was compiled with\r | |
24 | NASM from assembly source code. Example:\r | |
25 | \r | |
26 | NASM source code:\r | |
27 | \r | |
28 | mov eax, strict dword 0 ; the imm32 zero operand will be patched\r | |
29 | ASM_PFX(gPatchCr3):\r | |
30 | mov cr3, eax\r | |
31 | \r | |
32 | C source code:\r | |
33 | \r | |
34 | X86_ASSEMBLY_PATCH_LABEL gPatchCr3;\r | |
35 | PatchInstructionX86 (gPatchCr3, AsmReadCr3 (), 4);\r | |
36 | \r | |
37 | @param[out] InstructionEnd Pointer right past the instruction to patch. The\r | |
38 | immediate operand to patch is expected to\r | |
39 | comprise the trailing bytes of the instruction.\r | |
40 | If InstructionEnd is closer to address 0 than\r | |
41 | ValueSize permits, then ASSERT().\r | |
42 | \r | |
43 | @param[in] PatchValue The constant to write to the immediate operand.\r | |
44 | The caller is responsible for ensuring that\r | |
45 | PatchValue can be represented in the byte, word,\r | |
46 | dword or qword operand (as indicated through\r | |
47 | ValueSize); otherwise ASSERT().\r | |
48 | \r | |
49 | @param[in] ValueSize The size of the operand in bytes; must be 1, 2,\r | |
50 | 4, or 8. ASSERT() otherwise.\r | |
51 | **/\r | |
52 | VOID\r | |
53 | EFIAPI\r | |
54 | PatchInstructionX86 (\r | |
55 | OUT X86_ASSEMBLY_PATCH_LABEL *InstructionEnd,\r | |
56 | IN UINT64 PatchValue,\r | |
57 | IN UINTN ValueSize\r | |
58 | )\r | |
59 | {\r | |
60 | //\r | |
61 | // The equality ((UINTN)InstructionEnd == ValueSize) would assume a zero-size\r | |
62 | // instruction at address 0; forbid it.\r | |
63 | //\r | |
64 | ASSERT ((UINTN)InstructionEnd > ValueSize);\r | |
65 | \r | |
66 | switch (ValueSize) {\r | |
67 | case 1:\r | |
68 | ASSERT (PatchValue <= MAX_UINT8);\r | |
69 | *((UINT8 *)(UINTN)InstructionEnd - 1) = (UINT8)PatchValue;\r | |
70 | break;\r | |
71 | \r | |
72 | case 2:\r | |
73 | ASSERT (PatchValue <= MAX_UINT16);\r | |
74 | WriteUnaligned16 ((UINT16 *)(UINTN)InstructionEnd - 1, (UINT16)PatchValue);\r | |
75 | break;\r | |
76 | \r | |
77 | case 4:\r | |
78 | ASSERT (PatchValue <= MAX_UINT32);\r | |
79 | WriteUnaligned32 ((UINT32 *)(UINTN)InstructionEnd - 1, (UINT32)PatchValue);\r | |
80 | break;\r | |
81 | \r | |
82 | case 8:\r | |
83 | WriteUnaligned64 ((UINT64 *)(UINTN)InstructionEnd - 1, PatchValue);\r | |
84 | break;\r | |
85 | \r | |
86 | default:\r | |
87 | ASSERT (FALSE);\r | |
88 | }\r | |
89 | }\r |