memrange: Honor `limit` in the last step of top-down stealing

We only checked that the resource fits below the given `limit` in
memranges_find_entry(), but then accidentally placed it at the top
of the found memrange. As most resources have only a coarse limit,
e.g. the 4G barrier of 32-bit space, this became only visible when
artificially setting an unusual, lower limit on a resource.

So, for the final placement, use `MIN(limit, range end)` instead
of the range's end alone.

Change-Id: I3cc62ac3d427683c00ba0ac9f991fca62e99ce44
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/76480
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin L Roth <gaumless@gmail.com>
diff --git a/src/lib/memrange.c b/src/lib/memrange.c
index b68b86e..9ae3e3e 100644
--- a/src/lib/memrange.c
+++ b/src/lib/memrange.c
@@ -427,11 +427,12 @@
 		return false;
 
 	if (from_top) {
+		limit = MIN(limit, r->end);
 		/* Ensure we're within the range, even aligned down.
 		   Proof is simple: If ALIGN_UP(r->begin) would be
 		   higher, the stolen range wouldn't fit.*/
-		assert(r->begin <= ALIGN_DOWN(range_entry_end(r) - size, POWER_OF_2(align)));
-		*stolen_base = ALIGN_DOWN(range_entry_end(r) - size, POWER_OF_2(align));
+		assert(r->begin <= ALIGN_DOWN(limit - size + 1, POWER_OF_2(align)));
+		*stolen_base = ALIGN_DOWN(limit - size + 1, POWER_OF_2(align));
 	} else {
 		*stolen_base = ALIGN_UP(r->begin, POWER_OF_2(align));
 	}