diff --git a/Makefile.inc b/Makefile.inc index 8ecc0ef3b2..8de54a05a6 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -226,7 +226,7 @@ $(foreach type,ads adb, \ # Add handler to copy linker scripts define generic-objs_ld_template_gen de$(EMPTY)fine $(1)-objs_ld_template -$$(call src-to-obj,$1,$$(1).ld): $$(1).ld $(obj)/config.h +$$(call src-to-obj,$1,$$(1).ld): $$(1).ld $(obj)/config.h $(obj)/fmap_config.h @printf " CP $$$$(subst $$$$(obj)/,,$$$$(@))\n" $$(CC_$(1)) -MMD $$(CPPFLAGS_$(1)) $$($(1)-ld-ccopts) $(PREPROCESS_ONLY) -include $(obj)/config.h -MT $$$$@ -o $$$$@ $$$$< en$(EMPTY)def diff --git a/src/arch/x86/car.ld b/src/arch/x86/car.ld index 74fc74b58e..972cb5234b 100644 --- a/src/arch/x86/car.ld +++ b/src/arch/x86/car.ld @@ -58,6 +58,7 @@ #endif TIMESTAMP(., 0x200) + FMAP_CACHE(., FMAP_SIZE) _car_ehci_dbg_info = .; /* Reserve sizeof(struct ehci_dbg_info). */ diff --git a/src/include/memlayout.h b/src/include/memlayout.h index 0100e270c6..56dfb6a785 100644 --- a/src/include/memlayout.h +++ b/src/include/memlayout.h @@ -21,6 +21,8 @@ #include #include +#include "fmap_config.h" + /* Macros that the architecture can override. */ #ifndef ARCH_POINTER_ALIGN_SIZE #define ARCH_POINTER_ALIGN_SIZE 8 @@ -30,7 +32,8 @@ #define ARCH_CACHELINE_ALIGN_SIZE 64 #endif -#define STR(x) #x +#define STR(x) XSTR(x) +#define XSTR(x) #x #define ALIGN_COUNTER(align) \ . = ALIGN(align); @@ -73,6 +76,11 @@ 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 == 0 || sz >= FMAP_SIZE, \ + STR(FMAP does not fit in FMAP_CACHE! (sz < FMAP_SIZE))); + #if ENV_ROMSTAGE_OR_BEFORE #define PRERAM_CBFS_CACHE(addr, size) \ REGION(preram_cbfs_cache, addr, size, 4) \ diff --git a/src/include/symbols.h b/src/include/symbols.h index 56df8d5734..eec47010e4 100644 --- a/src/include/symbols.h +++ b/src/include/symbols.h @@ -34,6 +34,7 @@ DECLARE_REGION(stack) DECLARE_REGION(preram_cbfs_cache) DECLARE_REGION(postram_cbfs_cache) DECLARE_REGION(cbfs_cache) +DECLARE_REGION(fmap_cache) DECLARE_REGION(payload) /* "program" always refers to the current execution unit. */ diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 3b7d57c76a..dc0c46d460 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -208,13 +208,6 @@ $(call src-to-obj,smm,$(dir)/version.c) : $(obj)/build.h $(call src-to-obj,verstage,$(dir)/version.c) : $(obj)/build.h $(call src-to-obj,postcar,$(dir)/version.c) : $(obj)/build.h -$(call src-to-obj,bootblock,$(dir)/cbfs.c) : $(obj)/fmap_config.h -$(call src-to-obj,romstage,$(dir)/cbfs.c) : $(obj)/fmap_config.h -$(call src-to-obj,ramstage,$(dir)/cbfs.c) : $(obj)/fmap_config.h -$(call src-to-obj,smm,$(dir)/cbfs.c) : $(obj)/fmap_config.h -$(call src-to-obj,verstage,$(dir)/cbfs.c) : $(obj)/fmap_config.h -$(call src-to-obj,postcar,$(dir)/cbfs.c) : $(obj)/fmap_config.h - $(call src-to-obj,bootblock,$(dir)/fmap.c) : $(obj)/fmap_config.h $(call src-to-obj,romstage,$(dir)/fmap.c) : $(obj)/fmap_config.h $(call src-to-obj,ramstage,$(dir)/fmap.c) : $(obj)/fmap_config.h diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c index 1601f201fe..27a1592e2b 100644 --- a/src/lib/cbfs.c +++ b/src/lib/cbfs.c @@ -26,7 +26,6 @@ #include #include #include -#include "fmap_config.h" #include #define ERROR(x...) printk(BIOS_ERR, "CBFS: " x) @@ -310,7 +309,10 @@ int cbfs_master_header_props(struct cbfs_props *props) if (bdev == NULL) return -1; - size_t fmap_top = ___FMAP__COREBOOT_BASE + ___FMAP__COREBOOT_SIZE; + struct region fmap_region; + if (fmap_locate_area("COREBOOT", &fmap_region)) + return -1; + size_t fmap_top = region_end(&fmap_region); /* Find location of header using signed 32-bit offset from * end of CBFS region. */ diff --git a/src/lib/fmap.c b/src/lib/fmap.c index f3ff071766..4b4179c769 100644 --- a/src/lib/fmap.c +++ b/src/lib/fmap.c @@ -15,12 +15,13 @@ #include #include +#include #include #include #include #include #include -#include +#include #include "fmap_config.h" @@ -31,26 +32,94 @@ static int fmap_print_once CAR_GLOBAL; static struct mem_region_device fmap_cache CAR_GLOBAL; +#define print_once(...) do { \ + if (!car_get_var(fmap_print_once)) \ + printk(__VA_ARGS__); \ + } while (0) + +DECLARE_OPTIONAL_REGION(fmap_cache); + uint64_t get_fmap_flash_offset(void) { return FMAP_OFFSET; } +static int check_signature(const struct fmap *fmap) +{ + return memcmp(fmap->signature, FMAP_SIGNATURE, sizeof(fmap->signature)); +} + +static void report(const struct fmap *fmap) +{ + print_once(BIOS_DEBUG, "FMAP: Found \"%s\" version %d.%d at %#x.\n", + fmap->name, fmap->ver_major, fmap->ver_minor, FMAP_OFFSET); + print_once(BIOS_DEBUG, "FMAP: base = %#llx size = %#x #areas = %d\n", + (long long)fmap->base, fmap->size, fmap->nareas); + car_set_var(fmap_print_once, 1); +} + +static void setup_preram_cache(struct mem_region_device *cache_mrdev) +{ + if (!ENV_ROMSTAGE_OR_BEFORE) { + /* We get here if ramstage makes an FMAP access before calling + cbmem_initialize(). We should avoid letting it come to that, + so print a warning. */ + print_once(BIOS_WARNING, + "WARNING: Post-RAM FMAP access too early for cache!\n"); + return; + } + + if (REGION_SIZE(fmap_cache) == 0) { + /* If you see this you really want to add an FMAP_CACHE to your + memlayout, unless you absolutely can't affort the 2K. */ + print_once(BIOS_NOTICE, + "NOTE: Running without FMAP_CACHE, should add it!\n"); + return; + } + + struct fmap *fmap = (struct fmap *)_fmap_cache; + if (!ENV_BOOTBLOCK) { + /* NOTE: This assumes that for all platforms running this code, + the bootblock is the first stage and the bootblock will make + at least one FMAP access (usually from finding CBFS). */ + if (!check_signature(fmap)) + goto register_cache; + + printk(BIOS_ERR, "ERROR: FMAP cache corrupted?!\n"); + } + + /* In case we fail below, make sure the cache is invalid. */ + memset(fmap->signature, 0, sizeof(fmap->signature)); + + boot_device_init(); + const struct region_device *boot_rdev = boot_device_ro(); + if (!boot_rdev) + return; + + /* memlayout statically guarantees that the FMAP_CACHE is big enough. */ + if (rdev_readat(boot_rdev, fmap, FMAP_OFFSET, FMAP_SIZE) != FMAP_SIZE) + return; + if (check_signature(fmap)) + return; + report(fmap); + +register_cache: + mem_region_device_ro_init(cache_mrdev, fmap, FMAP_SIZE); +} + static int find_fmap_directory(struct region_device *fmrd) { const struct region_device *boot; struct fmap *fmap; - size_t fmap_size; + struct mem_region_device *cache; size_t offset = FMAP_OFFSET; - if (cbmem_possibly_online() && !ENV_SMM) { - /* Try FMAP cache first */ - const struct mem_region_device *cache; - - cache = car_get_var_ptr(&fmap_cache); - if (region_device_sz(&cache->rdev)) - return rdev_chain_full(fmrd, &cache->rdev); - } + /* Try FMAP cache first */ + cache = car_get_var_ptr(&fmap_cache); + if (!region_device_sz(&cache->rdev)) + setup_preram_cache(cache); + if (region_device_sz(&cache->rdev)) + return rdev_chain_full(fmrd, &cache->rdev); boot_device_init(); boot = boot_device_ro(); @@ -58,32 +127,22 @@ static int find_fmap_directory(struct region_device *fmrd) if (boot == NULL) return -1; - fmap_size = sizeof(struct fmap); - - fmap = rdev_mmap(boot, offset, fmap_size); + fmap = rdev_mmap(boot, offset, sizeof(struct fmap)); if (fmap == NULL) return -1; - if (memcmp(fmap->signature, FMAP_SIGNATURE, sizeof(fmap->signature))) { + if (check_signature(fmap)) { printk(BIOS_DEBUG, "No FMAP found at %zx offset.\n", offset); rdev_munmap(boot, fmap); return -1; } - if (!car_get_var(fmap_print_once)) { - printk(BIOS_DEBUG, "FMAP: Found \"%s\" version %d.%d at %zx.\n", - fmap->name, fmap->ver_major, fmap->ver_minor, offset); - printk(BIOS_DEBUG, "FMAP: base = %llx size = %x #areas = %d\n", - (long long)fmap->base, fmap->size, fmap->nareas); - car_set_var(fmap_print_once, 1); - } - - fmap_size += fmap->nareas * sizeof(struct fmap_area); + report(fmap); rdev_munmap(boot, fmap); - return rdev_chain(fmrd, boot, offset, fmap_size); + return rdev_chain(fmrd, boot, offset, FMAP_SIZE); } int fmap_locate_area_as_rdev(const char *name, struct region_device *area) @@ -212,7 +271,7 @@ ssize_t fmap_overwrite_area(const char *name, const void *buffer, size_t size) return rdev_writeat(&rdev, buffer, 0, size); } -static void fmap_register_cache(int unused) +static void fmap_register_cbmem_cache(int unused) { const struct cbmem_entry *e; struct mem_region_device *mdev; @@ -232,7 +291,7 @@ static void fmap_register_cache(int unused) * The main reason to copy the FMAP into CBMEM is to make it available to the * OS on every architecture. As side effect use the CBMEM copy as cache. */ -static void fmap_setup_cache(int unused) +static void fmap_setup_cbmem_cache(int unused) { struct region_device fmrd; @@ -255,9 +314,9 @@ static void fmap_setup_cache(int unused) } /* Finally advertise the cache for the current stage */ - fmap_register_cache(unused); + fmap_register_cbmem_cache(unused); } -ROMSTAGE_CBMEM_INIT_HOOK(fmap_setup_cache) -RAMSTAGE_CBMEM_INIT_HOOK(fmap_register_cache) -POSTCAR_CBMEM_INIT_HOOK(fmap_register_cache) +ROMSTAGE_CBMEM_INIT_HOOK(fmap_setup_cbmem_cache) +RAMSTAGE_CBMEM_INIT_HOOK(fmap_register_cbmem_cache) +POSTCAR_CBMEM_INIT_HOOK(fmap_register_cbmem_cache) diff --git a/src/soc/mediatek/mt8173/include/soc/memlayout.ld b/src/soc/mediatek/mt8173/include/soc/memlayout.ld index adda86e11b..2358c3940c 100644 --- a/src/soc/mediatek/mt8173/include/soc/memlayout.ld +++ b/src/soc/mediatek/mt8173/include/soc/memlayout.ld @@ -40,7 +40,8 @@ SECTIONS SRAM_START(0x00100000) VBOOT2_WORK(0x00100000, 12K) VBOOT2_TPM_LOG(0x00103000, 2K) - PRERAM_CBMEM_CONSOLE(0x00103800, 14K) + FMAP_CACHE(0x00103800, 2K) + PRERAM_CBMEM_CONSOLE(0x00104000, 12K) WATCHDOG_TOMBSTONE(0x00107000, 4) PRERAM_CBFS_CACHE(0x00107004, 16K - 4) TIMESTAMP(0x0010B000, 4K) diff --git a/src/soc/mediatek/mt8183/include/soc/memlayout.ld b/src/soc/mediatek/mt8183/include/soc/memlayout.ld index 82e404f790..a8f464a3d8 100644 --- a/src/soc/mediatek/mt8183/include/soc/memlayout.ld +++ b/src/soc/mediatek/mt8183/include/soc/memlayout.ld @@ -34,7 +34,8 @@ SECTIONS VBOOT2_TPM_LOG(0x00103000, 2K) PRERAM_CBMEM_CONSOLE(0x00103800, 14K) WATCHDOG_TOMBSTONE(0x00107000, 4) - PRERAM_CBFS_CACHE(0x00107004, 48K - 4) + PRERAM_CBFS_CACHE(0x00107004, 46K - 4) + FMAP_CACHE(0x00112800, 2K) TIMESTAMP(0x00113000, 4K) STACK(0x00114000, 16K) TTB(0x00118000, 28K) diff --git a/src/soc/nvidia/tegra124/include/soc/memlayout.ld b/src/soc/nvidia/tegra124/include/soc/memlayout.ld index 7e2f9ec2af..7e2cc7ad58 100644 --- a/src/soc/nvidia/tegra124/include/soc/memlayout.ld +++ b/src/soc/nvidia/tegra124/include/soc/memlayout.ld @@ -28,7 +28,8 @@ SECTIONS SRAM_START(0x40000000) TTB(0x40000000, 16K + 32) PRERAM_CBMEM_CONSOLE(0x40004020, 6K - 32) - PRERAM_CBFS_CACHE(0x40005800, 16K) + FMAP_CACHE(0x40005800, 2K) + PRERAM_CBFS_CACHE(0x40006000, 14K) VBOOT2_WORK(0x40009800, 12K) VBOOT2_TPM_LOG(0x4000D800, 2K) STACK(0x4000E000, 8K) diff --git a/src/soc/nvidia/tegra210/include/soc/memlayout.ld b/src/soc/nvidia/tegra210/include/soc/memlayout.ld index 1134da6111..b7268d114b 100644 --- a/src/soc/nvidia/tegra210/include/soc/memlayout.ld +++ b/src/soc/nvidia/tegra210/include/soc/memlayout.ld @@ -29,7 +29,8 @@ SECTIONS { SRAM_START(0x40000000) PRERAM_CBMEM_CONSOLE(0x40000000, 2K) - PRERAM_CBFS_CACHE(0x40000800, 30K) + FMAP_CACHE(0x40000800, 2K) + PRERAM_CBFS_CACHE(0x40001000, 28K) VBOOT2_WORK(0x40008000, 12K) VBOOT2_TPM_LOG(0x4000B000, 2K) #if ENV_ARM64 diff --git a/src/soc/qualcomm/ipq40xx/include/soc/memlayout.ld b/src/soc/qualcomm/ipq40xx/include/soc/memlayout.ld index f1a7bc59d2..6ff1018272 100644 --- a/src/soc/qualcomm/ipq40xx/include/soc/memlayout.ld +++ b/src/soc/qualcomm/ipq40xx/include/soc/memlayout.ld @@ -34,7 +34,8 @@ SECTIONS /* This includes bootblock image, can be reused after bootblock starts */ /* UBER_SBL(0x0A0C0000, 48K) */ - PRERAM_CBFS_CACHE(0x0A0C0000, 93K) + PRERAM_CBFS_CACHE(0x0A0C0000, 92K) + FMAP_CACHE(0x0A0EF800, 2K) TTB(0x0A0F0000, 16K) TTB_SUBTABLES(0x0A0F4000, 4K) diff --git a/src/soc/qualcomm/ipq806x/include/soc/memlayout.ld b/src/soc/qualcomm/ipq806x/include/soc/memlayout.ld index 25db17587c..595d939d0b 100644 --- a/src/soc/qualcomm/ipq806x/include/soc/memlayout.ld +++ b/src/soc/qualcomm/ipq806x/include/soc/memlayout.ld @@ -38,7 +38,8 @@ SECTIONS QCA_SHARED_RAM(2A03F000, 4K) */ STACK(0x2A040000, 16K) - PRERAM_CBFS_CACHE(0x2A044000, 93K) + PRERAM_CBFS_CACHE(0x2A044000, 91K) + FMAP_CACHE(0x2A05B000, 2K) TTB_SUBTABLES(0x2A05B800, 2K) TTB(0x2A05C000, 16K) SRAM_END(0x2A060000) diff --git a/src/soc/qualcomm/qcs405/include/soc/memlayout.ld b/src/soc/qualcomm/qcs405/include/soc/memlayout.ld index 68642d67a2..dd013b5e8f 100644 --- a/src/soc/qualcomm/qcs405/include/soc/memlayout.ld +++ b/src/soc/qualcomm/qcs405/include/soc/memlayout.ld @@ -39,7 +39,8 @@ SECTIONS TIMESTAMP(0x8C4F000, 1K) PRERAM_CBMEM_CONSOLE(0x8C4F400, 32K) PRERAM_CBFS_CACHE(0x8C57400, 70K) - REGION(bsram_unused, 0x8C68C00, 0xA2400, 0x100) + FMAP_CACHE(0x8C68C00, 2K) + REGION(bsram_unused, 0x8C69400, 0xA1C00, 0x100) BSRAM_END(0x8D80000) DRAM_START(0x80000000) diff --git a/src/soc/qualcomm/sc7180/include/soc/memlayout.ld b/src/soc/qualcomm/sc7180/include/soc/memlayout.ld index b2ee3b20a0..3f43419d14 100644 --- a/src/soc/qualcomm/sc7180/include/soc/memlayout.ld +++ b/src/soc/qualcomm/sc7180/include/soc/memlayout.ld @@ -43,6 +43,7 @@ SECTIONS REGION(ddr_training, 0x14850000, 8K, 4K) REGION(qclib_serial_log, 0x14852000, 4K, 4K) REGION(ddr_information, 0x14853000, 1K, 1K) + FMAP_CACHE(0x14853400, 2K) REGION(dcb, 0x14870000, 16K, 4K) REGION(pmic, 0x14874000, 44K, 4K) REGION(limits_cfg, 0x1487F000, 4K, 4K) diff --git a/src/soc/rockchip/rk3399/include/soc/memlayout.ld b/src/soc/rockchip/rk3399/include/soc/memlayout.ld index 293057a091..4e46e2d764 100644 --- a/src/soc/rockchip/rk3399/include/soc/memlayout.ld +++ b/src/soc/rockchip/rk3399/include/soc/memlayout.ld @@ -33,7 +33,8 @@ SECTIONS #if ENV_RAMSTAGE REGION(bl31_sram, 0xFF8C0000, 64K, 1) #else - PRERAM_CBFS_CACHE(0xFF8C0000, 7K) + PRERAM_CBFS_CACHE(0xFF8C0000, 5K) + FMAP_CACHE(0xFF8C1400, 2K) TIMESTAMP(0xFF8C1C00, 1K) /* 0xFF8C2004 is the entry point address the masked ROM will jump to. */ OVERLAP_DECOMPRESSOR_VERSTAGE_ROMSTAGE(0xFF8C2004, 88K - 4) diff --git a/src/soc/samsung/exynos5250/include/soc/memlayout.ld b/src/soc/samsung/exynos5250/include/soc/memlayout.ld index 0bd319e45d..7e052f0f31 100644 --- a/src/soc/samsung/exynos5250/include/soc/memlayout.ld +++ b/src/soc/samsung/exynos5250/include/soc/memlayout.ld @@ -31,7 +31,8 @@ SECTIONS ROMSTAGE(0x2030000, 128K) /* 32K hole */ TTB(0x2058000, 16K) - PRERAM_CBFS_CACHE(0x205C000, 78K) + PRERAM_CBFS_CACHE(0x205C000, 76K) + FMAP_CACHE(0x206F000, 2K) VBOOT2_TPM_LOG(0x206F800, 2K) VBOOT2_WORK(0x2070000, 12K) STACK(0x2074000, 16K) diff --git a/src/soc/samsung/exynos5420/include/soc/memlayout.ld b/src/soc/samsung/exynos5420/include/soc/memlayout.ld index bc5d0669da..ff781d2228 100644 --- a/src/soc/samsung/exynos5420/include/soc/memlayout.ld +++ b/src/soc/samsung/exynos5420/include/soc/memlayout.ld @@ -32,7 +32,8 @@ SECTIONS ROMSTAGE(0x2030000, 128K) /* 32K hole */ TTB(0x2058000, 16K) - PRERAM_CBFS_CACHE(0x205C000, 76K) + PRERAM_CBFS_CACHE(0x205C000, 74K) + FMAP_CACHE(0x206E800, 2K) STACK(0x206F000, 16K) /* 1K hole for weird kernel-shared CPU/SMP state structure that doesn't * seem to be implemented right now? */ diff --git a/util/cbfstool/fmaptool.c b/util/cbfstool/fmaptool.c index faf65081fd..1c01ec0da9 100644 --- a/util/cbfstool/fmaptool.c +++ b/util/cbfstool/fmaptool.c @@ -24,6 +24,7 @@ #define STDIN_FILENAME_SENTINEL "-" #define HEADER_FMAP_OFFSET "FMAP_OFFSET" +#define HEADER_FMAP_SIZE "FMAP_SIZE" enum fmaptool_return { FMAPTOOL_EXIT_SUCCESS = 0, @@ -83,7 +84,8 @@ static void list_cbfs_section_names(FILE *out) } static bool write_header(const char *out_fname, - const struct flashmap_descriptor *root) + const struct flashmap_descriptor *root, + const int fmap_size) { assert(out_fname); @@ -100,21 +102,8 @@ static bool write_header(const char *out_fname, fputs("#ifndef FMAPTOOL_GENERATED_HEADER_H_\n", header); fputs("#define FMAPTOOL_GENERATED_HEADER_H_\n\n", header); - fprintf(header, "#define %s %#x\n\n", HEADER_FMAP_OFFSET, fmap_offset); - - /* also add defines for each CBFS-carrying fmap region: base and size */ - cbfs_section_iterator_t cbfs_it = cbfs_sections_iterator(); - while (cbfs_it) { - const struct flashmap_descriptor *item = - cbfs_sections_iterator_deref(cbfs_it); - assert(item->offset_known && item->size_known); - unsigned abs_base = fmd_calc_absolute_offset(root, item->name); - fprintf(header, "#define ___FMAP__%s_BASE 0x%x\n", - item->name, abs_base); - fprintf(header, "#define ___FMAP__%s_SIZE 0x%x\n", - item->name, item->size); - cbfs_sections_iterator_advance(&cbfs_it); - } + fprintf(header, "#define %s %#x\n", HEADER_FMAP_OFFSET, fmap_offset); + fprintf(header, "#define %s %#x\n\n", HEADER_FMAP_SIZE, fmap_size); fputs("#endif\n", header); @@ -245,7 +234,7 @@ int main(int argc, char **argv) fmap_destroy(flashmap); if (args.header_filename && - !write_header(args.header_filename, descriptor)) { + !write_header(args.header_filename, descriptor, size)) { full_fmd_cleanup(&descriptor); return FMAPTOOL_EXIT_FAILED_WRITING_HEADER; }