coreboot-kgpe-d16/src/include/memlayout.h
Julius Werner 84446e6e54 rmodtool: Make memlayout symbols absolute and do not relocate them
Memlayout is a mechanism to define memory areas outside the normal
program segment constructed by the linker. Therefore, it generally
doesn't make sense to relocate memlayout symbols when the program is
relocated. They tend to refer to things that are always in one specific
spot, independent of where the program is loaded.

This hasn't really hurt us in the past because the use case we have for
rmodules (ramstage on x86) just happens to not really need to refer to
any memlayout-defined areas at the moment. But that use case may come up
in the future so it's still worth fixing.

This patch declares all memlayout-defined symbols as ABSOLUTE() in the
linker, which is then reflected in the symbol table of the generated
ELF. We can then use that distinction to have rmodtool skip them when
generating the relocation table for an rmodule. (Also rearrange rmodtool
a little to make the primary string table more easily accessible to the
rest of the code, so we can refer to symbol names in debug output.)

A similar problem can come up with userspace unit tests, but we cannot
modify the userspace relocation toolchain (and for unfortunate
historical reasons, it tries to relocate even absolute symbols). We'll
just disable PIC and make those binaries fully static to avoid that
issue.

Signed-off-by: Julius Werner <jwerner@chromium.org>
Change-Id: Ic51d9add3dc463495282b365c1b6d4a9bf11dbf2
Reviewed-on: https://review.coreboot.org/c/coreboot/+/50629
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
2021-02-18 02:32:06 +00:00

