Angel Pons | 8a3453f | 2020-04-02 23:48:19 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Damien Roth | bedbd67 | 2016-01-18 13:59:26 -0700 | [diff] [blame] | 2 | |
Arthur Heymans | e6a60fd | 2022-05-16 09:28:18 +0200 | [diff] [blame] | 3 | #pragma pack(push) |
Elyes HAOUAS | 19f5ba8 | 2018-10-14 14:52:06 +0200 | [diff] [blame] | 4 | #include <AGESA.h> |
Arthur Heymans | e6a60fd | 2022-05-16 09:28:18 +0200 | [diff] [blame] | 5 | #pragma pack(pop) |
| 6 | |
Elyes HAOUAS | 19f5ba8 | 2018-10-14 14:52:06 +0200 | [diff] [blame] | 7 | #include <amdlib.h> |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 8 | |
| 9 | #include <cbmem.h> |
Kyösti Mälkki | da74041 | 2017-03-05 18:57:03 +0200 | [diff] [blame] | 10 | #include <northbridge/amd/agesa/agesa_helper.h> |
Kyösti Mälkki | f728408 | 2015-05-26 10:12:45 +0300 | [diff] [blame] | 11 | #include <northbridge/amd/agesa/BiosCallOuts.h> |
| 12 | |
Furquan Shaikh | 76cedd2 | 2020-05-02 10:24:23 -0700 | [diff] [blame] | 13 | #include <acpi/acpi.h> |
Elyes HAOUAS | 20eaef0 | 2019-03-29 17:45:28 +0100 | [diff] [blame] | 14 | #include <console/console.h> |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 15 | #include <string.h> |
| 16 | |
Kyösti Mälkki | b1fcbf3 | 2015-05-26 11:25:13 +0300 | [diff] [blame] | 17 | /* BIOS_HEAP_START_ADDRESS is only for cold boots. */ |
| 18 | #define BIOS_HEAP_SIZE 0x30000 |
| 19 | #define BIOS_HEAP_START_ADDRESS 0x010000000 |
| 20 | |
Julius Werner | cd49cce | 2019-03-05 16:53:33 -0800 | [diff] [blame] | 21 | #if CONFIG(HAVE_ACPI_RESUME) && (HIGH_MEMORY_SCRATCH < BIOS_HEAP_SIZE) |
Kyösti Mälkki | f728408 | 2015-05-26 10:12:45 +0300 | [diff] [blame] | 22 | #error Increase HIGH_MEMORY_SCRATCH allocation |
| 23 | #endif |
| 24 | |
Kyösti Mälkki | b1fcbf3 | 2015-05-26 11:25:13 +0300 | [diff] [blame] | 25 | void *GetHeapBase(void) |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 26 | { |
Kyösti Mälkki | b1fcbf3 | 2015-05-26 11:25:13 +0300 | [diff] [blame] | 27 | void *heap = (void *)BIOS_HEAP_START_ADDRESS; |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 28 | |
Kyösti Mälkki | 4240277 | 2017-03-29 15:55:23 +0300 | [diff] [blame] | 29 | if (acpi_is_wakeup_s3()) { |
| 30 | /* FIXME: For S3 resume path, buffer is in CBMEM |
| 31 | * with some arbitrary header. */ |
Kyösti Mälkki | b1fcbf3 | 2015-05-26 11:25:13 +0300 | [diff] [blame] | 32 | heap = cbmem_find(CBMEM_ID_RESUME_SCRATCH); |
Kyösti Mälkki | 4240277 | 2017-03-29 15:55:23 +0300 | [diff] [blame] | 33 | heap += 0x10; |
| 34 | } |
Kyösti Mälkki | 78c5d58 | 2015-01-09 23:48:47 +0200 | [diff] [blame] | 35 | |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 36 | return heap; |
| 37 | } |
| 38 | |
| 39 | void EmptyHeap(void) |
| 40 | { |
Kyösti Mälkki | b1fcbf3 | 2015-05-26 11:25:13 +0300 | [diff] [blame] | 41 | void *base = GetHeapBase(); |
| 42 | memset(base, 0, BIOS_HEAP_SIZE); |
Kyösti Mälkki | 50e6daf | 2016-11-27 06:37:52 +0200 | [diff] [blame] | 43 | |
| 44 | printk(BIOS_DEBUG, "Wiped HEAP at [%08x - %08x]\n", |
Elyes Haouas | 1ef547e | 2022-11-18 15:05:39 +0100 | [diff] [blame^] | 45 | (unsigned int)(uintptr_t)base, (unsigned int)(uintptr_t)base + BIOS_HEAP_SIZE - 1); |
Kyösti Mälkki | b1fcbf3 | 2015-05-26 11:25:13 +0300 | [diff] [blame] | 46 | } |
| 47 | |
Kyösti Mälkki | bceccec | 2017-03-29 10:59:21 +0300 | [diff] [blame] | 48 | #if defined(HEAP_CALLOUT_RUNTIME) && ENV_RAMSTAGE |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 49 | |
| 50 | #define AGESA_RUNTIME_SIZE 4096 |
Kyösti Mälkki | bceccec | 2017-03-29 10:59:21 +0300 | [diff] [blame] | 51 | static AGESA_STATUS alloc_cbmem(AGESA_BUFFER_PARAMS *AllocParams) |
| 52 | { |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 53 | static unsigned int used = 0; |
| 54 | void *p = cbmem_find(CBMEM_ID_AGESA_RUNTIME); |
| 55 | |
| 56 | if ((AGESA_RUNTIME_SIZE - used) < AllocParams->BufferLength) { |
| 57 | return AGESA_BOUNDS_CHK; |
| 58 | } |
| 59 | |
| 60 | /* first time allocation */ |
| 61 | if (!p) { |
| 62 | p = cbmem_add(CBMEM_ID_AGESA_RUNTIME, AGESA_RUNTIME_SIZE); |
| 63 | if (!p) |
| 64 | return AGESA_BOUNDS_CHK; |
| 65 | } |
| 66 | |
| 67 | AllocParams->BufferPointer = p + used; |
| 68 | used += AllocParams->BufferLength; |
| 69 | return AGESA_SUCCESS; |
| 70 | } |
| 71 | #endif |
| 72 | |
Kyösti Mälkki | 82fbda7 | 2015-01-02 22:46:32 +0200 | [diff] [blame] | 73 | typedef struct _BIOS_HEAP_MANAGER { |
| 74 | UINT32 StartOfAllocatedNodes; |
| 75 | UINT32 StartOfFreedNodes; |
| 76 | } BIOS_HEAP_MANAGER; |
| 77 | |
| 78 | typedef struct _BIOS_BUFFER_NODE { |
| 79 | UINT32 BufferHandle; |
| 80 | UINT32 BufferSize; |
| 81 | UINT32 NextNodeOffset; |
| 82 | } BIOS_BUFFER_NODE; |
| 83 | |
Kyösti Mälkki | 45ff9cb | 2017-03-29 10:59:45 +0300 | [diff] [blame] | 84 | static AGESA_STATUS agesa_AllocateBuffer(BIOS_HEAP_MANAGER *BiosHeapBasePtr, |
| 85 | AGESA_BUFFER_PARAMS *AllocParams) |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 86 | { |
| 87 | UINT32 AvailableHeapSize; |
Kyösti Mälkki | 45ff9cb | 2017-03-29 10:59:45 +0300 | [diff] [blame] | 88 | UINT8 *BiosHeapBaseAddr = (void *)BiosHeapBasePtr; |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 89 | UINT32 CurrNodeOffset; |
| 90 | UINT32 PrevNodeOffset; |
| 91 | UINT32 FreedNodeOffset; |
| 92 | UINT32 BestFitNodeOffset; |
| 93 | UINT32 BestFitPrevNodeOffset; |
| 94 | UINT32 NextFreeOffset; |
| 95 | BIOS_BUFFER_NODE *CurrNodePtr; |
| 96 | BIOS_BUFFER_NODE *FreedNodePtr; |
| 97 | BIOS_BUFFER_NODE *BestFitNodePtr; |
| 98 | BIOS_BUFFER_NODE *BestFitPrevNodePtr; |
| 99 | BIOS_BUFFER_NODE *NextFreePtr; |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 100 | |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 101 | AllocParams->BufferPointer = NULL; |
Elyes HAOUAS | 5e0242b | 2016-10-03 22:06:08 +0200 | [diff] [blame] | 102 | AvailableHeapSize = BIOS_HEAP_SIZE - sizeof(BIOS_HEAP_MANAGER); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 103 | |
| 104 | if (BiosHeapBasePtr->StartOfAllocatedNodes == 0) { |
| 105 | /* First allocation */ |
Elyes HAOUAS | 5e0242b | 2016-10-03 22:06:08 +0200 | [diff] [blame] | 106 | CurrNodeOffset = sizeof(BIOS_HEAP_MANAGER); |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 107 | CurrNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + CurrNodeOffset); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 108 | CurrNodePtr->BufferHandle = AllocParams->BufferHandle; |
| 109 | CurrNodePtr->BufferSize = AllocParams->BufferLength; |
| 110 | CurrNodePtr->NextNodeOffset = 0; |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 111 | AllocParams->BufferPointer = (UINT8 *)CurrNodePtr + sizeof(BIOS_BUFFER_NODE); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 112 | |
| 113 | /* Update the remaining free space */ |
Elyes HAOUAS | 5e0242b | 2016-10-03 22:06:08 +0200 | [diff] [blame] | 114 | FreedNodeOffset = CurrNodeOffset + CurrNodePtr->BufferSize + sizeof(BIOS_BUFFER_NODE); |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 115 | FreedNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + FreedNodeOffset); |
Marc Jones | 9826d1b | 2018-01-17 11:33:56 -0700 | [diff] [blame] | 116 | FreedNodePtr->BufferSize = AvailableHeapSize |
| 117 | - (FreedNodeOffset - CurrNodeOffset) |
| 118 | - sizeof(BIOS_BUFFER_NODE); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 119 | FreedNodePtr->NextNodeOffset = 0; |
| 120 | |
| 121 | /* Update the offsets for Allocated and Freed nodes */ |
| 122 | BiosHeapBasePtr->StartOfAllocatedNodes = CurrNodeOffset; |
| 123 | BiosHeapBasePtr->StartOfFreedNodes = FreedNodeOffset; |
| 124 | } else { |
| 125 | /* Find out whether BufferHandle has been allocated on the heap. |
| 126 | * If it has, return AGESA_BOUNDS_CHK. |
| 127 | */ |
| 128 | CurrNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes; |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 129 | CurrNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + CurrNodeOffset); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 130 | |
| 131 | while (CurrNodeOffset != 0) { |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 132 | CurrNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + CurrNodeOffset); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 133 | if (CurrNodePtr->BufferHandle == AllocParams->BufferHandle) { |
| 134 | return AGESA_BOUNDS_CHK; |
| 135 | } |
| 136 | CurrNodeOffset = CurrNodePtr->NextNodeOffset; |
| 137 | /* If BufferHandle has not been allocated on the heap, CurrNodePtr here points |
| 138 | * to the end of the allocated nodes list. |
| 139 | */ |
| 140 | } |
| 141 | /* Find the node that best fits the requested buffer size */ |
| 142 | FreedNodeOffset = BiosHeapBasePtr->StartOfFreedNodes; |
| 143 | PrevNodeOffset = FreedNodeOffset; |
| 144 | BestFitNodeOffset = 0; |
| 145 | BestFitPrevNodeOffset = 0; |
| 146 | while (FreedNodeOffset != 0) { |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 147 | FreedNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + FreedNodeOffset); |
Elyes HAOUAS | 5e0242b | 2016-10-03 22:06:08 +0200 | [diff] [blame] | 148 | if (FreedNodePtr->BufferSize >= (AllocParams->BufferLength + sizeof(BIOS_BUFFER_NODE))) { |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 149 | if (BestFitNodeOffset == 0) { |
| 150 | /* First node that fits the requested buffer size */ |
| 151 | BestFitNodeOffset = FreedNodeOffset; |
| 152 | BestFitPrevNodeOffset = PrevNodeOffset; |
| 153 | } else { |
| 154 | /* Find out whether current node is a better fit than the previous nodes */ |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 155 | BestFitNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + BestFitNodeOffset); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 156 | if (BestFitNodePtr->BufferSize > FreedNodePtr->BufferSize) { |
| 157 | BestFitNodeOffset = FreedNodeOffset; |
| 158 | BestFitPrevNodeOffset = PrevNodeOffset; |
| 159 | } |
| 160 | } |
| 161 | } |
| 162 | PrevNodeOffset = FreedNodeOffset; |
| 163 | FreedNodeOffset = FreedNodePtr->NextNodeOffset; |
| 164 | } /* end of while loop */ |
| 165 | |
| 166 | if (BestFitNodeOffset == 0) { |
| 167 | /* If we could not find a node that fits the requested buffer |
| 168 | * size, return AGESA_BOUNDS_CHK. |
| 169 | */ |
| 170 | return AGESA_BOUNDS_CHK; |
| 171 | } else { |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 172 | BestFitNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + BestFitNodeOffset); |
| 173 | BestFitPrevNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + BestFitPrevNodeOffset); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 174 | |
| 175 | /* If BestFitNode is larger than the requested buffer, fragment the node further */ |
Elyes HAOUAS | 5e0242b | 2016-10-03 22:06:08 +0200 | [diff] [blame] | 176 | if (BestFitNodePtr->BufferSize > (AllocParams->BufferLength + sizeof(BIOS_BUFFER_NODE))) { |
| 177 | NextFreeOffset = BestFitNodeOffset + AllocParams->BufferLength + sizeof(BIOS_BUFFER_NODE); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 178 | |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 179 | NextFreePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + NextFreeOffset); |
Elyes HAOUAS | 5e0242b | 2016-10-03 22:06:08 +0200 | [diff] [blame] | 180 | NextFreePtr->BufferSize = BestFitNodePtr->BufferSize - (AllocParams->BufferLength + sizeof(BIOS_BUFFER_NODE)); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 181 | NextFreePtr->NextNodeOffset = BestFitNodePtr->NextNodeOffset; |
| 182 | } else { |
| 183 | /* Otherwise, next free node is NextNodeOffset of BestFitNode */ |
| 184 | NextFreeOffset = BestFitNodePtr->NextNodeOffset; |
| 185 | } |
| 186 | |
| 187 | /* If BestFitNode is the first buffer in the list, then update |
| 188 | * StartOfFreedNodes to reflect the new free node. |
| 189 | */ |
| 190 | if (BestFitNodeOffset == BiosHeapBasePtr->StartOfFreedNodes) { |
| 191 | BiosHeapBasePtr->StartOfFreedNodes = NextFreeOffset; |
| 192 | } else { |
| 193 | BestFitPrevNodePtr->NextNodeOffset = NextFreeOffset; |
| 194 | } |
| 195 | |
| 196 | /* Add BestFitNode to the list of Allocated nodes */ |
| 197 | CurrNodePtr->NextNodeOffset = BestFitNodeOffset; |
| 198 | BestFitNodePtr->BufferSize = AllocParams->BufferLength; |
| 199 | BestFitNodePtr->BufferHandle = AllocParams->BufferHandle; |
| 200 | BestFitNodePtr->NextNodeOffset = 0; |
| 201 | |
| 202 | /* Remove BestFitNode from list of Freed nodes */ |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 203 | AllocParams->BufferPointer = (UINT8 *)BestFitNodePtr + sizeof(BIOS_BUFFER_NODE); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 204 | } |
| 205 | } |
| 206 | |
| 207 | return AGESA_SUCCESS; |
| 208 | } |
| 209 | |
Kyösti Mälkki | 45ff9cb | 2017-03-29 10:59:45 +0300 | [diff] [blame] | 210 | static AGESA_STATUS agesa_DeallocateBuffer(BIOS_HEAP_MANAGER *BiosHeapBasePtr, |
| 211 | AGESA_BUFFER_PARAMS *AllocParams) |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 212 | { |
Kyösti Mälkki | 45ff9cb | 2017-03-29 10:59:45 +0300 | [diff] [blame] | 213 | UINT8 *BiosHeapBaseAddr = (void *)BiosHeapBasePtr; |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 214 | UINT32 AllocNodeOffset; |
| 215 | UINT32 PrevNodeOffset; |
| 216 | UINT32 NextNodeOffset; |
| 217 | UINT32 FreedNodeOffset; |
| 218 | UINT32 EndNodeOffset; |
| 219 | BIOS_BUFFER_NODE *AllocNodePtr; |
| 220 | BIOS_BUFFER_NODE *PrevNodePtr; |
| 221 | BIOS_BUFFER_NODE *FreedNodePtr; |
| 222 | BIOS_BUFFER_NODE *NextNodePtr; |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 223 | |
| 224 | /* Find target node to deallocate in list of allocated nodes. |
| 225 | * Return AGESA_BOUNDS_CHK if the BufferHandle is not found. |
| 226 | */ |
| 227 | AllocNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes; |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 228 | AllocNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + AllocNodeOffset); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 229 | PrevNodeOffset = AllocNodeOffset; |
| 230 | |
| 231 | while (AllocNodePtr->BufferHandle != AllocParams->BufferHandle) { |
| 232 | if (AllocNodePtr->NextNodeOffset == 0) { |
| 233 | return AGESA_BOUNDS_CHK; |
| 234 | } |
| 235 | PrevNodeOffset = AllocNodeOffset; |
| 236 | AllocNodeOffset = AllocNodePtr->NextNodeOffset; |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 237 | AllocNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + AllocNodeOffset); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 238 | } |
| 239 | |
| 240 | /* Remove target node from list of allocated nodes */ |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 241 | PrevNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + PrevNodeOffset); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 242 | PrevNodePtr->NextNodeOffset = AllocNodePtr->NextNodeOffset; |
| 243 | |
| 244 | /* Zero out the buffer, and clear the BufferHandle */ |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 245 | LibAmdMemFill((UINT8 *)AllocNodePtr + sizeof(BIOS_BUFFER_NODE), 0, AllocNodePtr->BufferSize, &(AllocParams->StdHeader)); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 246 | AllocNodePtr->BufferHandle = 0; |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 247 | |
| 248 | /* Add deallocated node in order to the list of freed nodes */ |
| 249 | FreedNodeOffset = BiosHeapBasePtr->StartOfFreedNodes; |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 250 | FreedNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + FreedNodeOffset); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 251 | |
Marc Jones | 9826d1b | 2018-01-17 11:33:56 -0700 | [diff] [blame] | 252 | EndNodeOffset = AllocNodeOffset + AllocNodePtr->BufferSize + |
| 253 | sizeof(BIOS_BUFFER_NODE); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 254 | |
| 255 | if (AllocNodeOffset < FreedNodeOffset) { |
| 256 | /* Add to the start of the freed list */ |
| 257 | if (EndNodeOffset == FreedNodeOffset) { |
| 258 | /* If the freed node is adjacent to the first node in the list, concatenate both nodes */ |
Marc Jones | 9826d1b | 2018-01-17 11:33:56 -0700 | [diff] [blame] | 259 | AllocNodePtr->BufferSize += FreedNodePtr->BufferSize + |
| 260 | sizeof(BIOS_BUFFER_NODE); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 261 | AllocNodePtr->NextNodeOffset = FreedNodePtr->NextNodeOffset; |
| 262 | |
Marc Jones | 9826d1b | 2018-01-17 11:33:56 -0700 | [diff] [blame] | 263 | /* Zero out the FreedNode header */ |
| 264 | memset((UINT8 *)FreedNodePtr, 0, |
| 265 | sizeof(BIOS_BUFFER_NODE)); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 266 | } else { |
| 267 | /* Otherwise, add freed node to the start of the list |
| 268 | * Update NextNodeOffset and BufferSize to include the |
| 269 | * size of BIOS_BUFFER_NODE. |
| 270 | */ |
| 271 | AllocNodePtr->NextNodeOffset = FreedNodeOffset; |
| 272 | } |
| 273 | /* Update StartOfFreedNodes to the new first node */ |
| 274 | BiosHeapBasePtr->StartOfFreedNodes = AllocNodeOffset; |
| 275 | } else { |
| 276 | /* Traverse list of freed nodes to find where the deallocated node |
| 277 | * should be placed. |
| 278 | */ |
| 279 | NextNodeOffset = FreedNodeOffset; |
| 280 | NextNodePtr = FreedNodePtr; |
| 281 | while (AllocNodeOffset > NextNodeOffset) { |
| 282 | PrevNodeOffset = NextNodeOffset; |
| 283 | if (NextNodePtr->NextNodeOffset == 0) { |
| 284 | break; |
| 285 | } |
| 286 | NextNodeOffset = NextNodePtr->NextNodeOffset; |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 287 | NextNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + NextNodeOffset); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 288 | } |
| 289 | |
| 290 | /* If deallocated node is adjacent to the next node, |
| 291 | * concatenate both nodes. |
| 292 | */ |
| 293 | if (NextNodeOffset == EndNodeOffset) { |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 294 | NextNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + NextNodeOffset); |
Marc Jones | 9826d1b | 2018-01-17 11:33:56 -0700 | [diff] [blame] | 295 | AllocNodePtr->BufferSize += NextNodePtr->BufferSize + |
| 296 | sizeof(BIOS_BUFFER_NODE); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 297 | AllocNodePtr->NextNodeOffset = NextNodePtr->NextNodeOffset; |
| 298 | |
Marc Jones | 9826d1b | 2018-01-17 11:33:56 -0700 | [diff] [blame] | 299 | /* Zero out the NextNode header */ |
| 300 | memset((UINT8 *)NextNodePtr, 0, |
| 301 | sizeof(BIOS_BUFFER_NODE)); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 302 | } else { |
| 303 | /*AllocNodePtr->NextNodeOffset = FreedNodePtr->NextNodeOffset; */ |
| 304 | AllocNodePtr->NextNodeOffset = NextNodeOffset; |
| 305 | } |
| 306 | /* If deallocated node is adjacent to the previous node, |
| 307 | * concatenate both nodes. |
| 308 | */ |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 309 | PrevNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + PrevNodeOffset); |
Marc Jones | 9826d1b | 2018-01-17 11:33:56 -0700 | [diff] [blame] | 310 | EndNodeOffset = PrevNodeOffset + PrevNodePtr->BufferSize + |
| 311 | sizeof(BIOS_BUFFER_NODE); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 312 | if (AllocNodeOffset == EndNodeOffset) { |
| 313 | PrevNodePtr->NextNodeOffset = AllocNodePtr->NextNodeOffset; |
Marc Jones | 9826d1b | 2018-01-17 11:33:56 -0700 | [diff] [blame] | 314 | PrevNodePtr->BufferSize += AllocNodePtr->BufferSize + |
| 315 | sizeof(BIOS_BUFFER_NODE); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 316 | |
Marc Jones | 9826d1b | 2018-01-17 11:33:56 -0700 | [diff] [blame] | 317 | /* Zero out the AllocNode header */ |
| 318 | memset((UINT8 *)AllocNodePtr, 0, |
| 319 | sizeof(BIOS_BUFFER_NODE)); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 320 | } else { |
| 321 | PrevNodePtr->NextNodeOffset = AllocNodeOffset; |
| 322 | } |
| 323 | } |
| 324 | return AGESA_SUCCESS; |
| 325 | } |
| 326 | |
Kyösti Mälkki | 45ff9cb | 2017-03-29 10:59:45 +0300 | [diff] [blame] | 327 | static AGESA_STATUS agesa_LocateBuffer(BIOS_HEAP_MANAGER *BiosHeapBasePtr, |
| 328 | AGESA_BUFFER_PARAMS *AllocParams) |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 329 | { |
| 330 | UINT32 AllocNodeOffset; |
Kyösti Mälkki | 45ff9cb | 2017-03-29 10:59:45 +0300 | [diff] [blame] | 331 | UINT8 *BiosHeapBaseAddr = (void *)BiosHeapBasePtr; |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 332 | BIOS_BUFFER_NODE *AllocNodePtr; |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 333 | |
| 334 | AllocNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes; |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 335 | AllocNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + AllocNodeOffset); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 336 | |
| 337 | while (AllocParams->BufferHandle != AllocNodePtr->BufferHandle) { |
| 338 | if (AllocNodePtr->NextNodeOffset == 0) { |
| 339 | AllocParams->BufferPointer = NULL; |
| 340 | AllocParams->BufferLength = 0; |
| 341 | return AGESA_BOUNDS_CHK; |
| 342 | } else { |
| 343 | AllocNodeOffset = AllocNodePtr->NextNodeOffset; |
Elyes Haouas | 76c6323 | 2022-07-16 09:47:00 +0200 | [diff] [blame] | 344 | AllocNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + AllocNodeOffset); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 345 | } |
| 346 | } |
| 347 | |
Elyes Haouas | 1ef547e | 2022-11-18 15:05:39 +0100 | [diff] [blame^] | 348 | AllocParams->BufferPointer = (UINT8 *)((UINT8 *)AllocNodePtr + sizeof(BIOS_BUFFER_NODE)); |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 349 | AllocParams->BufferLength = AllocNodePtr->BufferSize; |
| 350 | |
| 351 | return AGESA_SUCCESS; |
Kyösti Mälkki | ef9343c | 2014-05-04 11:42:55 +0300 | [diff] [blame] | 352 | } |
Kyösti Mälkki | 82fbda7 | 2015-01-02 22:46:32 +0200 | [diff] [blame] | 353 | |
Stefan Reinauer | dd132a5 | 2015-07-30 11:16:37 -0700 | [diff] [blame] | 354 | AGESA_STATUS HeapManagerCallout(UINT32 Func, UINTN Data, VOID *ConfigPtr) |
Kyösti Mälkki | 82fbda7 | 2015-01-02 22:46:32 +0200 | [diff] [blame] | 355 | { |
Kyösti Mälkki | bceccec | 2017-03-29 10:59:21 +0300 | [diff] [blame] | 356 | AGESA_BUFFER_PARAMS *AllocParams = ConfigPtr; |
| 357 | |
Kyösti Mälkki | 45ff9cb | 2017-03-29 10:59:45 +0300 | [diff] [blame] | 358 | #if defined(HEAP_CALLOUT_RUNTIME) && ENV_RAMSTAGE |
Kyösti Mälkki | bceccec | 2017-03-29 10:59:21 +0300 | [diff] [blame] | 359 | if (Func == AGESA_ALLOCATE_BUFFER && Data == HEAP_CALLOUT_RUNTIME) |
| 360 | return alloc_cbmem(AllocParams); |
| 361 | #endif |
| 362 | |
Kyösti Mälkki | 45ff9cb | 2017-03-29 10:59:45 +0300 | [diff] [blame] | 363 | /* Must not call GetHeapBase() in AGESA_UNSUPPORTED path. */ |
Kyösti Mälkki | 82fbda7 | 2015-01-02 22:46:32 +0200 | [diff] [blame] | 364 | if (Func == AGESA_LOCATE_BUFFER) |
Kyösti Mälkki | 45ff9cb | 2017-03-29 10:59:45 +0300 | [diff] [blame] | 365 | return agesa_LocateBuffer(GetHeapBase(), AllocParams); |
Kyösti Mälkki | 82fbda7 | 2015-01-02 22:46:32 +0200 | [diff] [blame] | 366 | else if (Func == AGESA_ALLOCATE_BUFFER) |
Kyösti Mälkki | 45ff9cb | 2017-03-29 10:59:45 +0300 | [diff] [blame] | 367 | return agesa_AllocateBuffer(GetHeapBase(), AllocParams); |
Kyösti Mälkki | 82fbda7 | 2015-01-02 22:46:32 +0200 | [diff] [blame] | 368 | else if (Func == AGESA_DEALLOCATE_BUFFER) |
Kyösti Mälkki | 45ff9cb | 2017-03-29 10:59:45 +0300 | [diff] [blame] | 369 | return agesa_DeallocateBuffer(GetHeapBase(), AllocParams); |
| 370 | |
| 371 | return AGESA_UNSUPPORTED; |
Kyösti Mälkki | 82fbda7 | 2015-01-02 22:46:32 +0200 | [diff] [blame] | 372 | } |