aboutsummaryrefslogtreecommitdiffstats
path: root/payloads
diff options
context:
space:
mode:
authorJulius Werner <jwerner@chromium.org>2014-11-10 13:14:24 -0800
committerPatrick Georgi <pgeorgi@google.com>2015-04-14 09:01:27 +0200
commitefcee767deed9d10628764eb9143724dd206d5fa (patch)
tree1c08a60bd292e8217856bdc367535fe4e187c8b4 /payloads
parentf780c40f40306a21489f8ddd6e17c979ba0fd7a3 (diff)
downloadcoreboot-efcee767deed9d10628764eb9143724dd206d5fa.tar.gz
coreboot-efcee767deed9d10628764eb9143724dd206d5fa.tar.xz
coreboot-efcee767deed9d10628764eb9143724dd206d5fa.zip
CBFS: Automate ROM image layout and remove hardcoded offsets
Non-x86 boards currently need to hardcode the position of their CBFS master header in a Kconfig. This is very brittle because it is usually put in between the bootblock and the first CBFS entry, without any checks to guarantee that it won't overlap either of those. It is not fun to debug random failures that move and disappear with tiny alignment changes because someone decided to write "ORBC1112" over some part of your data section (in a way that is not visible in the symbolized .elf binaries, only in the final image). This patch seeks to prevent those issues and reduce the need for manual configuration by making the image layout a completely automated part of cbfstool. Since automated placement of the CBFS header means we can no longer hardcode its position into coreboot, this patch takes the existing x86 solution of placing a pointer to the header at the very end of the CBFS-managed section of the ROM and generalizes it to all architectures. This is now even possible with the read-only/read-write split in ChromeOS, since coreboot knows how large that section is from the CBFS_SIZE Kconfig (which is by default equal to ROM_SIZE, but can be changed on systems that place other data next to coreboot/CBFS in ROM). Also adds a feature to cbfstool that makes the -B (bootblock file name) argument on image creation optional, since we have recently found valid use cases for CBFS images that are not the first boot medium of the device (instead opened by an earlier bootloader that can already interpret CBFS) and therefore don't really need a bootblock. BRANCH=None BUG=None TEST=Built and booted on Veyron_Pinky, Nyan_Blaze and Falco. Change-Id: Ib715bb8db258e602991b34f994750a2d3e2d5adf Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: e9879c0fbd57f105254c54bacb3e592acdcad35c Original-Change-Id: Ifcc755326832755cfbccd6f0a12104cba28a20af Original-Signed-off-by: Julius Werner <jwerner@chromium.org> Original-Reviewed-on: https://chromium-review.googlesource.com/229975 Reviewed-on: http://review.coreboot.org/9620 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'payloads')
-rw-r--r--payloads/libpayload/include/cbfs_core.h7
-rw-r--r--payloads/libpayload/libcbfs/cbfs.c13
-rw-r--r--payloads/libpayload/libcbfs/cbfs_core.c27
3 files changed, 18 insertions, 29 deletions
diff --git a/payloads/libpayload/include/cbfs_core.h b/payloads/libpayload/include/cbfs_core.h
index 42f2dc849..459952466 100644
--- a/payloads/libpayload/include/cbfs_core.h
+++ b/payloads/libpayload/include/cbfs_core.h
@@ -85,10 +85,9 @@
#define CBFS_HEADER_INVALID_ADDRESS ((void*)(0xffffffff))
-/** this is the master cbfs header - it needs to be located somewhere available
- to bootblock (to load romstage). Where it actually lives is up to coreboot.
- On x86, a pointer to this header will live at 0xFFFFFFFC.
- For other platforms, you need to define CONFIG_LP_CBFS_HEADER_ROM_OFFSET */
+/* this is the master cbfs header - it must be located somewhere available
+ * to bootblock (to load romstage). The last 4 bytes in the image contain its
+ * relative offset from the end of the image (as a 32-bit signed integer). */
struct cbfs_header {
uint32_t magic;
diff --git a/payloads/libpayload/libcbfs/cbfs.c b/payloads/libpayload/libcbfs/cbfs.c
index 5ab7ffa04..b2b9d6160 100644
--- a/payloads/libpayload/libcbfs/cbfs.c
+++ b/payloads/libpayload/libcbfs/cbfs.c
@@ -62,19 +62,6 @@
# endif
#endif
-#if defined(CONFIG_LP_CBFS_HEADER_ROM_OFFSET) && (CONFIG_LP_CBFS_HEADER_ROM_OFFSET)
-# define CBFS_HEADER_ROM_ADDRESS (CONFIG_LP_CBFS_HEADER_ROM_OFFSET)
-#else
-/* ugly hack: this assumes that "media" exists
- in the scope where the macro is used. */
-static uint32_t fetch_x86_header(struct cbfs_media *media)
-{
- uint32_t *header_ptr = media->map(media, 0xfffffffc, 4);
- return *header_ptr;
-}
-# define CBFS_HEADER_ROM_ADDRESS fetch_x86_header(media)
-#endif
-
#include "cbfs_core.c"
#ifndef __SMM__
diff --git a/payloads/libpayload/libcbfs/cbfs_core.c b/payloads/libpayload/libcbfs/cbfs_core.c
index fb15744fe..eb07e2d29 100644
--- a/payloads/libpayload/libcbfs/cbfs_core.c
+++ b/payloads/libpayload/libcbfs/cbfs_core.c
@@ -34,10 +34,6 @@
* CBFS_CORE_WITH_LZMA (must be #define)
* if defined, ulzma() must exist for decompression of data streams
*
- * CBFS_HEADER_ROM_ADDRESS
- * ROM address (offset) of CBFS header. Underlying CBFS media may interpret
- * it in other way so we call this "address".
- *
* ERROR(x...)
* print an error message x (in printf format)
*
@@ -56,6 +52,7 @@
* on failure */
const struct cbfs_header *cbfs_get_header(struct cbfs_media *media)
{
+ int32_t rel_offset;
const struct cbfs_header *header;
struct cbfs_media default_media;
@@ -66,22 +63,28 @@ const struct cbfs_header *cbfs_get_header(struct cbfs_media *media)
return CBFS_HEADER_INVALID_ADDRESS;
}
}
-
media->open(media);
- DEBUG("CBFS_HEADER_ROM_ADDRESS: 0x%x/0x%x\n", CBFS_HEADER_ROM_ADDRESS,
- CONFIG_LP_ROM_SIZE);
- header = media->map(media, CBFS_HEADER_ROM_ADDRESS, sizeof(*header));
+
+ if (!media->read(media, &rel_offset, (size_t)(0 - sizeof(int32_t)),
+ sizeof(int32_t))) {
+ ERROR("Could not read CBFS master header offset!\n");
+ return CBFS_HEADER_INVALID_ADDRESS;
+ }
+ header = media->map(media, (size_t)rel_offset, sizeof(*header));
+ DEBUG("CBFS header at %#zx (-%#zx from end of image).\n",
+ (size_t)rel_offset, (size_t)-rel_offset);
media->close(media);
if (header == CBFS_MEDIA_INVALID_MAP_ADDRESS) {
- ERROR("Failed to load CBFS header from 0x%x\n",
- CBFS_HEADER_ROM_ADDRESS);
+ ERROR("Failed to load CBFS header from %#zx(-%#zx)\n",
+ (size_t)rel_offset, (size_t)-rel_offset);
return CBFS_HEADER_INVALID_ADDRESS;
}
if (CBFS_HEADER_MAGIC != ntohl(header->magic)) {
- ERROR("Could not find valid CBFS master header at %x: "
- "%x vs %x.\n", CBFS_HEADER_ROM_ADDRESS, CBFS_HEADER_MAGIC,
+ ERROR("Could not find valid CBFS master header at %#zx(-%#zx): "
+ "magic %#.8x vs %#.8x.\n", (size_t)rel_offset,
+ (size_t)-rel_offset, CBFS_HEADER_MAGIC,
ntohl(header->magic));
if (header->magic == 0xffffffff) {
ERROR("Maybe ROM is not mapped properly?\n");