mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-27 03:33:50 +00:00
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>
69 lines
1.7 KiB
C
69 lines
1.7 KiB
C
/*
|
|
* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#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)
|
|
{
|
|
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;
|
|
}
|
|
|
|
/* Search for an area by name, return pointer to its beginning */
|
|
uint8_t *fmap_find_by_name(uint8_t *ptr, size_t size, FmapHeader *fmap,
|
|
const char *name, FmapAreaHeader **ah_ptr)
|
|
{
|
|
int i;
|
|
FmapAreaHeader *ah;
|
|
|
|
if (!fmap)
|
|
fmap = fmap_find(ptr, size);
|
|
if (!fmap)
|
|
return NULL;
|
|
|
|
ah = (FmapAreaHeader*)((void *)fmap + sizeof(FmapHeader));
|
|
for (i = 0; i < fmap->fmap_nareas; i++)
|
|
if (!strncmp(ah[i].area_name, name, FMAP_NAMELEN)) {
|
|
if (ah_ptr)
|
|
*ah_ptr = ah + i;
|
|
return ptr + ah[i].area_offset;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|