summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulius Werner <jwerner@chromium.org>2015-01-14 11:41:45 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-01-14 23:13:01 +0000
commit75efe872a621a8f865f1a90792ad9ea0932fca2e (patch)
tree2d41b51ac0512862170a71a719c83f368f4fefe7
parent32138f9d4c143bc0858d32e3a7a7b30ff5655212 (diff)
downloadvboot-75efe872a621a8f865f1a90792ad9ea0932fca2e.tar.gz
futility: Change find_fmap() to search larger alignments first
This patch changes the FMAP detection mechanism in host utilities to use the same algorithm as flashrom: try to check the offset with the largest possible alignment first, then subsequently check other offsets in the order of larger to smaller alignments. This provides consistency between the tools and makes the chance of finding the "wrong" FMAP (e.g. a bit pattern that just looks like an FMAP header, maybe from a piece of source code that tries to look for the same) less likely, since we usually try to prefer large alignments for the FMAP offset (for flashrom efficiency). BRANCH=None (should be updated on the signers... is that a branch?) BUG=chromium:447051 TEST='make runtests'. Manually ran the new dump_fmap on all images in tests/futility/data, and on a "known broken" Veyron_Pinky image that had a "fake" FMAP header at a 4-byte aligned offset. Change-Id: I15873573a93f3926c70136679dccd626e5038614 Signed-off-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/240750 Reviewed-by: Bill Richardson <wfrichar@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--host/lib/fmap.c40
1 files changed, 28 insertions, 12 deletions
diff --git a/host/lib/fmap.c b/host/lib/fmap.c
index 76fa9f1d..845d28f2 100644
--- a/host/lib/fmap.c
+++ b/host/lib/fmap.c
@@ -9,21 +9,37 @@
#include "fmap.h"
+static int is_fmap(uint8_t *ptr)
+{
+ FmapHeader *fmap_header = (FmapHeader *)ptr;
+
+ if (0 != memcmp(ptr, FMAP_SIGNATURE, FMAP_SIGNATURE_SIZE))
+ return 0;
+
+ if (fmap_header->fmap_ver_major == FMAP_VER_MAJOR)
+ return 1;
+
+ fprintf(stderr, "Found FMAP, but major version is %u instead of %u\n",
+ fmap_header->fmap_ver_major, FMAP_VER_MAJOR);
+ return 0;
+}
+
/* Find and point to the FMAP header within the buffer */
FmapHeader *fmap_find(uint8_t *ptr, size_t size)
{
- size_t i;
- FmapHeader *fmap_header;
- size_t lim = size - sizeof(FmapHeader);
- for (i = 0;
- i <= lim;
- i += FMAP_SEARCH_STRIDE, ptr += FMAP_SEARCH_STRIDE) {
- if (0 != memcmp(ptr, FMAP_SIGNATURE, FMAP_SIGNATURE_SIZE))
- continue;
- fmap_header = (FmapHeader *)ptr;
- if (fmap_header->fmap_ver_major == FMAP_VER_MAJOR)
- return fmap_header;
- }
+ ssize_t offset, align;
+ ssize_t lim = size - sizeof(FmapHeader);
+
+ if (lim >= 0 && is_fmap(ptr))
+ return (FmapHeader *)ptr;
+
+ /* Search large alignments before small ones to find "right" FMAP. */
+ for (align = FMAP_SEARCH_STRIDE; align <= lim; align *= 2);
+ for (; align >= FMAP_SEARCH_STRIDE; align /= 2)
+ for (offset = align; offset <= lim; offset += align * 2)
+ if (is_fmap(ptr + offset))
+ return (FmapHeader *)(ptr + offset);
+
return NULL;
}