| 49 | "RW_NVRAM FMAP section not present or too small"); |
| 50 | |
| 51 | static int init_vbnv(void) |
| 52 | { |
| 53 | struct vbnv_flash_ctx *ctx = &vbnv_flash; |
| 54 | struct region_device *rdev = &ctx->vbnv_dev; |
| 55 | uint8_t buf[BLOB_SIZE]; |
| 56 | uint8_t empty_blob[BLOB_SIZE]; |
| 57 | int used_below, empty_above; |
| 58 | int offset; |
| 59 | int i; |
| 60 | |
| 61 | if (fmap_locate_area_as_rdev_rw("RW_NVRAM", rdev) || |
| 62 | region_device_sz(rdev) < BLOB_SIZE) { |
| 63 | printk(BIOS_ERR, "%s: failed to locate NVRAM\n", __func__); |
| 64 | return 1; |
| 65 | } |
| 66 | |
| 67 | /* Prepare an empty blob to compare against. */ |
| 68 | for (i = 0; i < BLOB_SIZE; i++) |
| 69 | empty_blob[i] = erase_value(); |
| 70 | |
| 71 | ctx->top_offset = region_device_sz(rdev) - BLOB_SIZE; |
| 72 | |
| 73 | /* Binary search for the border between used and empty */ |
| 74 | used_below = 0; |
| 75 | empty_above = region_device_sz(rdev) / BLOB_SIZE; |
| 76 | |
| 77 | while (used_below + 1 < empty_above) { |
| 78 | int guess = (used_below + empty_above) / 2; |
| 79 | if (rdev_readat(rdev, buf, guess * BLOB_SIZE, BLOB_SIZE) < 0) { |
| 80 | printk(BIOS_ERR, "failed to read nvdata\n"); |
| 81 | return 1; |
| 82 | } |
| 83 | if (!memcmp(buf, empty_blob, BLOB_SIZE)) |
| 84 | empty_above = guess; |
| 85 | else |
| 86 | used_below = guess; |
| 87 | } |
| 88 | |
| 89 | /* |
| 90 | * Offset points to the last non-empty blob. Or if all blobs are empty |
| 91 | * (nvram is totally erased), point to the first blob. |
| 92 | */ |
| 93 | offset = used_below * BLOB_SIZE; |
| 94 | |
| 95 | /* reread the nvdata and write it to the cache */ |
| 96 | if (rdev_readat(rdev, ctx->cache, offset, BLOB_SIZE) < 0) { |
| 97 | printk(BIOS_ERR, "failed to read nvdata\n"); |
| 98 | return 1; |
| 99 | } |
| 100 | |
| 101 | ctx->blob_offset = offset; |
| 102 | ctx->initialized = 1; |
| 103 | |
| 104 | return 0; |
| 105 | } |
| 106 | |
| 107 | static int erase_nvram(void) |
| 108 | { |
no test coverage detected