| Index: fmap.c
|
| diff --git a/fmap.c b/fmap.c
|
| index c3ebefb1e0e06409d50907361ee98abb903c5c76..3b8e57969f2a0a6b1bd0ee9ca77c972709478d9f 100644
|
| --- a/fmap.c
|
| +++ b/fmap.c
|
| @@ -44,33 +44,34 @@ extern int fmap_find(struct flashchip *flash, uint8_t **buf)
|
| {
|
| unsigned long int offset = 0;
|
| uint64_t sig, tmp64;
|
| - int i, fmap_found = 0;
|
| - /* Note: keep the strides sorted in largest to smallest order for
|
| - efficient operation below. Strides should all be powers of 2. */
|
| - unsigned int strides[] = { 64 * 1024, 4 * 1024, 64 };
|
| struct fmap fmap;
|
| - int fmap_size;
|
| + int fmap_size, fmap_found = 0, stride;
|
|
|
| memcpy(&sig, FMAP_SIGNATURE, strlen(FMAP_SIGNATURE));
|
|
|
| /*
|
| - * Find FMAP signature within image. The alignment requirements
|
| - * increased over time due to speed concerns, so we'll use an array to
|
| - * represent the strides we wish to attempt to use.
|
| - *
|
| * For efficient operation, we start with the largest stride possible
|
| * and then decrease the stride on each iteration. We will check for a
|
| * remainder when modding the offset with the previous stride. This
|
| * makes it so that each offset is only checked once.
|
| + *
|
| + * At some point, programmer transaction overhead becomes greater than
|
| + * simply copying everything into RAM and checking one byte at a time.
|
| + * At some arbitrary point, we'll stop being clever and use brute
|
| + * force instead by copying the while ROM into RAM and searching one
|
| + * byte at a time.
|
| + *
|
| + * In practice, the flash map is usually stored in a write-protected
|
| + * section of flash which is often at the top of ROM where the boot
|
| + * vector on x86 resides. Because of this, we will search from top
|
| + * to bottom.
|
| */
|
| - for (i = 0; i < ARRAY_SIZE(strides); i++) {
|
| - for (offset = flash->total_size * 1024 - strides[i];
|
| + for (stride = (flash->total_size * 1024) / 2; stride >= 16; stride /= 2) {
|
| + for (offset = flash->total_size * 1024 - stride;
|
| offset > 0;
|
| - offset -= strides[i]) {
|
| - if (i > 0) {
|
| - if (offset % strides[i-1] == 0)
|
| + offset -= stride) {
|
| + if (offset % (stride * 2) == 0)
|
| continue;
|
| - }
|
|
|
| if (flash->read(flash, (uint8_t *)&tmp64,
|
| offset, sizeof(tmp64))) {
|
| @@ -88,6 +89,27 @@ extern int fmap_find(struct flashchip *flash, uint8_t **buf)
|
| break;
|
| }
|
|
|
| + /* brute force */
|
| + /* FIXME: This results in the entire ROM being read twice -- once here
|
| + * and again in doit(). The performance penalty needs to be dealt
|
| + * with before going upstream.
|
| + */
|
| + if (!fmap_found) {
|
| + uint8_t *image = malloc(flash->total_size * 1024);
|
| +
|
| + msg_gdbg("using brute force method to find fmap\n");
|
| + flash->read(flash, image, 0, flash->total_size * 1024);
|
| + for (offset = flash->total_size * 1024 - sizeof(sig);
|
| + offset > 0;
|
| + offset--) {
|
| + if (!memcmp(&image[offset], &sig, sizeof(sig))) {
|
| + fmap_found = 1;
|
| + break;
|
| + }
|
| + }
|
| + free(image);
|
| + }
|
| +
|
| if (!fmap_found)
|
| return 0;
|
|
|
|
|