blob: 6f7ad7259d9a0be6b5626dc3c992888cb3603e7c [file] [log] [blame]
Angel Ponsae593872020-04-04 18:50:57 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Marc Jones21cde8b2017-05-07 16:47:36 -06002
3
Richard Spiegel0ad74ac2017-12-08 16:53:29 -07004#include <amdblocks/agesawrapper.h>
Richard Spiegel0ad74ac2017-12-08 16:53:29 -07005#include <amdblocks/BiosCallOuts.h>
Marc Jones21cde8b2017-05-07 16:47:36 -06006#include <cbmem.h>
Marc Jones21cde8b2017-05-07 16:47:36 -06007#include <string.h>
8
Marshall Dawson1dd7a112018-03-28 20:21:10 -06009static void *agesa_heap_base(void)
Marc Jones21cde8b2017-05-07 16:47:36 -060010{
Marshall Dawson8cc5fde2018-01-30 15:23:48 -070011 return cbmem_add(CBMEM_ID_RESUME_SCRATCH, BIOS_HEAP_SIZE);
Marc Jones21cde8b2017-05-07 16:47:36 -060012}
13
Marshall Dawson6c747062017-09-21 12:21:14 -060014static void EmptyHeap(int unused)
Marc Jones21cde8b2017-05-07 16:47:36 -060015{
Marshall Dawson21c5e152017-12-15 11:13:54 -070016 void *BiosManagerPtr = agesa_heap_base();
Marc Jones21cde8b2017-05-07 16:47:36 -060017 memset(BiosManagerPtr, 0, BIOS_HEAP_SIZE);
18}
19
Richard Spiegel51895d12018-04-17 14:25:26 -070020/*
Marshall Dawson10b52e02018-05-07 08:51:04 -060021 * Name agesa_GetTempHeapBase
22 * Brief description Get the location for TempRam, the target location in
23 * memory where AmdInitPost copies the heap prior to CAR
24 * teardown. AmdInitEnv calls this function after
25 * teardown for the source address when relocation the
26 * heap to its final location.
27 * Input parameters
28 * Func Unused
29 * Data Unused
30 * ConfigPtr Pointer to type AGESA_TEMP_HEAP_BASE_PARAMS
31 * Output parameters
32 * Status Indicates whether TempHeapAddress was successfully
33 * set.
34 */
Richard Spiegel271b8a52018-11-06 16:32:28 -070035AGESA_STATUS agesa_GetTempHeapBase(uint32_t Func, uintptr_t Data,
36 void *ConfigPtr)
Marshall Dawson10b52e02018-05-07 08:51:04 -060037{
38 AGESA_TEMP_HEAP_BASE_PARAMS *pTempHeapBase;
39
40 pTempHeapBase = (AGESA_TEMP_HEAP_BASE_PARAMS *)ConfigPtr;
41 pTempHeapBase->TempHeapAddress = CONFIG_PI_AGESA_TEMP_RAM_BASE;
42
43 return AGESA_SUCCESS;
44}
45
46/*
Marshall Dawsonc150a572018-04-30 17:59:27 -060047 * Name agesa_HeapRebase
48 * Brief description AGESA may use internal hardcoded locations for its
49 * heap. Modern implementations allow the base to be
50 * overridden by calling agesa_HeapRebase.
51 * Input parameters
52 * Func Unused
53 * Data Unused
54 * ConfigPtr Pointer to type AGESA_REBASE_PARAMS
55 * Output parameters
56 * Status Indicates whether HeapAddress was successfully
57 * set.
58 */
Richard Spiegel271b8a52018-11-06 16:32:28 -070059AGESA_STATUS agesa_HeapRebase(uint32_t Func, uintptr_t Data, void *ConfigPtr)
Marshall Dawsonc150a572018-04-30 17:59:27 -060060{
61 AGESA_REBASE_PARAMS *Rebase;
62
63 Rebase = (AGESA_REBASE_PARAMS *)ConfigPtr;
Richard Spiegel271b8a52018-11-06 16:32:28 -070064 Rebase->HeapAddress = (uintptr_t)agesa_heap_base();
Marshall Dawson418c2bb2018-06-27 10:45:33 -060065 if (!Rebase->HeapAddress)
Marshall Dawsonc150a572018-04-30 17:59:27 -060066 Rebase->HeapAddress = CONFIG_PI_AGESA_CAR_HEAP_BASE;
Marshall Dawsonc150a572018-04-30 17:59:27 -060067
68 return AGESA_SUCCESS;
69}
70
71/*
Richard Spiegel51895d12018-04-17 14:25:26 -070072 * Name FindAllocatedNode
73 * Brief description Find an allocated node that matches the handle.
74 * Input parameter The desired handle.
75 * Output parameters
76 * pointer Here is returned either the found node or the last
77 * allocated node if the handle is not found. This is
78 * intentional, as the field NextNode of this node will
79 * have to be filled with the offset of the node being
80 * created in procedure agesa_AllocateBuffer().
81 * Status Indicates if the node was or was not found.
82 */
83static AGESA_STATUS FindAllocatedNode(uint32_t handle,
84 BIOS_BUFFER_NODE **last_allocd_or_match)
85{
Richard Spiegel271b8a52018-11-06 16:32:28 -070086 uint32_t AllocNodeOffset;
87 uint8_t *BiosHeapBaseAddr;
Richard Spiegel51895d12018-04-17 14:25:26 -070088 BIOS_BUFFER_NODE *AllocNodePtr;
89 BIOS_HEAP_MANAGER *BiosHeapBasePtr;
90 AGESA_STATUS Status = AGESA_SUCCESS;
91
92 BiosHeapBaseAddr = agesa_heap_base();
93 BiosHeapBasePtr = (BIOS_HEAP_MANAGER *)BiosHeapBaseAddr;
94
95 AllocNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes;
96 AllocNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + AllocNodeOffset);
97
98 while (handle != AllocNodePtr->BufferHandle) {
99 if (AllocNodePtr->NextNodeOffset == 0) {
100 Status = AGESA_BOUNDS_CHK;
101 break;
102 }
103 AllocNodeOffset = AllocNodePtr->NextNodeOffset;
104 AllocNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr +
105 AllocNodeOffset);
106 }
107 *last_allocd_or_match = AllocNodePtr;
108 return Status;
109}
110
111/*
112 * Name ConcatenateNodes
113 * Brief description Concatenates two adjacent nodes into a single node,
114 * this procedure is used by agesa_DeallocateBuffer().
115 * Input parameters
116 * FirstNodePtr This node is in the front, its header will be
117 * maintained.
118 * SecondNodePtr This node is in the back, its header will be cleared.
119 */
120static void ConcatenateNodes(BIOS_BUFFER_NODE *FirstNodePtr,
121 BIOS_BUFFER_NODE *SecondNodePtr)
122{
123 FirstNodePtr->BufferSize += SecondNodePtr->BufferSize +
124 sizeof(BIOS_BUFFER_NODE);
125 FirstNodePtr->NextNodeOffset = SecondNodePtr->NextNodeOffset;
126
127 /* Zero out the SecondNode header */
128 memset(SecondNodePtr, 0, sizeof(BIOS_BUFFER_NODE));
129}
130
Marshall Dawson6c747062017-09-21 12:21:14 -0600131ROMSTAGE_CBMEM_INIT_HOOK(EmptyHeap)
132
Richard Spiegel271b8a52018-11-06 16:32:28 -0700133AGESA_STATUS agesa_AllocateBuffer(uint32_t Func, uintptr_t Data,
134 void *ConfigPtr)
Marc Jones21cde8b2017-05-07 16:47:36 -0600135{
Richard Spiegel51895d12018-04-17 14:25:26 -0700136 /*
137 * Size variables explanation:
138 * FreedNodeSize - the size of the buffer node being examined,
139 * will be copied to BestFitNodeSize if the node
140 * is selected as a possible best fit.
141 * BestFitNodeSize - the size qf the buffer of the node currently
142 * considered the best fit.
143 * MinimumSize - the requested size + sizeof(BIOS_BUFFER_NODE).
144 * Its the minimum size for the buffer to be broken
145 * down into 2 nodes, once a node is selected as
146 * the best fit.
147 */
Richard Spiegel271b8a52018-11-06 16:32:28 -0700148 uint32_t AvailableHeapSize;
149 uint8_t *BiosHeapBaseAddr;
150 uint32_t CurrNodeOffset;
151 uint32_t PrevNodeOffset;
152 uint32_t FreedNodeOffset;
153 uint32_t FreedNodeSize;
154 uint32_t BestFitNodeOffset;
155 uint32_t BestFitNodeSize;
156 uint32_t BestFitPrevNodeOffset;
157 uint32_t NextFreeOffset;
158 uint32_t MinimumSize;
Marc Jones21cde8b2017-05-07 16:47:36 -0600159 BIOS_BUFFER_NODE *CurrNodePtr;
160 BIOS_BUFFER_NODE *FreedNodePtr;
161 BIOS_BUFFER_NODE *BestFitNodePtr;
162 BIOS_BUFFER_NODE *BestFitPrevNodePtr;
163 BIOS_BUFFER_NODE *NextFreePtr;
164 BIOS_HEAP_MANAGER *BiosHeapBasePtr;
165 AGESA_BUFFER_PARAMS *AllocParams;
Richard Spiegel51895d12018-04-17 14:25:26 -0700166 AGESA_STATUS Status;
Marc Jones21cde8b2017-05-07 16:47:36 -0600167
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600168 AllocParams = ((AGESA_BUFFER_PARAMS *)ConfigPtr);
Marc Jones21cde8b2017-05-07 16:47:36 -0600169 AllocParams->BufferPointer = NULL;
Richard Spiegel51895d12018-04-17 14:25:26 -0700170 MinimumSize = AllocParams->BufferLength + sizeof(BIOS_BUFFER_NODE);
Marc Jones21cde8b2017-05-07 16:47:36 -0600171
172 AvailableHeapSize = BIOS_HEAP_SIZE - sizeof(BIOS_HEAP_MANAGER);
Richard Spiegel51895d12018-04-17 14:25:26 -0700173 BestFitNodeSize = AvailableHeapSize; /* init with largest possible */
Marshall Dawson21c5e152017-12-15 11:13:54 -0700174 BiosHeapBaseAddr = agesa_heap_base();
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600175 BiosHeapBasePtr = (BIOS_HEAP_MANAGER *)BiosHeapBaseAddr;
Marc Jones21cde8b2017-05-07 16:47:36 -0600176
177 if (BiosHeapBasePtr->StartOfAllocatedNodes == 0) {
178 /* First allocation */
179 CurrNodeOffset = sizeof(BIOS_HEAP_MANAGER);
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600180 CurrNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr
181 + CurrNodeOffset);
Marc Jones21cde8b2017-05-07 16:47:36 -0600182 CurrNodePtr->BufferHandle = AllocParams->BufferHandle;
183 CurrNodePtr->BufferSize = AllocParams->BufferLength;
184 CurrNodePtr->NextNodeOffset = 0;
Richard Spiegel271b8a52018-11-06 16:32:28 -0700185 AllocParams->BufferPointer = (uint8_t *)CurrNodePtr
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600186 + sizeof(BIOS_BUFFER_NODE);
Marc Jones21cde8b2017-05-07 16:47:36 -0600187
188 /* Update the remaining free space */
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600189 FreedNodeOffset = CurrNodeOffset + CurrNodePtr->BufferSize
190 + sizeof(BIOS_BUFFER_NODE);
191 FreedNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr
192 + FreedNodeOffset);
193 FreedNodePtr->BufferSize = AvailableHeapSize
Marc Jonese6033ce2018-01-15 18:47:24 -0700194 - (FreedNodeOffset - CurrNodeOffset)
195 - sizeof(BIOS_BUFFER_NODE);
Marc Jones21cde8b2017-05-07 16:47:36 -0600196 FreedNodePtr->NextNodeOffset = 0;
197
198 /* Update the offsets for Allocated and Freed nodes */
199 BiosHeapBasePtr->StartOfAllocatedNodes = CurrNodeOffset;
200 BiosHeapBasePtr->StartOfFreedNodes = FreedNodeOffset;
201 } else {
Richard Spiegel51895d12018-04-17 14:25:26 -0700202 /*
203 * Find out whether BufferHandle has been allocated on the heap.
Marc Jones21cde8b2017-05-07 16:47:36 -0600204 * If it has, return AGESA_BOUNDS_CHK.
205 */
Richard Spiegel51895d12018-04-17 14:25:26 -0700206 Status = FindAllocatedNode(AllocParams->BufferHandle,
207 &CurrNodePtr);
208 if (Status == AGESA_SUCCESS)
209 return AGESA_BOUNDS_CHK;
Marc Jones21cde8b2017-05-07 16:47:36 -0600210
Richard Spiegel51895d12018-04-17 14:25:26 -0700211 /*
212 * If status ditn't returned AGESA_SUCCESS, CurrNodePtr here
213 * points to the end of the allocated nodes list.
214 */
215
Marc Jones21cde8b2017-05-07 16:47:36 -0600216 /* Find the node that best fits the requested buffer size */
217 FreedNodeOffset = BiosHeapBasePtr->StartOfFreedNodes;
218 PrevNodeOffset = FreedNodeOffset;
219 BestFitNodeOffset = 0;
220 BestFitPrevNodeOffset = 0;
Richard Spiegel51895d12018-04-17 14:25:26 -0700221 while (FreedNodeOffset != 0) {
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600222 FreedNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr
223 + FreedNodeOffset);
Richard Spiegel51895d12018-04-17 14:25:26 -0700224 FreedNodeSize = FreedNodePtr->BufferSize;
225 if (FreedNodeSize >= MinimumSize) {
Marc Jones21cde8b2017-05-07 16:47:36 -0600226 if (BestFitNodeOffset == 0) {
Richard Spiegelfc511272017-12-11 16:23:58 -0700227 /*
228 * First node that fits the requested
229 * buffer size
230 */
Marc Jones21cde8b2017-05-07 16:47:36 -0600231 BestFitNodeOffset = FreedNodeOffset;
232 BestFitPrevNodeOffset = PrevNodeOffset;
Richard Spiegel51895d12018-04-17 14:25:26 -0700233 BestFitNodeSize = FreedNodeSize;
Marc Jones21cde8b2017-05-07 16:47:36 -0600234 } else {
Richard Spiegelfc511272017-12-11 16:23:58 -0700235 /*
236 * Find out whether current node is a
237 * betterfit than the previous nodes
238 */
Richard Spiegel51895d12018-04-17 14:25:26 -0700239 if (BestFitNodeSize > FreedNodeSize) {
Richard Spiegelfc511272017-12-11 16:23:58 -0700240
241 BestFitNodeOffset =
242 FreedNodeOffset;
243 BestFitPrevNodeOffset =
244 PrevNodeOffset;
Richard Spiegel51895d12018-04-17 14:25:26 -0700245 BestFitNodeSize = FreedNodeSize;
Marc Jones21cde8b2017-05-07 16:47:36 -0600246 }
247 }
248 }
249 PrevNodeOffset = FreedNodeOffset;
250 FreedNodeOffset = FreedNodePtr->NextNodeOffset;
251 } /* end of while loop */
252
253 if (BestFitNodeOffset == 0) {
Richard Spiegelfc511272017-12-11 16:23:58 -0700254 /*
255 * If we could not find a node that fits the requested
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600256 * buffer size, return AGESA_BOUNDS_CHK.
Marc Jones21cde8b2017-05-07 16:47:36 -0600257 */
258 return AGESA_BOUNDS_CHK;
Marc Jones21cde8b2017-05-07 16:47:36 -0600259 }
Richard Spiegelfc511272017-12-11 16:23:58 -0700260
261 BestFitNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr
262 + BestFitNodeOffset);
263 BestFitPrevNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr +
264 BestFitPrevNodeOffset);
265
266 /*
Marc Jonesa2737532018-01-12 16:52:29 +0000267 * If BestFitNode is larger than the requested buffer,
268 * fragment the node further
Richard Spiegelfc511272017-12-11 16:23:58 -0700269 */
Richard Spiegel51895d12018-04-17 14:25:26 -0700270 if (BestFitNodePtr->BufferSize > MinimumSize) {
271 NextFreeOffset = BestFitNodeOffset + MinimumSize;
Richard Spiegelfc511272017-12-11 16:23:58 -0700272 NextFreePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr +
273 NextFreeOffset);
Richard Spiegel51895d12018-04-17 14:25:26 -0700274 NextFreePtr->BufferSize = BestFitNodeSize - MinimumSize;
275
276 /* Remove BestFitNode from list of Freed nodes */
Richard Spiegelfc511272017-12-11 16:23:58 -0700277 NextFreePtr->NextNodeOffset =
278 BestFitNodePtr->NextNodeOffset;
279 } else {
280 /*
Richard Spiegel51895d12018-04-17 14:25:26 -0700281 * Otherwise, next free node is NextNodeOffset of
282 * BestFitNode. Remove it from list of Freed nodes.
Richard Spiegelfc511272017-12-11 16:23:58 -0700283 */
284 NextFreeOffset = BestFitNodePtr->NextNodeOffset;
285 }
286
287 /*
288 * If BestFitNode is the first buffer in the list, then
289 * update StartOfFreedNodes to reflect new free node.
290 */
291 if (BestFitNodeOffset == BiosHeapBasePtr->StartOfFreedNodes)
292 BiosHeapBasePtr->StartOfFreedNodes = NextFreeOffset;
293 else
294 BestFitPrevNodePtr->NextNodeOffset = NextFreeOffset;
295
296 /* Add BestFitNode to the list of Allocated nodes */
297 CurrNodePtr->NextNodeOffset = BestFitNodeOffset;
298 BestFitNodePtr->BufferSize = AllocParams->BufferLength;
299 BestFitNodePtr->BufferHandle = AllocParams->BufferHandle;
300 BestFitNodePtr->NextNodeOffset = 0;
301
Richard Spiegel271b8a52018-11-06 16:32:28 -0700302 AllocParams->BufferPointer = (uint8_t *)BestFitNodePtr +
Richard Spiegelfc511272017-12-11 16:23:58 -0700303 sizeof(BIOS_BUFFER_NODE);
Marc Jones21cde8b2017-05-07 16:47:36 -0600304 }
305
306 return AGESA_SUCCESS;
307}
308
Richard Spiegel271b8a52018-11-06 16:32:28 -0700309AGESA_STATUS agesa_DeallocateBuffer(uint32_t Func, uintptr_t Data,
310 void *ConfigPtr)
Marc Jones21cde8b2017-05-07 16:47:36 -0600311{
312
Richard Spiegel271b8a52018-11-06 16:32:28 -0700313 uint8_t *BiosHeapBaseAddr;
314 uint32_t AllocNodeOffset;
315 uint32_t PrevNodeOffset;
316 uint32_t NextNodeOffset;
317 uint32_t FreedNodeOffset;
318 uint32_t EndNodeOffset;
Marc Jones21cde8b2017-05-07 16:47:36 -0600319 BIOS_BUFFER_NODE *AllocNodePtr;
320 BIOS_BUFFER_NODE *PrevNodePtr;
321 BIOS_BUFFER_NODE *FreedNodePtr;
322 BIOS_BUFFER_NODE *NextNodePtr;
323 BIOS_HEAP_MANAGER *BiosHeapBasePtr;
324 AGESA_BUFFER_PARAMS *AllocParams;
325
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600326 AllocParams = (AGESA_BUFFER_PARAMS *)ConfigPtr;
Marc Jones21cde8b2017-05-07 16:47:36 -0600327
Marshall Dawson21c5e152017-12-15 11:13:54 -0700328 BiosHeapBaseAddr = agesa_heap_base();
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600329 BiosHeapBasePtr = (BIOS_HEAP_MANAGER *)BiosHeapBaseAddr;
Marc Jones21cde8b2017-05-07 16:47:36 -0600330
331 /* Find target node to deallocate in list of allocated nodes.
332 * Return AGESA_BOUNDS_CHK if the BufferHandle is not found.
333 */
334 AllocNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes;
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600335 AllocNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + AllocNodeOffset);
Marc Jones21cde8b2017-05-07 16:47:36 -0600336 PrevNodeOffset = AllocNodeOffset;
337
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600338 while (AllocNodePtr->BufferHandle != AllocParams->BufferHandle) {
339 if (AllocNodePtr->NextNodeOffset == 0)
Marc Jones21cde8b2017-05-07 16:47:36 -0600340 return AGESA_BOUNDS_CHK;
Marc Jones21cde8b2017-05-07 16:47:36 -0600341 PrevNodeOffset = AllocNodeOffset;
342 AllocNodeOffset = AllocNodePtr->NextNodeOffset;
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600343 AllocNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr
344 + AllocNodeOffset);
Marc Jones21cde8b2017-05-07 16:47:36 -0600345 }
346
347 /* Remove target node from list of allocated nodes */
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600348 PrevNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + PrevNodeOffset);
Marc Jones21cde8b2017-05-07 16:47:36 -0600349 PrevNodePtr->NextNodeOffset = AllocNodePtr->NextNodeOffset;
350
351 /* Zero out the buffer, and clear the BufferHandle */
Richard Spiegel271b8a52018-11-06 16:32:28 -0700352 memset((uint8_t *)AllocNodePtr + sizeof(BIOS_BUFFER_NODE), 0,
Aaron Durbine3f7d442017-11-03 11:44:10 -0600353 AllocNodePtr->BufferSize);
Marc Jones21cde8b2017-05-07 16:47:36 -0600354 AllocNodePtr->BufferHandle = 0;
Marc Jones21cde8b2017-05-07 16:47:36 -0600355
356 /* Add deallocated node in order to the list of freed nodes */
357 FreedNodeOffset = BiosHeapBasePtr->StartOfFreedNodes;
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600358 FreedNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + FreedNodeOffset);
Marc Jones21cde8b2017-05-07 16:47:36 -0600359
Marc Jonese6033ce2018-01-15 18:47:24 -0700360 EndNodeOffset = AllocNodeOffset + AllocNodePtr->BufferSize +
361 sizeof(BIOS_BUFFER_NODE);
Marc Jones21cde8b2017-05-07 16:47:36 -0600362
363 if (AllocNodeOffset < FreedNodeOffset) {
364 /* Add to the start of the freed list */
365 if (EndNodeOffset == FreedNodeOffset) {
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600366 /* If the freed node is adjacent to the first node in
367 * the list, concatenate both nodes
368 */
Richard Spiegel51895d12018-04-17 14:25:26 -0700369 ConcatenateNodes(AllocNodePtr, FreedNodePtr);
Marc Jones21cde8b2017-05-07 16:47:36 -0600370 } else {
371 /* Otherwise, add freed node to the start of the list
372 * Update NextNodeOffset and BufferSize to include the
373 * size of BIOS_BUFFER_NODE.
374 */
375 AllocNodePtr->NextNodeOffset = FreedNodeOffset;
376 }
377 /* Update StartOfFreedNodes to the new first node */
378 BiosHeapBasePtr->StartOfFreedNodes = AllocNodeOffset;
379 } else {
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600380 /* Traverse list of freed nodes to find where the deallocated
381 * node should be placed.
Marc Jones21cde8b2017-05-07 16:47:36 -0600382 */
383 NextNodeOffset = FreedNodeOffset;
384 NextNodePtr = FreedNodePtr;
385 while (AllocNodeOffset > NextNodeOffset) {
386 PrevNodeOffset = NextNodeOffset;
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600387 if (NextNodePtr->NextNodeOffset == 0)
Marc Jones21cde8b2017-05-07 16:47:36 -0600388 break;
Marc Jones21cde8b2017-05-07 16:47:36 -0600389 NextNodeOffset = NextNodePtr->NextNodeOffset;
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600390 NextNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr
391 + NextNodeOffset);
Marc Jones21cde8b2017-05-07 16:47:36 -0600392 }
393
394 /* If deallocated node is adjacent to the next node,
395 * concatenate both nodes.
396 */
397 if (NextNodeOffset == EndNodeOffset) {
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600398 NextNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr
399 + NextNodeOffset);
Richard Spiegel51895d12018-04-17 14:25:26 -0700400 ConcatenateNodes(AllocNodePtr, NextNodePtr);
Marc Jones21cde8b2017-05-07 16:47:36 -0600401 } else {
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600402 /*AllocNodePtr->NextNodeOffset =
Elyes HAOUAS05498a22018-05-28 16:26:43 +0200403 * FreedNodePtr->NextNodeOffset; */
Marc Jones21cde8b2017-05-07 16:47:36 -0600404 AllocNodePtr->NextNodeOffset = NextNodeOffset;
405 }
Richard Spiegelfc511272017-12-11 16:23:58 -0700406 /*
407 * If deallocated node is adjacent to the previous node,
Marc Jones21cde8b2017-05-07 16:47:36 -0600408 * concatenate both nodes.
409 */
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600410 PrevNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr
411 + PrevNodeOffset);
Marc Jonese6033ce2018-01-15 18:47:24 -0700412 EndNodeOffset = PrevNodeOffset + PrevNodePtr->BufferSize +
413 sizeof(BIOS_BUFFER_NODE);
414
Richard Spiegel51895d12018-04-17 14:25:26 -0700415 if (AllocNodeOffset == EndNodeOffset)
416 ConcatenateNodes(PrevNodePtr, AllocNodePtr);
417 else
Marc Jones21cde8b2017-05-07 16:47:36 -0600418 PrevNodePtr->NextNodeOffset = AllocNodeOffset;
Marc Jones21cde8b2017-05-07 16:47:36 -0600419 }
420 return AGESA_SUCCESS;
421}
422
Richard Spiegel271b8a52018-11-06 16:32:28 -0700423AGESA_STATUS agesa_LocateBuffer(uint32_t Func, uintptr_t Data, void *ConfigPtr)
Marc Jones21cde8b2017-05-07 16:47:36 -0600424{
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600425 BIOS_BUFFER_NODE *AllocNodePtr;
Marc Jones21cde8b2017-05-07 16:47:36 -0600426 AGESA_BUFFER_PARAMS *AllocParams;
Richard Spiegel51895d12018-04-17 14:25:26 -0700427 AGESA_STATUS Status;
Marc Jones21cde8b2017-05-07 16:47:36 -0600428
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600429 AllocParams = (AGESA_BUFFER_PARAMS *)ConfigPtr;
Marc Jones21cde8b2017-05-07 16:47:36 -0600430
Richard Spiegel51895d12018-04-17 14:25:26 -0700431 Status = FindAllocatedNode(AllocParams->BufferHandle, &AllocNodePtr);
Marc Jones21cde8b2017-05-07 16:47:36 -0600432
Richard Spiegel51895d12018-04-17 14:25:26 -0700433 if (Status == AGESA_SUCCESS) {
Richard Spiegel271b8a52018-11-06 16:32:28 -0700434 AllocParams->BufferPointer = (uint8_t *)((uint8_t *)AllocNodePtr
Richard Spiegel51895d12018-04-17 14:25:26 -0700435 + sizeof(BIOS_BUFFER_NODE));
436 AllocParams->BufferLength = AllocNodePtr->BufferSize;
Marc Jones21cde8b2017-05-07 16:47:36 -0600437 }
438
Richard Spiegel51895d12018-04-17 14:25:26 -0700439 return Status;
Marc Jones21cde8b2017-05-07 16:47:36 -0600440
441}