summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Jones <marcj303@gmail.com>2018-01-10 16:41:46 -0800
committerMarc Jones <marc@marcjonesconsulting.com>2018-01-12 01:46:58 +0000
commitca966f9a2df171848e57f4deac0dda6ce24cc938 (patch)
treed31505e79bb3c3e0264f541ab2260343c923d388
parent3441292ecda5e76a98ff63f55fc45d010fc76188 (diff)
downloadcoreboot-ca966f9a2df171848e57f4deac0dda6ce24cc938.tar.xz
soc/amd/common/pi: Fix issue in AGESA heap allocator
The heap allocator would try to split a buffer node that was too small for another node. In the failing case, the buffer node was 0x140 bytes and the requested size was 0x133 bytes. The logic would check that there was room for the header and buffer and try to split the buffer node. The buffer node header is 0xC bytes, so 0x13F bytes are need. The problem is that it didn't leave room for another node header and a little space for a buffer. BUG=b:71764350 TEST= Boot grunt. BRANCH=none Change-Id: Iece5e12d5787415a335bb953985331a5dc312152 Signed-off-by: Marc Jones <marcj303@gmail.com> Reviewed-on: https://review.coreboot.org/23211 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Martin Roth <martinroth@google.com> Reviewed-by: Daniel Kurtz <djkurtz@google.com>
-rw-r--r--src/soc/amd/common/block/include/amdblocks/BiosCallOuts.h2
-rw-r--r--src/soc/amd/common/block/pi/heapmanager.c9
2 files changed, 7 insertions, 4 deletions
diff --git a/src/soc/amd/common/block/include/amdblocks/BiosCallOuts.h b/src/soc/amd/common/block/include/amdblocks/BiosCallOuts.h
index 2302889e6b..87856003f3 100644
--- a/src/soc/amd/common/block/include/amdblocks/BiosCallOuts.h
+++ b/src/soc/amd/common/block/include/amdblocks/BiosCallOuts.h
@@ -34,6 +34,8 @@ typedef struct _BIOS_BUFFER_NODE {
UINT32 NextNodeOffset;
} BIOS_BUFFER_NODE;
+#define MIN_BUFFER_NODE_SIZE (sizeof(BIOS_BUFFER_NODE) + sizeof(uint32_t))
+
AGESA_STATUS agesa_AllocateBuffer(UINT32 Func, UINTN Data, VOID *ConfigPtr);
AGESA_STATUS agesa_DeallocateBuffer(UINT32 Func, UINTN Data, VOID *ConfigPtr);
AGESA_STATUS agesa_LocateBuffer(UINT32 Func, UINTN Data, VOID *ConfigPtr);
diff --git a/src/soc/amd/common/block/pi/heapmanager.c b/src/soc/amd/common/block/pi/heapmanager.c
index cea3171aa5..d149e9144f 100644
--- a/src/soc/amd/common/block/pi/heapmanager.c
+++ b/src/soc/amd/common/block/pi/heapmanager.c
@@ -159,11 +159,12 @@ AGESA_STATUS agesa_AllocateBuffer (UINT32 Func, UINTN Data, VOID *ConfigPtr)
BestFitPrevNodeOffset);
/*
- * If BestFitNode is larger than the requested buffer,
- * fragment the node further
+ * If BestFitNode is larger than the requested buffer and
+ * has room for another buffer node, fragment the node further.
*/
- if (BestFitNodePtr->BufferSize >
- (AllocParams->BufferLength + sizeof(BIOS_BUFFER_NODE))) {
+ if (BestFitNodePtr->BufferSize >=
+ (AllocParams->BufferLength + sizeof(BIOS_BUFFER_NODE) +
+ MIN_BUFFER_NODE_SIZE)) {
NextFreeOffset = BestFitNodeOffset +
AllocParams->BufferLength +
sizeof(BIOS_BUFFER_NODE);