195 lines
5.8 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only */
/* This file contains macro definitions for memlayout.ld linker scripts. */
#ifndef __MEMLAYOUT_H
#define __MEMLAYOUT_H
#include <arch/memlayout.h>
#include <vb2_constants.h>
#include "fmap_config.h"
/* Macros that the architecture can override. */
#ifndef ARCH_POINTER_ALIGN_SIZE
#define ARCH_POINTER_ALIGN_SIZE 8
#endif
#ifndef ARCH_CACHELINE_ALIGN_SIZE
#define ARCH_CACHELINE_ALIGN_SIZE 64
#endif
#define STR(x) XSTR(x)
#define XSTR(x) #x
#define ALIGN_COUNTER(align) \
. = ALIGN(align);
#define SET_COUNTER(name, addr) \
_ = ASSERT(. <= addr, STR(name overlaps the previous region!)); \
. = addr;
#define SYMBOL(name, addr) \
SET_COUNTER(name, addr) \
_##name = ABSOLUTE(.);
#define REGION(name, addr, size, expected_align) \
SYMBOL(name, addr) \
_ = ASSERT(. == ALIGN(expected_align), \
STR(name must be aligned to expected_align!)); \
SYMBOL(e##name, addr + size)
#define ALIAS_REGION(name, alias) \
_##alias = ABSOLUTE(_##name); \
_e##alias = ABSOLUTE(_e##name); \
/* Declare according to SRAM/DRAM ranges in SoC hardware-defined address map. */
#define SRAM_START(addr) SYMBOL(sram, addr)
#define SRAM_END(addr) SYMBOL(esram, addr)
#define DRAM_START(addr) SYMBOL(dram, addr)
#define TIMESTAMP(addr, size) \
REGION(timestamp, addr, size, 8) \
_ = ASSERT(size >= 212, "Timestamp region must fit timestamp_cache!");
#define PRERAM_CBMEM_CONSOLE(addr, size) \
REGION(preram_cbmem_console, addr, size, 4)
#define EARLYRAM_STACK(addr, size) \
REGION(earlyram_stack, addr, size, ARCH_STACK_ALIGN_SIZE)
/* Use either CBFS_CACHE (unified) or both (PRERAM|POSTRAM)_CBFS_CACHE */
#define CBFS_CACHE(addr, size) \
REGION(cbfs_cache, addr, size, 4) \
ALIAS_REGION(cbfs_cache, preram_cbfs_cache) \
ALIAS_REGION(cbfs_cache, postram_cbfs_cache)
#define FMAP_CACHE(addr, sz) \
REGION(fmap_cache, addr, sz, 4) \
_ = ASSERT(sz >= FMAP_SIZE, \
STR(FMAP does not fit in FMAP_CACHE! (sz < FMAP_SIZE)));
#define CBFS_MCACHE(addr, sz) \
REGION(cbfs_mcache, addr, sz, 4)
#if ENV_ROMSTAGE_OR_BEFORE
#define PRERAM_CBFS_CACHE(addr, size) \
REGION(preram_cbfs_cache, addr, size, 4) \
ALIAS_REGION(preram_cbfs_cache, cbfs_cache)
#define POSTRAM_CBFS_CACHE(addr, size) \
REGION(postram_cbfs_cache, addr, size, 4)
#else
#define PRERAM_CBFS_CACHE(addr, size) \
REGION(preram_cbfs_cache, addr, size, 4)
#define POSTRAM_CBFS_CACHE(addr, size) \
REGION(postram_cbfs_cache, addr, size, 4) \
ALIAS_REGION(postram_cbfs_cache, cbfs_cache)
#endif
/* Careful: 'INCLUDE <filename>' must always be at the end of the output line */
#if ENV_DECOMPRESSOR
#define DECOMPRESSOR(addr, sz) \
SYMBOL(decompressor, addr) \
_edecompressor = ABSOLUTE(_decompressor + sz); \
_ = ASSERT(_eprogram - _program <= sz, \
STR(decompressor exceeded its allotted size! (sz))); \
INCLUDE "decompressor/lib/program.ld"
#define OVERLAP_DECOMPRESSOR_ROMSTAGE(addr, sz) DECOMPRESSOR(addr, sz)
#define OVERLAP_DECOMPRESSOR_VERSTAGE_ROMSTAGE(addr, sz) \
DECOMPRESSOR(addr, sz)
#else
#define DECOMPRESSOR(addr, sz) \
REGION(decompressor, addr, sz, 1)
#define OVERLAP_DECOMPRESSOR_ROMSTAGE(addr, sz) ROMSTAGE(addr, sz)
#define OVERLAP_DECOMPRESSOR_VERSTAGE_ROMSTAGE(addr, sz) \
OVERLAP_VERSTAGE_ROMSTAGE(addr, sz)
#endif
#if ENV_BOOTBLOCK
#define BOOTBLOCK(addr, sz) \
SYMBOL(bootblock, addr) \
_ebootblock = ABSOLUTE(_bootblock + sz); \
_ = ASSERT(_eprogram - _program <= sz, \
STR(Bootblock exceeded its allotted size! (sz))); \
INCLUDE "bootblock/lib/program.ld"
#else
#define BOOTBLOCK(addr, sz) \
REGION(bootblock, addr, sz, 1)
#endif
#if ENV_ROMSTAGE
#define ROMSTAGE(addr, sz) \
SYMBOL(romstage, addr) \
_eromstage = ABSOLUTE(_romstage + sz); \
_ = ASSERT(_eprogram - _program <= sz, \
STR(Romstage exceeded its allotted size! (sz))); \
INCLUDE "romstage/lib/program.ld"
#else
#define ROMSTAGE(addr, sz) \
REGION(romstage, addr, sz, 1)
#endif
#if ENV_RAMSTAGE
#define RAMSTAGE(addr, sz) \
SYMBOL(ramstage, addr) \
_eramstage = ABSOLUTE(_ramstage + sz); \
_ = ASSERT(_eprogram - _program <= sz, \
STR(Ramstage exceeded its allotted size! (sz))); \
INCLUDE "ramstage/lib/program.ld"
#else
#define RAMSTAGE(addr, sz) \
REGION(ramstage, addr, sz, 1)
#endif
/* VBOOT2_WORK must always use VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE for its
* size argument. The constant is imported via vb2_workbuf_size.h. */
#define VBOOT2_WORK(addr, sz) \
REGION(vboot2_work, addr, sz, 16) \
_ = ASSERT(sz == VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE, \
STR(vboot2 work buffer size must be equivalent to \
VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE! (sz)));
#define TPM_TCPA_LOG(addr, size) \
REGION(tpm_tcpa_log, addr, size, 16) \
_ = ASSERT(size >= 2K, "tpm tcpa log buffer must be at least 2K!");
#if ENV_SEPARATE_VERSTAGE
#define VERSTAGE(addr, sz) \
SYMBOL(verstage, addr) \
_everstage = ABSOLUTE(_verstage + sz); \
_ = ASSERT(_eprogram - _program <= sz, \
STR(Verstage exceeded its allotted size! (sz))); \
INCLUDE "verstage/lib/program.ld"
#define OVERLAP_VERSTAGE_ROMSTAGE(addr, size) \
_ = ASSERT(CONFIG(VBOOT_RETURN_FROM_VERSTAGE) == 1, \
"Must set RETURN_FROM_VERSTAGE to overlap romstage."); \
VERSTAGE(addr, size)
#else
#define VERSTAGE(addr, sz) \
REGION(verstage, addr, sz, 1)
#define OVERLAP_VERSTAGE_ROMSTAGE(addr, size) ROMSTAGE(addr, size)
#endif
#if ENV_POSTCAR
#define POSTCAR(addr, sz) \
SYMBOL(postcar, addr) \
_epostcar = ABSOLUTE(_postcar + sz); \
_ = ASSERT(_eprogram - _program <= sz, \
STR(Aftercar exceeded its allotted size! (sz))); \
INCLUDE "postcar/lib/program.ld"
#else
#define POSTCAR(addr, sz) \
REGION(postcar, addr, sz, 1)
#endif
#define WATCHDOG_TOMBSTONE(addr, size) \
REGION(watchdog_tombstone, addr, size, 4) \
_ = ASSERT(size == 4, "watchdog tombstones should be exactly 4 byte!");
#endif /* __MEMLAYOUT_H */