From 41eaf2dba315dabb51b5c6a77b083165187ebb18 Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Sat, 23 Mar 2024 15:47:39 +0100
Subject: soc/amd/non_car/memlayout_x86.ld: Top align the code

This does the following:
- Top align the bootblock so that the only the memory needed gets used.
  This might slightly reduce the time the PSP needs to decompress the
  bootblock in memory
- Use a memory directive to assert that the 16bit code is inside the top
  64K segment
- Use the program counter less. While the BDF linker is happy about
  running the program counter backwards, LLD is not. There is no
  downside to this.
- Use a symbol rather that the program counter for sections. LLD gets
  confused when (.) is used along with '<': it places the section at the
  start of the memory region, rather than at the program counter. Using
  a variable name works around this.
- Use a 'last_byte' section to make sure the first instruction is at
  0xfff0. Both the BDF and the LLD linkers seems to work well with this
  code

TEST: Both BFD and LLD are able to link the bootblock

Change-Id: I18bdf262f9c358aa01795b11efcb863686edc79c
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/81433
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin L Roth <gaumless@gmail.com>
---
 .../amd/common/block/cpu/noncar/memlayout_x86.ld   | 34 ++++++++++++++--------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/src/soc/amd/common/block/cpu/noncar/memlayout_x86.ld b/src/soc/amd/common/block/cpu/noncar/memlayout_x86.ld
index 9eb9d21ce6..3c596f4c20 100644
--- a/src/soc/amd/common/block/cpu/noncar/memlayout_x86.ld
+++ b/src/soc/amd/common/block/cpu/noncar/memlayout_x86.ld
@@ -95,7 +95,6 @@ SECTIONS
 	PSP_SHAREDMEM_DRAM_END(CONFIG_PSP_SHAREDMEM_BASE + CONFIG_PSP_SHAREDMEM_SIZE)
 #endif
 	_ = ASSERT(BOOTBLOCK_END == ((BOOTBLOCK_END + 0xFFFF) & 0xFFFF0000), "Bootblock end must be 16 bit aligned");
-	BOOTBLOCK(BOOTBLOCK_ADDR, CONFIG_C_ENV_BOOTBLOCK_SIZE)
 	ROMSTAGE(CONFIG_ROMSTAGE_ADDR, CONFIG_ROMSTAGE_SIZE)
 
 #if CONFIG(PLATFORM_USES_FSP2_0)
@@ -124,19 +123,29 @@ SECTIONS
 gdtptr_offset = gdtptr & 0xffff;
 nullidt_offset = nullidt & 0xffff;
 
+MEMORY
+{
+	/* Make sure all the 16bit code is in the same 64K segment as the reset vector */
+	resetsection (rwx) : ORIGIN = BOOTBLOCK_END - 64K, LENGTH = 64K
+}
+
 SECTIONS {
-	/* Trigger an error if I have an unusable start address */
-	_TOO_LOW = _X86_RESET_VECTOR - 0xfff0;
-	_bogus = ASSERT(_start16bit >= _TOO_LOW, "_start16bit too low. Please report.");
+	/* Page tables need to be at a 4K boundary so align the bootblock downwards */
+	. = (BOOTBLOCK_TOP - PROGRAM_SZ) & ~(4096 - 1);
+	_bootblock = .;
+
+	INCLUDE "bootblock/lib/program.ld"
+
+	PROGRAM_SZ = SIZEOF(.text) + SIZEOF(.bss) + SIZEOF(.data);
 
 	. = _X86_RESET_VECTOR - EARLYASM_SZ;
 	. = ALIGN(16);
 	BOOTBLOCK_TOP = .;
-	.init (.) : {
+	.init BOOTBLOCK_TOP : {
 		*(.init._start);
 		*(.init);
 		*(.init.*);
-	}
+	} >resetsection
 
 	/*
 	 * Allocation reserves extra space here. Alignment requirements
@@ -145,13 +154,14 @@ SECTIONS {
 	 */
 	EARLYASM_SZ = SIZEOF(.init) + 16;
 
-	. = BOOTBLOCK_END - 0x10;
-	_X86_RESET_VECTOR = .;
+	_X86_RESET_VECTOR = BOOTBLOCK_END - 0x10;
 	_bogus = ASSERT((_X86_RESET_VECTOR & 0xffff) == 0xfff0, "IP needs to be 0xfff0");
-	.reset . : {
+	.reset (_X86_RESET_VECTOR) : {
 		*(.reset);
-		. = 15;
-		BYTE(0x00);
-	}
+	} >resetsection
+	.last_byte (BOOTBLOCK_END - 1) : {
+		BYTE(0xff);
+	} >resetsection
+	_ebootblock = BOOTBLOCK_END;
 }
 #endif  /* ENV_BOOTBLOCK */
-- 
cgit v1.2.3