amdfwtool: Use relative address for EFS gen2

The second generation EFS (offset 0x24[0]=0) uses "binary relative"
offsets and not "x86 physical MMIO address" like gen1.

The field additional_info in table header can tell if the absolute or
relative address is used.

Chips like Cezanne can run in both cases, so no problem
comes up so far.

The related change in psp_verstage has been uploaded.
https://review.coreboot.org/c/coreboot/+/58316

The relative mode is the mode 1 of four address modes. The absolute
mode is the mode 0. Later we will implement mode 2. Not sure if mode 3
is needed.

It needs to be simple to work with psp_verstage change to make SOC
Cezanne work quickly. This patch is defacto a subset of
    https://review.coreboot.org/c/coreboot/+/59308
which implements the framework of address mode and covers mode
0,1,2. Some hardcode value like 29 can be removed in 59308.

BUG=b:188754219
Test=Majolica (Cezanne)

Change-Id: I7701c7819f03586d4ecab3d744056c8c902b630f
Signed-off-by: Zheng Bao <fishbaozi@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/56438
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Kangheui Won <khwon@chromium.org>
Reviewed-by: Karthik Ramasubramanian <kramasub@google.com>
diff --git a/util/amdfwtool/amdfwtool.c b/util/amdfwtool/amdfwtool.c
index 98e3189..d8cda92 100644
--- a/util/amdfwtool/amdfwtool.c
+++ b/util/amdfwtool/amdfwtool.c
@@ -343,11 +343,12 @@
 typedef struct _context {
 	char *rom;		/* target buffer, size of flash device */
 	uint32_t rom_size;	/* size of flash device */
+	uint32_t abs_address;	/* produce absolute or relative address */
 	uint32_t current;	/* pointer within flash & proxy buffer */
 } context;
 
 #define RUN_BASE(ctx) (0xFFFFFFFF - (ctx).rom_size + 1)
-#define RUN_OFFSET(ctx, offset) (RUN_BASE(ctx) + (offset))
+#define RUN_OFFSET(ctx, offset) ((ctx).abs_address ? RUN_BASE(ctx) + (offset) : (offset))
 #define RUN_CURRENT(ctx) RUN_OFFSET((ctx), (ctx).current)
 #define BUFF_OFFSET(ctx, offset) ((void *)((ctx).rom + (offset)))
 #define BUFF_CURRENT(ctx) BUFF_OFFSET((ctx), (ctx).current)
@@ -439,6 +440,8 @@
 		dir->header.cookie = cookie;
 		dir->header.num_entries = count;
 		dir->header.additional_info = (table_size / 0x1000) | (1 << 10);
+		if (ctx->abs_address == 0)
+			dir->header.additional_info |= 1 << 29;
 		/* checksum everything that comes after the Checksum field */
 		dir->header.checksum = fletcher32(&dir->header.num_entries,
 					count * sizeof(psp_directory_entry)
@@ -455,6 +458,8 @@
 		bdir->header.cookie = cookie;
 		bdir->header.num_entries = count;
 		bdir->header.additional_info = (table_size / 0x1000) | (1 << 10);
+		if (ctx->abs_address == 0)
+			bdir->header.additional_info |= 1 << 29;
 		/* checksum everything that comes after the Checksum field */
 		bdir->header.checksum = fletcher32(&bdir->header.num_entries,
 					count * sizeof(bios_directory_entry)
@@ -1576,8 +1581,6 @@
 		romsig_offset = ctx.current = dir_location - rom_base_address;
 	else
 		romsig_offset = ctx.current = AMD_ROMSIG_OFFSET;
-	printf("    AMDFWTOOL  Using firmware directory location of 0x%08x\n",
-			RUN_CURRENT(ctx));
 
 	amd_romsig = BUFF_OFFSET(ctx, romsig_offset);
 	amd_romsig->signature = EMBEDDED_FW_SIGNATURE;
@@ -1596,6 +1599,13 @@
 		fprintf(stderr, "WARNING: No SOC name specified.\n");
 	}
 
+	if (amd_romsig->efs_gen.gen == EFS_SECOND_GEN)
+		ctx.abs_address = 0;
+	else
+		ctx.abs_address = 1;
+	printf("    AMDFWTOOL  Using firmware directory location of %s address: 0x%08x\n",
+			ctx.abs_address == 1 ? "absolute" : "relative", RUN_CURRENT(ctx));
+
 	integrate_firmwares(&ctx, amd_romsig, amd_fw_table);
 
 	ctx.current = ALIGN(ctx.current, 0x10000U); /* TODO: is it necessary? */