blob: 34a4837d73dc72cefc9e4a69364654810e551051 [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
Richard Spiegel0ad74ac2017-12-08 16:53:29 -07003#include <amdblocks/agesawrapper.h>
Richard Spiegel0ad74ac2017-12-08 16:53:29 -07004#include <amdblocks/BiosCallOuts.h>
Marc Jones21cde8b2017-05-07 16:47:36 -06005#include <cbmem.h>
Marc Jones21cde8b2017-05-07 16:47:36 -06006#include <string.h>
7
Marshall Dawson1dd7a112018-03-28 20:21:10 -06008static void *agesa_heap_base(void)
Marc Jones21cde8b2017-05-07 16:47:36 -06009{
Marshall Dawson8cc5fde2018-01-30 15:23:48 -070010 return cbmem_add(CBMEM_ID_RESUME_SCRATCH, BIOS_HEAP_SIZE);
Marc Jones21cde8b2017-05-07 16:47:36 -060011}
12
Marshall Dawson6c747062017-09-21 12:21:14 -060013static void EmptyHeap(int unused)
Marc Jones21cde8b2017-05-07 16:47:36 -060014{
Marshall Dawson21c5e152017-12-15 11:13:54 -070015 void *BiosManagerPtr = agesa_heap_base();
Marc Jones21cde8b2017-05-07 16:47:36 -060016 memset(BiosManagerPtr, 0, BIOS_HEAP_SIZE);
17}
18
Richard Spiegel51895d12018-04-17 14:25:26 -070019/*
Marshall Dawson10b52e02018-05-07 08:51:04 -060020 * Name agesa_GetTempHeapBase
21 * Brief description Get the location for TempRam, the target location in
22 * memory where AmdInitPost copies the heap prior to CAR
23 * teardown. AmdInitEnv calls this function after
24 * teardown for the source address when relocation the
25 * heap to its final location.
26 * Input parameters
27 * Func Unused
28 * Data Unused
29 * ConfigPtr Pointer to type AGESA_TEMP_HEAP_BASE_PARAMS
30 * Output parameters
31 * Status Indicates whether TempHeapAddress was successfully
32 * set.
33 */
Richard Spiegel271b8a52018-11-06 16:32:28 -070034AGESA_STATUS agesa_GetTempHeapBase(uint32_t Func, uintptr_t Data,
35 void *ConfigPtr)
Marshall Dawson10b52e02018-05-07 08:51:04 -060036{
37 AGESA_TEMP_HEAP_BASE_PARAMS *pTempHeapBase;
38
39 pTempHeapBase = (AGESA_TEMP_HEAP_BASE_PARAMS *)ConfigPtr;
40 pTempHeapBase->TempHeapAddress = CONFIG_PI_AGESA_TEMP_RAM_BASE;
41
42 return AGESA_SUCCESS;
43}
44
45/*
Marshall Dawsonc150a572018-04-30 17:59:27 -060046 * Name agesa_HeapRebase
47 * Brief description AGESA may use internal hardcoded locations for its
48 * heap. Modern implementations allow the base to be
49 * overridden by calling agesa_HeapRebase.
50 * Input parameters
51 * Func Unused
52 * Data Unused
53 * ConfigPtr Pointer to type AGESA_REBASE_PARAMS
54 * Output parameters
55 * Status Indicates whether HeapAddress was successfully
56 * set.
57 */
Richard Spiegel271b8a52018-11-06 16:32:28 -070058AGESA_STATUS agesa_HeapRebase(uint32_t Func, uintptr_t Data, void *ConfigPtr)
Marshall Dawsonc150a572018-04-30 17:59:27 -060059{
60 AGESA_REBASE_PARAMS *Rebase;
61
62 Rebase = (AGESA_REBASE_PARAMS *)ConfigPtr;
Richard Spiegel271b8a52018-11-06 16:32:28 -070063 Rebase->HeapAddress = (uintptr_t)agesa_heap_base();
Marshall Dawson418c2bb2018-06-27 10:45:33 -060064 if (!Rebase->HeapAddress)
Marshall Dawsonc150a572018-04-30 17:59:27 -060065 Rebase->HeapAddress = CONFIG_PI_AGESA_CAR_HEAP_BASE;
Marshall Dawsonc150a572018-04-30 17:59:27 -060066
67 return AGESA_SUCCESS;
68}
69
70/*
Richard Spiegel51895d12018-04-17 14:25:26 -070071 * Name FindAllocatedNode
72 * Brief description Find an allocated node that matches the handle.
73 * Input parameter The desired handle.
74 * Output parameters
75 * pointer Here is returned either the found node or the last
76 * allocated node if the handle is not found. This is
77 * intentional, as the field NextNode of this node will
78 * have to be filled with the offset of the node being
79 * created in procedure agesa_AllocateBuffer().
80 * Status Indicates if the node was or was not found.
81 */
82static AGESA_STATUS FindAllocatedNode(uint32_t handle,
83 BIOS_BUFFER_NODE **last_allocd_or_match)
84{
Richard Spiegel271b8a52018-11-06 16:32:28 -070085 uint32_t AllocNodeOffset;
86 uint8_t *BiosHeapBaseAddr;
Richard Spiegel51895d12018-04-17 14:25:26 -070087 BIOS_BUFFER_NODE *AllocNodePtr;
88 BIOS_HEAP_MANAGER *BiosHeapBasePtr;
89 AGESA_STATUS Status = AGESA_SUCCESS;
90
91 BiosHeapBaseAddr = agesa_heap_base();
92 BiosHeapBasePtr = (BIOS_HEAP_MANAGER *)BiosHeapBaseAddr;
93
94 AllocNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes;
95 AllocNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + AllocNodeOffset);
96
97 while (handle != AllocNodePtr->BufferHandle) {
98 if (AllocNodePtr->NextNodeOffset == 0) {
99 Status = AGESA_BOUNDS_CHK;
100 break;
101 }
102 AllocNodeOffset = AllocNodePtr->NextNodeOffset;
103 AllocNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr +
104 AllocNodeOffset);
105 }
106 *last_allocd_or_match = AllocNodePtr;
107 return Status;
108}
109
110/*
111 * Name ConcatenateNodes
112 * Brief description Concatenates two adjacent nodes into a single node,
113 * this procedure is used by agesa_DeallocateBuffer().
114 * Input parameters
115 * FirstNodePtr This node is in the front, its header will be
116 * maintained.
117 * SecondNodePtr This node is in the back, its header will be cleared.
118 */
119static void ConcatenateNodes(BIOS_BUFFER_NODE *FirstNodePtr,
120 BIOS_BUFFER_NODE *SecondNodePtr)
121{
122 FirstNodePtr->BufferSize += SecondNodePtr->BufferSize +
123 sizeof(BIOS_BUFFER_NODE);
124 FirstNodePtr->NextNodeOffset = SecondNodePtr->NextNodeOffset;
125
126 /* Zero out the SecondNode header */
127 memset(SecondNodePtr, 0, sizeof(BIOS_BUFFER_NODE));
128}
129
Kyösti Mälkkifa3bc042022-03-31 07:40:10 +0300130CBMEM_CREATION_HOOK(EmptyHeap);
Marshall Dawson6c747062017-09-21 12:21:14 -0600131
Richard Spiegel271b8a52018-11-06 16:32:28 -0700132AGESA_STATUS agesa_AllocateBuffer(uint32_t Func, uintptr_t Data,
133 void *ConfigPtr)
Marc Jones21cde8b2017-05-07 16:47:36 -0600134{
Richard Spiegel51895d12018-04-17 14:25:26 -0700135 /*
136 * Size variables explanation:
137 * FreedNodeSize - the size of the buffer node being examined,
138 * will be copied to BestFitNodeSize if the node
139 * is selected as a possible best fit.
140 * BestFitNodeSize - the size qf the buffer of the node currently
141 * considered the best fit.
142 * MinimumSize - the requested size + sizeof(BIOS_BUFFER_NODE).
143 * Its the minimum size for the buffer to be broken
144 * down into 2 nodes, once a node is selected as
145 * the best fit.
146 */
Richard Spiegel271b8a52018-11-06 16:32:28 -0700147 uint32_t AvailableHeapSize;
148 uint8_t *BiosHeapBaseAddr;
149 uint32_t CurrNodeOffset;
150 uint32_t PrevNodeOffset;
151 uint32_t FreedNodeOffset;
152 uint32_t FreedNodeSize;
153 uint32_t BestFitNodeOffset;
154 uint32_t BestFitNodeSize;
155 uint32_t BestFitPrevNodeOffset;
156 uint32_t NextFreeOffset;
157 uint32_t MinimumSize;
Marc Jones21cde8b2017-05-07 16:47:36 -0600158 BIOS_BUFFER_NODE *CurrNodePtr;
159 BIOS_BUFFER_NODE *FreedNodePtr;
160 BIOS_BUFFER_NODE *BestFitNodePtr;
161 BIOS_BUFFER_NODE *BestFitPrevNodePtr;
162 BIOS_BUFFER_NODE *NextFreePtr;
163 BIOS_HEAP_MANAGER *BiosHeapBasePtr;
164 AGESA_BUFFER_PARAMS *AllocParams;
Richard Spiegel51895d12018-04-17 14:25:26 -0700165 AGESA_STATUS Status;
Marc Jones21cde8b2017-05-07 16:47:36 -0600166
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600167 AllocParams = ((AGESA_BUFFER_PARAMS *)ConfigPtr);
Marc Jones21cde8b2017-05-07 16:47:36 -0600168 AllocParams->BufferPointer = NULL;
Richard Spiegel51895d12018-04-17 14:25:26 -0700169 MinimumSize = AllocParams->BufferLength + sizeof(BIOS_BUFFER_NODE);
Marc Jones21cde8b2017-05-07 16:47:36 -0600170
171 AvailableHeapSize = BIOS_HEAP_SIZE - sizeof(BIOS_HEAP_MANAGER);
Richard Spiegel51895d12018-04-17 14:25:26 -0700172 BestFitNodeSize = AvailableHeapSize; /* init with largest possible */
Marshall Dawson21c5e152017-12-15 11:13:54 -0700173 BiosHeapBaseAddr = agesa_heap_base();
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600174 BiosHeapBasePtr = (BIOS_HEAP_MANAGER *)BiosHeapBaseAddr;
Marc Jones21cde8b2017-05-07 16:47:36 -0600175
176 if (BiosHeapBasePtr->StartOfAllocatedNodes == 0) {
177 /* First allocation */
178 CurrNodeOffset = sizeof(BIOS_HEAP_MANAGER);
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600179 CurrNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr
180 + CurrNodeOffset);
Marc Jones21cde8b2017-05-07 16:47:36 -0600181 CurrNodePtr->BufferHandle = AllocParams->BufferHandle;
182 CurrNodePtr->BufferSize = AllocParams->BufferLength;
183 CurrNodePtr->NextNodeOffset = 0;
Richard Spiegel271b8a52018-11-06 16:32:28 -0700184 AllocParams->BufferPointer = (uint8_t *)CurrNodePtr
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600185 + sizeof(BIOS_BUFFER_NODE);
Marc Jones21cde8b2017-05-07 16:47:36 -0600186
187 /* Update the remaining free space */
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600188 FreedNodeOffset = CurrNodeOffset + CurrNodePtr->BufferSize
189 + sizeof(BIOS_BUFFER_NODE);
190 FreedNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr
191 + FreedNodeOffset);
192 FreedNodePtr->BufferSize = AvailableHeapSize
Marc Jonese6033ce2018-01-15 18:47:24 -0700193 - (FreedNodeOffset - CurrNodeOffset)
194 - sizeof(BIOS_BUFFER_NODE);
Marc Jones21cde8b2017-05-07 16:47:36 -0600195 FreedNodePtr->NextNodeOffset = 0;
196
197 /* Update the offsets for Allocated and Freed nodes */
198 BiosHeapBasePtr->StartOfAllocatedNodes = CurrNodeOffset;
199 BiosHeapBasePtr->StartOfFreedNodes = FreedNodeOffset;
200 } else {
Richard Spiegel51895d12018-04-17 14:25:26 -0700201 /*
202 * Find out whether BufferHandle has been allocated on the heap.
Marc Jones21cde8b2017-05-07 16:47:36 -0600203 * If it has, return AGESA_BOUNDS_CHK.
204 */
Richard Spiegel51895d12018-04-17 14:25:26 -0700205 Status = FindAllocatedNode(AllocParams->BufferHandle,
206 &CurrNodePtr);
207 if (Status == AGESA_SUCCESS)
208 return AGESA_BOUNDS_CHK;
Marc Jones21cde8b2017-05-07 16:47:36 -0600209
Richard Spiegel51895d12018-04-17 14:25:26 -0700210 /*
211 * If status ditn't returned AGESA_SUCCESS, CurrNodePtr here
212 * points to the end of the allocated nodes list.
213 */
214
Marc Jones21cde8b2017-05-07 16:47:36 -0600215 /* Find the node that best fits the requested buffer size */
216 FreedNodeOffset = BiosHeapBasePtr->StartOfFreedNodes;
217 PrevNodeOffset = FreedNodeOffset;
218 BestFitNodeOffset = 0;
219 BestFitPrevNodeOffset = 0;
Richard Spiegel51895d12018-04-17 14:25:26 -0700220 while (FreedNodeOffset != 0) {
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600221 FreedNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr
222 + FreedNodeOffset);
Richard Spiegel51895d12018-04-17 14:25:26 -0700223 FreedNodeSize = FreedNodePtr->BufferSize;
224 if (FreedNodeSize >= MinimumSize) {
Marc Jones21cde8b2017-05-07 16:47:36 -0600225 if (BestFitNodeOffset == 0) {
Richard Spiegelfc511272017-12-11 16:23:58 -0700226 /*
227 * First node that fits the requested
228 * buffer size
229 */
Marc Jones21cde8b2017-05-07 16:47:36 -0600230 BestFitNodeOffset = FreedNodeOffset;
231 BestFitPrevNodeOffset = PrevNodeOffset;
Richard Spiegel51895d12018-04-17 14:25:26 -0700232 BestFitNodeSize = FreedNodeSize;
Marc Jones21cde8b2017-05-07 16:47:36 -0600233 } else {
Richard Spiegelfc511272017-12-11 16:23:58 -0700234 /*
235 * Find out whether current node is a
236 * betterfit than the previous nodes
237 */
Richard Spiegel51895d12018-04-17 14:25:26 -0700238 if (BestFitNodeSize > FreedNodeSize) {
Richard Spiegelfc511272017-12-11 16:23:58 -0700239 BestFitNodeOffset =
240 FreedNodeOffset;
241 BestFitPrevNodeOffset =
242 PrevNodeOffset;
Richard Spiegel51895d12018-04-17 14:25:26 -0700243 BestFitNodeSize = FreedNodeSize;
Marc Jones21cde8b2017-05-07 16:47:36 -0600244 }
245 }
246 }
247 PrevNodeOffset = FreedNodeOffset;
248 FreedNodeOffset = FreedNodePtr->NextNodeOffset;
249 } /* end of while loop */
250
251 if (BestFitNodeOffset == 0) {
Richard Spiegelfc511272017-12-11 16:23:58 -0700252 /*
253 * If we could not find a node that fits the requested
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600254 * buffer size, return AGESA_BOUNDS_CHK.
Marc Jones21cde8b2017-05-07 16:47:36 -0600255 */
256 return AGESA_BOUNDS_CHK;
Marc Jones21cde8b2017-05-07 16:47:36 -0600257 }
Richard Spiegelfc511272017-12-11 16:23:58 -0700258
259 BestFitNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr
260 + BestFitNodeOffset);
Elyes Haouas68fc51f2022-07-16 09:48:27 +0200261 BestFitPrevNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr +
Richard Spiegelfc511272017-12-11 16:23:58 -0700262 BestFitPrevNodeOffset);
263
264 /*
Marc Jonesa2737532018-01-12 16:52:29 +0000265 * If BestFitNode is larger than the requested buffer,
266 * fragment the node further
Richard Spiegelfc511272017-12-11 16:23:58 -0700267 */
Richard Spiegel51895d12018-04-17 14:25:26 -0700268 if (BestFitNodePtr->BufferSize > MinimumSize) {
269 NextFreeOffset = BestFitNodeOffset + MinimumSize;
Elyes Haouas68fc51f2022-07-16 09:48:27 +0200270 NextFreePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr +
Richard Spiegelfc511272017-12-11 16:23:58 -0700271 NextFreeOffset);
Richard Spiegel51895d12018-04-17 14:25:26 -0700272 NextFreePtr->BufferSize = BestFitNodeSize - MinimumSize;
273
274 /* Remove BestFitNode from list of Freed nodes */
Richard Spiegelfc511272017-12-11 16:23:58 -0700275 NextFreePtr->NextNodeOffset =
276 BestFitNodePtr->NextNodeOffset;
277 } else {
278 /*
Richard Spiegel51895d12018-04-17 14:25:26 -0700279 * Otherwise, next free node is NextNodeOffset of
280 * BestFitNode. Remove it from list of Freed nodes.
Richard Spiegelfc511272017-12-11 16:23:58 -0700281 */
282 NextFreeOffset = BestFitNodePtr->NextNodeOffset;
283 }
284
285 /*
286 * If BestFitNode is the first buffer in the list, then
287 * update StartOfFreedNodes to reflect new free node.
288 */
289 if (BestFitNodeOffset == BiosHeapBasePtr->StartOfFreedNodes)
290 BiosHeapBasePtr->StartOfFreedNodes = NextFreeOffset;
291 else
292 BestFitPrevNodePtr->NextNodeOffset = NextFreeOffset;
293
294 /* Add BestFitNode to the list of Allocated nodes */
295 CurrNodePtr->NextNodeOffset = BestFitNodeOffset;
296 BestFitNodePtr->BufferSize = AllocParams->BufferLength;
297 BestFitNodePtr->BufferHandle = AllocParams->BufferHandle;
298 BestFitNodePtr->NextNodeOffset = 0;
299
Richard Spiegel271b8a52018-11-06 16:32:28 -0700300 AllocParams->BufferPointer = (uint8_t *)BestFitNodePtr +
Richard Spiegelfc511272017-12-11 16:23:58 -0700301 sizeof(BIOS_BUFFER_NODE);
Marc Jones21cde8b2017-05-07 16:47:36 -0600302 }
303
304 return AGESA_SUCCESS;
305}
306
Richard Spiegel271b8a52018-11-06 16:32:28 -0700307AGESA_STATUS agesa_DeallocateBuffer(uint32_t Func, uintptr_t Data,
308 void *ConfigPtr)
Marc Jones21cde8b2017-05-07 16:47:36 -0600309{
Richard Spiegel271b8a52018-11-06 16:32:28 -0700310 uint8_t *BiosHeapBaseAddr;
311 uint32_t AllocNodeOffset;
312 uint32_t PrevNodeOffset;
313 uint32_t NextNodeOffset;
314 uint32_t FreedNodeOffset;
315 uint32_t EndNodeOffset;
Marc Jones21cde8b2017-05-07 16:47:36 -0600316 BIOS_BUFFER_NODE *AllocNodePtr;
317 BIOS_BUFFER_NODE *PrevNodePtr;
318 BIOS_BUFFER_NODE *FreedNodePtr;
319 BIOS_BUFFER_NODE *NextNodePtr;
320 BIOS_HEAP_MANAGER *BiosHeapBasePtr;
321 AGESA_BUFFER_PARAMS *AllocParams;
322
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600323 AllocParams = (AGESA_BUFFER_PARAMS *)ConfigPtr;
Marc Jones21cde8b2017-05-07 16:47:36 -0600324
Marshall Dawson21c5e152017-12-15 11:13:54 -0700325 BiosHeapBaseAddr = agesa_heap_base();
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600326 BiosHeapBasePtr = (BIOS_HEAP_MANAGER *)BiosHeapBaseAddr;
Marc Jones21cde8b2017-05-07 16:47:36 -0600327
328 /* Find target node to deallocate in list of allocated nodes.
329 * Return AGESA_BOUNDS_CHK if the BufferHandle is not found.
330 */
331 AllocNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes;
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600332 AllocNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + AllocNodeOffset);
Marc Jones21cde8b2017-05-07 16:47:36 -0600333 PrevNodeOffset = AllocNodeOffset;
334
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600335 while (AllocNodePtr->BufferHandle != AllocParams->BufferHandle) {
336 if (AllocNodePtr->NextNodeOffset == 0)
Marc Jones21cde8b2017-05-07 16:47:36 -0600337 return AGESA_BOUNDS_CHK;
Marc Jones21cde8b2017-05-07 16:47:36 -0600338 PrevNodeOffset = AllocNodeOffset;
339 AllocNodeOffset = AllocNodePtr->NextNodeOffset;
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600340 AllocNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr
341 + AllocNodeOffset);
Marc Jones21cde8b2017-05-07 16:47:36 -0600342 }
343
344 /* Remove target node from list of allocated nodes */
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600345 PrevNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + PrevNodeOffset);
Marc Jones21cde8b2017-05-07 16:47:36 -0600346 PrevNodePtr->NextNodeOffset = AllocNodePtr->NextNodeOffset;
347
348 /* Zero out the buffer, and clear the BufferHandle */
Richard Spiegel271b8a52018-11-06 16:32:28 -0700349 memset((uint8_t *)AllocNodePtr + sizeof(BIOS_BUFFER_NODE), 0,
Aaron Durbine3f7d442017-11-03 11:44:10 -0600350 AllocNodePtr->BufferSize);
Marc Jones21cde8b2017-05-07 16:47:36 -0600351 AllocNodePtr->BufferHandle = 0;
Marc Jones21cde8b2017-05-07 16:47:36 -0600352
353 /* Add deallocated node in order to the list of freed nodes */
354 FreedNodeOffset = BiosHeapBasePtr->StartOfFreedNodes;
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600355 FreedNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr + FreedNodeOffset);
Marc Jones21cde8b2017-05-07 16:47:36 -0600356
Marc Jonese6033ce2018-01-15 18:47:24 -0700357 EndNodeOffset = AllocNodeOffset + AllocNodePtr->BufferSize +
358 sizeof(BIOS_BUFFER_NODE);
Marc Jones21cde8b2017-05-07 16:47:36 -0600359
360 if (AllocNodeOffset < FreedNodeOffset) {
361 /* Add to the start of the freed list */
362 if (EndNodeOffset == FreedNodeOffset) {
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600363 /* If the freed node is adjacent to the first node in
364 * the list, concatenate both nodes
365 */
Richard Spiegel51895d12018-04-17 14:25:26 -0700366 ConcatenateNodes(AllocNodePtr, FreedNodePtr);
Marc Jones21cde8b2017-05-07 16:47:36 -0600367 } else {
368 /* Otherwise, add freed node to the start of the list
369 * Update NextNodeOffset and BufferSize to include the
370 * size of BIOS_BUFFER_NODE.
371 */
372 AllocNodePtr->NextNodeOffset = FreedNodeOffset;
373 }
374 /* Update StartOfFreedNodes to the new first node */
375 BiosHeapBasePtr->StartOfFreedNodes = AllocNodeOffset;
376 } else {
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600377 /* Traverse list of freed nodes to find where the deallocated
378 * node should be placed.
Marc Jones21cde8b2017-05-07 16:47:36 -0600379 */
380 NextNodeOffset = FreedNodeOffset;
381 NextNodePtr = FreedNodePtr;
382 while (AllocNodeOffset > NextNodeOffset) {
383 PrevNodeOffset = NextNodeOffset;
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600384 if (NextNodePtr->NextNodeOffset == 0)
Marc Jones21cde8b2017-05-07 16:47:36 -0600385 break;
Marc Jones21cde8b2017-05-07 16:47:36 -0600386 NextNodeOffset = NextNodePtr->NextNodeOffset;
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600387 NextNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr
388 + NextNodeOffset);
Marc Jones21cde8b2017-05-07 16:47:36 -0600389 }
390
391 /* If deallocated node is adjacent to the next node,
392 * concatenate both nodes.
393 */
394 if (NextNodeOffset == EndNodeOffset) {
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600395 NextNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr
396 + NextNodeOffset);
Richard Spiegel51895d12018-04-17 14:25:26 -0700397 ConcatenateNodes(AllocNodePtr, NextNodePtr);
Marc Jones21cde8b2017-05-07 16:47:36 -0600398 } else {
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600399 /*AllocNodePtr->NextNodeOffset =
Elyes HAOUAS05498a22018-05-28 16:26:43 +0200400 * FreedNodePtr->NextNodeOffset; */
Marc Jones21cde8b2017-05-07 16:47:36 -0600401 AllocNodePtr->NextNodeOffset = NextNodeOffset;
402 }
Richard Spiegelfc511272017-12-11 16:23:58 -0700403 /*
404 * If deallocated node is adjacent to the previous node,
Marc Jones21cde8b2017-05-07 16:47:36 -0600405 * concatenate both nodes.
406 */
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600407 PrevNodePtr = (BIOS_BUFFER_NODE *)(BiosHeapBaseAddr
408 + PrevNodeOffset);
Marc Jonese6033ce2018-01-15 18:47:24 -0700409 EndNodeOffset = PrevNodeOffset + PrevNodePtr->BufferSize +
410 sizeof(BIOS_BUFFER_NODE);
411
Richard Spiegel51895d12018-04-17 14:25:26 -0700412 if (AllocNodeOffset == EndNodeOffset)
413 ConcatenateNodes(PrevNodePtr, AllocNodePtr);
414 else
Marc Jones21cde8b2017-05-07 16:47:36 -0600415 PrevNodePtr->NextNodeOffset = AllocNodeOffset;
Marc Jones21cde8b2017-05-07 16:47:36 -0600416 }
417 return AGESA_SUCCESS;
418}
419
Richard Spiegel271b8a52018-11-06 16:32:28 -0700420AGESA_STATUS agesa_LocateBuffer(uint32_t Func, uintptr_t Data, void *ConfigPtr)
Marc Jones21cde8b2017-05-07 16:47:36 -0600421{
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600422 BIOS_BUFFER_NODE *AllocNodePtr;
Marc Jones21cde8b2017-05-07 16:47:36 -0600423 AGESA_BUFFER_PARAMS *AllocParams;
Richard Spiegel51895d12018-04-17 14:25:26 -0700424 AGESA_STATUS Status;
Marc Jones21cde8b2017-05-07 16:47:36 -0600425
Marshall Dawsonf3dc71e2017-06-14 16:22:07 -0600426 AllocParams = (AGESA_BUFFER_PARAMS *)ConfigPtr;
Marc Jones21cde8b2017-05-07 16:47:36 -0600427
Richard Spiegel51895d12018-04-17 14:25:26 -0700428 Status = FindAllocatedNode(AllocParams->BufferHandle, &AllocNodePtr);
Marc Jones21cde8b2017-05-07 16:47:36 -0600429
Richard Spiegel51895d12018-04-17 14:25:26 -0700430 if (Status == AGESA_SUCCESS) {
Richard Spiegel271b8a52018-11-06 16:32:28 -0700431 AllocParams->BufferPointer = (uint8_t *)((uint8_t *)AllocNodePtr
Richard Spiegel51895d12018-04-17 14:25:26 -0700432 + sizeof(BIOS_BUFFER_NODE));
433 AllocParams->BufferLength = AllocNodePtr->BufferSize;
Marc Jones21cde8b2017-05-07 16:47:36 -0600434 }
435
Richard Spiegel51895d12018-04-17 14:25:26 -0700436 return Status;
Marc Jones21cde8b2017-05-07 16:47:36 -0600437}