|
10 | 10 | from ..ProcessorBind import * |
11 | 11 | from ..UefiBaseType import * |
12 | 12 | from ..PiMultiPhase import * |
13 | | -from ..utils import write_int64, read_int64 |
| 13 | +from .. import utils |
14 | 14 |
|
15 | 15 | # @see: MdePkg\Include\Pi\PiMultiPhase.h |
16 | 16 | class EFI_MMRAM_DESCRIPTOR(STRUCT): |
@@ -108,8 +108,23 @@ def hook_GetCapabilities(ql: Qiling, address: int, params): |
108 | 108 | size = len(chunks) * EFI_SMRAM_DESCRIPTOR.sizeof() |
109 | 109 | MmramMapSize = params["MmramMapSize"] |
110 | 110 |
|
111 | | - if read_int64(ql, MmramMapSize) < size: |
112 | | - write_int64(ql, MmramMapSize, size) |
| 111 | + if utils.read_int64(ql, MmramMapSize) < size: |
| 112 | + # since the caller cannot predict how much memory would be required for storing |
| 113 | + # the memory map, this method is normally called twice. the first one passes a |
| 114 | + # zero size only to determine the expected size, then the caller allocates the |
| 115 | + # required amount of memory and call it again. |
| 116 | + # |
| 117 | + # our memory map is managed differently from the real one, and memory allocations |
| 118 | + # are likely to generate an additional "map block" (or two, if allocated somewhere |
| 119 | + # in the last free heap chunk). because the caller allocates a new memory chunk |
| 120 | + # between the two calls, that would cause the second call to always complain the |
| 121 | + # buffer is too small. |
| 122 | + # |
| 123 | + # to work around that, we have the first call return a larger number than it should |
| 124 | + # have, to compensate on the coming allocation. |
| 125 | + extra = 2 * EFI_SMRAM_DESCRIPTOR.sizeof() |
| 126 | + |
| 127 | + utils.write_int64(ql, MmramMapSize, size + extra) |
113 | 128 | return EFI_BUFFER_TOO_SMALL |
114 | 129 |
|
115 | 130 | MmramMap = params["MmramMap"] |
|
0 commit comments