Joel Kitching | 9adf2aa | 2019-08-20 17:43:50 +0800 | [diff] [blame] | 1 | /* Copyright 2014 The Chromium OS Authors. All rights reserved. |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 2 | * Use of this source code is governed by a BSD-style license that can be |
| 3 | * found in the LICENSE file. |
| 4 | */ |
| 5 | |
Hung-Te Lin | 859682a | 2019-01-15 18:07:23 +0800 | [diff] [blame] | 6 | #include <assert.h> |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 7 | #include <errno.h> |
Idwer Vollering | b384db3 | 2021-05-10 21:15:45 +0200 | [diff] [blame^] | 8 | #if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__) |
Bill Richardson | e192e7f | 2014-09-23 12:49:26 -0700 | [diff] [blame] | 9 | #include <linux/fs.h> /* For BLKGETSIZE64 */ |
David Riley | 05987b1 | 2015-02-05 19:22:49 -0800 | [diff] [blame] | 10 | #endif |
Bill Richardson | e192e7f | 2014-09-23 12:49:26 -0700 | [diff] [blame] | 11 | #include <stdarg.h> |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 12 | #include <stdint.h> |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 13 | #include <stdio.h> |
| 14 | #include <stdlib.h> |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 15 | #include <string.h> |
Bill Richardson | e192e7f | 2014-09-23 12:49:26 -0700 | [diff] [blame] | 16 | #include <sys/ioctl.h> |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 17 | #include <sys/mman.h> |
| 18 | #include <sys/stat.h> |
| 19 | #include <sys/types.h> |
| 20 | #include <sys/wait.h> |
| 21 | #include <unistd.h> |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 22 | |
Randall Spangler | 7c3ae42 | 2016-05-11 13:50:18 -0700 | [diff] [blame] | 23 | #include "2common.h" |
| 24 | #include "2sha.h" |
Joel Kitching | ffd42a8 | 2019-08-29 13:58:52 +0800 | [diff] [blame] | 25 | #include "2sysincludes.h" |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 26 | #include "cgptlib_internal.h" |
| 27 | #include "file_type.h" |
Bill Richardson | e192e7f | 2014-09-23 12:49:26 -0700 | [diff] [blame] | 28 | #include "futility.h" |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 29 | |
Bill Richardson | c8054ea | 2015-03-12 08:53:10 -0700 | [diff] [blame] | 30 | /* Default is to support everything we can */ |
| 31 | enum vboot_version vboot_version = VBOOT_VERSION_ALL; |
| 32 | |
Bill Richardson | e192e7f | 2014-09-23 12:49:26 -0700 | [diff] [blame] | 33 | int debugging_enabled; |
Julius Werner | 5160e69 | 2019-03-05 13:56:41 -0800 | [diff] [blame] | 34 | void vb2ex_printf(const char *func, const char *format, ...) |
Bill Richardson | e192e7f | 2014-09-23 12:49:26 -0700 | [diff] [blame] | 35 | { |
| 36 | if (!debugging_enabled) |
| 37 | return; |
| 38 | |
| 39 | va_list ap; |
| 40 | va_start(ap, format); |
Julius Werner | 88a47ff | 2019-05-08 13:33:20 -0700 | [diff] [blame] | 41 | fprintf(stderr, "DEBUG: %s: ", func); |
| 42 | vfprintf(stderr, format, ap); |
Bill Richardson | e192e7f | 2014-09-23 12:49:26 -0700 | [diff] [blame] | 43 | va_end(ap); |
| 44 | } |
| 45 | |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 46 | static int is_null_terminated(const char *s, int len) |
| 47 | { |
| 48 | len--; |
| 49 | s += len; |
| 50 | while (len-- >= 0) |
| 51 | if (!*s--) |
| 52 | return 1; |
| 53 | return 0; |
| 54 | } |
| 55 | |
| 56 | static inline uint32_t max(uint32_t a, uint32_t b) |
| 57 | { |
| 58 | return a > b ? a : b; |
| 59 | } |
| 60 | |
Bill Richardson | 35c69cc | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 61 | enum futil_file_type ft_recognize_gbb(uint8_t *buf, uint32_t len) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 62 | { |
Joel Kitching | 27e3e9f | 2019-04-25 18:31:14 +0800 | [diff] [blame] | 63 | struct vb2_gbb_header *gbb = (struct vb2_gbb_header *)buf; |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 64 | |
Joel Kitching | 27e3e9f | 2019-04-25 18:31:14 +0800 | [diff] [blame] | 65 | if (memcmp(gbb->signature, VB2_GBB_SIGNATURE, VB2_GBB_SIGNATURE_SIZE)) |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 66 | return FILE_TYPE_UNKNOWN; |
Joel Kitching | 27e3e9f | 2019-04-25 18:31:14 +0800 | [diff] [blame] | 67 | if (gbb->major_version > VB2_GBB_MAJOR_VER) |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 68 | return FILE_TYPE_UNKNOWN; |
Joel Kitching | 27e3e9f | 2019-04-25 18:31:14 +0800 | [diff] [blame] | 69 | if (sizeof(struct vb2_gbb_header) > len) |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 70 | return FILE_TYPE_UNKNOWN; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 71 | |
| 72 | /* close enough */ |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 73 | return FILE_TYPE_GBB; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 74 | } |
| 75 | |
Joel Kitching | 27e3e9f | 2019-04-25 18:31:14 +0800 | [diff] [blame] | 76 | int futil_valid_gbb_header(struct vb2_gbb_header *gbb, uint32_t len, |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 77 | uint32_t *maxlen_ptr) |
| 78 | { |
Joel Kitching | 27e3e9f | 2019-04-25 18:31:14 +0800 | [diff] [blame] | 79 | if (len < sizeof(struct vb2_gbb_header)) |
Bill Richardson | 7ccd9ce | 2015-01-30 23:45:49 -0800 | [diff] [blame] | 80 | return 0; |
| 81 | |
Joel Kitching | 27e3e9f | 2019-04-25 18:31:14 +0800 | [diff] [blame] | 82 | if (memcmp(gbb->signature, VB2_GBB_SIGNATURE, VB2_GBB_SIGNATURE_SIZE)) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 83 | return 0; |
Joel Kitching | 27e3e9f | 2019-04-25 18:31:14 +0800 | [diff] [blame] | 84 | if (gbb->major_version != VB2_GBB_MAJOR_VER) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 85 | return 0; |
| 86 | |
| 87 | /* Check limits first, to help identify problems */ |
| 88 | if (maxlen_ptr) { |
| 89 | uint32_t maxlen = gbb->header_size; |
| 90 | maxlen = max(maxlen, |
| 91 | gbb->hwid_offset + gbb->hwid_size); |
| 92 | maxlen = max(maxlen, |
| 93 | gbb->rootkey_offset + gbb->rootkey_size); |
| 94 | maxlen = max(maxlen, |
| 95 | gbb->bmpfv_offset + gbb->bmpfv_size); |
| 96 | maxlen = max(maxlen, |
| 97 | gbb->recovery_key_offset + gbb->recovery_key_size); |
| 98 | *maxlen_ptr = maxlen; |
| 99 | } |
| 100 | |
Joel Kitching | 27e3e9f | 2019-04-25 18:31:14 +0800 | [diff] [blame] | 101 | if (gbb->header_size != EXPECTED_VB2_GBB_HEADER_SIZE || |
| 102 | gbb->header_size > len) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 103 | return 0; |
Joel Kitching | 27e3e9f | 2019-04-25 18:31:14 +0800 | [diff] [blame] | 104 | if (gbb->hwid_offset < EXPECTED_VB2_GBB_HEADER_SIZE) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 105 | return 0; |
| 106 | if (gbb->hwid_offset + gbb->hwid_size > len) |
| 107 | return 0; |
| 108 | if (gbb->hwid_size) { |
| 109 | const char *s = (const char *) |
| 110 | ((uint8_t *)gbb + gbb->hwid_offset); |
| 111 | if (!is_null_terminated(s, gbb->hwid_size)) |
| 112 | return 0; |
| 113 | } |
Joel Kitching | 27e3e9f | 2019-04-25 18:31:14 +0800 | [diff] [blame] | 114 | if (gbb->rootkey_offset < EXPECTED_VB2_GBB_HEADER_SIZE) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 115 | return 0; |
| 116 | if (gbb->rootkey_offset + gbb->rootkey_size > len) |
| 117 | return 0; |
| 118 | |
Joel Kitching | 27e3e9f | 2019-04-25 18:31:14 +0800 | [diff] [blame] | 119 | if (gbb->bmpfv_offset < EXPECTED_VB2_GBB_HEADER_SIZE) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 120 | return 0; |
| 121 | if (gbb->bmpfv_offset + gbb->bmpfv_size > len) |
| 122 | return 0; |
Joel Kitching | 27e3e9f | 2019-04-25 18:31:14 +0800 | [diff] [blame] | 123 | if (gbb->recovery_key_offset < EXPECTED_VB2_GBB_HEADER_SIZE) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 124 | return 0; |
| 125 | if (gbb->recovery_key_offset + gbb->recovery_key_size > len) |
| 126 | return 0; |
| 127 | |
| 128 | /* Seems legit... */ |
| 129 | return 1; |
| 130 | } |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 131 | |
Bill Richardson | 6df3e33 | 2014-10-02 18:50:33 -0700 | [diff] [blame] | 132 | /* For GBB v1.2 and later, print the stored digest of the HWID (and whether |
| 133 | * it's correct). Return true if it is correct. */ |
Joel Kitching | 27e3e9f | 2019-04-25 18:31:14 +0800 | [diff] [blame] | 134 | int print_hwid_digest(struct vb2_gbb_header *gbb, |
Bill Richardson | 6df3e33 | 2014-10-02 18:50:33 -0700 | [diff] [blame] | 135 | const char *banner, const char *footer) |
| 136 | { |
| 137 | printf("%s", banner); |
| 138 | |
| 139 | /* There isn't one for v1.1 and earlier, so assume it's good. */ |
| 140 | if (gbb->minor_version < 2) { |
| 141 | printf("<none>%s", footer); |
| 142 | return 1; |
| 143 | } |
| 144 | |
| 145 | uint8_t *buf = (uint8_t *)gbb; |
| 146 | char *hwid_str = (char *)(buf + gbb->hwid_offset); |
| 147 | int is_valid = 0; |
Randall Spangler | 7c3ae42 | 2016-05-11 13:50:18 -0700 | [diff] [blame] | 148 | uint8_t digest[VB2_SHA256_DIGEST_SIZE]; |
| 149 | |
| 150 | if (VB2_SUCCESS == vb2_digest_buffer(buf + gbb->hwid_offset, |
| 151 | strlen(hwid_str), VB2_HASH_SHA256, |
| 152 | digest, sizeof(digest))) { |
Bill Richardson | 6df3e33 | 2014-10-02 18:50:33 -0700 | [diff] [blame] | 153 | int i; |
| 154 | is_valid = 1; |
| 155 | /* print it, comparing as we go */ |
Randall Spangler | 7c3ae42 | 2016-05-11 13:50:18 -0700 | [diff] [blame] | 156 | for (i = 0; i < VB2_SHA256_DIGEST_SIZE; i++) { |
Bill Richardson | 6df3e33 | 2014-10-02 18:50:33 -0700 | [diff] [blame] | 157 | printf("%02x", gbb->hwid_digest[i]); |
| 158 | if (gbb->hwid_digest[i] != digest[i]) |
| 159 | is_valid = 0; |
| 160 | } |
Bill Richardson | 6df3e33 | 2014-10-02 18:50:33 -0700 | [diff] [blame] | 161 | } |
| 162 | |
| 163 | printf(" %s", is_valid ? "valid" : "<invalid>"); |
| 164 | printf("%s", footer); |
| 165 | return is_valid; |
| 166 | } |
| 167 | |
Hung-Te Lin | 859682a | 2019-01-15 18:07:23 +0800 | [diff] [blame] | 168 | /* Deprecated. Use futil_set_gbb_hwid in future. */ |
Bill Richardson | 6df3e33 | 2014-10-02 18:50:33 -0700 | [diff] [blame] | 169 | /* For GBB v1.2 and later, update the hwid_digest field. */ |
Joel Kitching | 27e3e9f | 2019-04-25 18:31:14 +0800 | [diff] [blame] | 170 | void update_hwid_digest(struct vb2_gbb_header *gbb) |
Bill Richardson | 6df3e33 | 2014-10-02 18:50:33 -0700 | [diff] [blame] | 171 | { |
| 172 | /* There isn't one for v1.1 and earlier */ |
| 173 | if (gbb->minor_version < 2) |
| 174 | return; |
| 175 | |
| 176 | uint8_t *buf = (uint8_t *)gbb; |
| 177 | char *hwid_str = (char *)(buf + gbb->hwid_offset); |
Randall Spangler | 7c3ae42 | 2016-05-11 13:50:18 -0700 | [diff] [blame] | 178 | |
| 179 | vb2_digest_buffer(buf + gbb->hwid_offset, strlen(hwid_str), |
| 180 | VB2_HASH_SHA256, |
| 181 | gbb->hwid_digest, sizeof(gbb->hwid_digest)); |
Bill Richardson | 6df3e33 | 2014-10-02 18:50:33 -0700 | [diff] [blame] | 182 | } |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 183 | |
Hung-Te Lin | 859682a | 2019-01-15 18:07:23 +0800 | [diff] [blame] | 184 | /* Sets the HWID string field inside a GBB header. */ |
| 185 | int futil_set_gbb_hwid(struct vb2_gbb_header *gbb, const char *hwid) |
| 186 | { |
| 187 | uint8_t *to = (uint8_t *)gbb + gbb->hwid_offset; |
| 188 | size_t len; |
| 189 | |
| 190 | assert(hwid); |
| 191 | len = strlen(hwid); |
| 192 | if (len >= gbb->hwid_size) |
| 193 | return -1; |
| 194 | |
| 195 | /* Zero whole area so we won't have garbage after NUL. */ |
| 196 | memset(to, 0, gbb->hwid_size); |
| 197 | memcpy(to, hwid, len); |
| 198 | |
| 199 | /* major_version starts from 1 and digest must be updated since v1.2. */ |
| 200 | if (gbb->major_version == 1 && gbb->minor_version < 2) |
| 201 | return 0; |
| 202 | |
| 203 | return vb2_digest_buffer(to, len, VB2_HASH_SHA256, gbb->hwid_digest, |
| 204 | sizeof(gbb->hwid_digest)); |
| 205 | } |
| 206 | |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 207 | /* |
| 208 | * TODO: All sorts of race conditions likely here, and everywhere this is used. |
| 209 | * Do we care? If so, fix it. |
| 210 | */ |
Bill Richardson | e192e7f | 2014-09-23 12:49:26 -0700 | [diff] [blame] | 211 | void futil_copy_file_or_die(const char *infile, const char *outfile) |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 212 | { |
| 213 | pid_t pid; |
| 214 | int status; |
| 215 | |
Julius Werner | 5160e69 | 2019-03-05 13:56:41 -0800 | [diff] [blame] | 216 | VB2_DEBUG("%s -> %s\n", infile, outfile); |
Bill Richardson | b406c10 | 2014-12-03 14:10:13 -0800 | [diff] [blame] | 217 | |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 218 | pid = fork(); |
| 219 | |
| 220 | if (pid < 0) { |
| 221 | fprintf(stderr, "Couldn't fork /bin/cp process: %s\n", |
| 222 | strerror(errno)); |
| 223 | exit(1); |
| 224 | } |
| 225 | |
| 226 | /* child */ |
| 227 | if (!pid) { |
| 228 | execl("/bin/cp", "/bin/cp", infile, outfile, NULL); |
| 229 | fprintf(stderr, "Child couldn't exec /bin/cp: %s\n", |
| 230 | strerror(errno)); |
| 231 | exit(1); |
| 232 | } |
| 233 | |
| 234 | /* parent - wait for child to finish */ |
| 235 | if (wait(&status) == -1) { |
| 236 | fprintf(stderr, |
| 237 | "Couldn't wait for /bin/cp process to exit: %s\n", |
| 238 | strerror(errno)); |
| 239 | exit(1); |
| 240 | } |
| 241 | |
| 242 | if (WIFEXITED(status)) { |
| 243 | status = WEXITSTATUS(status); |
| 244 | /* zero is normal exit */ |
| 245 | if (!status) |
| 246 | return; |
| 247 | fprintf(stderr, "/bin/cp exited with status %d\n", status); |
| 248 | exit(1); |
| 249 | } |
| 250 | |
Bill Richardson | 779796f | 2014-09-23 11:47:40 -0700 | [diff] [blame] | 251 | if (WIFSIGNALED(status)) { |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 252 | status = WTERMSIG(status); |
| 253 | fprintf(stderr, "/bin/cp was killed with signal %d\n", status); |
| 254 | exit(1); |
| 255 | } |
| 256 | |
| 257 | fprintf(stderr, "I have no idea what just happened\n"); |
| 258 | exit(1); |
| 259 | } |
| 260 | |
| 261 | |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 262 | enum futil_file_err futil_map_file(int fd, int writeable, |
| 263 | uint8_t **buf, uint32_t *len) |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 264 | { |
| 265 | struct stat sb; |
| 266 | void *mmap_ptr; |
| 267 | uint32_t reasonable_len; |
| 268 | |
| 269 | if (0 != fstat(fd, &sb)) { |
| 270 | fprintf(stderr, "Can't stat input file: %s\n", |
| 271 | strerror(errno)); |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 272 | return FILE_ERR_STAT; |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 273 | } |
| 274 | |
Idwer Vollering | b384db3 | 2021-05-10 21:15:45 +0200 | [diff] [blame^] | 275 | #if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__) |
Bill Richardson | e192e7f | 2014-09-23 12:49:26 -0700 | [diff] [blame] | 276 | if (S_ISBLK(sb.st_mode)) |
| 277 | ioctl(fd, BLKGETSIZE64, &sb.st_size); |
David Riley | 05987b1 | 2015-02-05 19:22:49 -0800 | [diff] [blame] | 278 | #endif |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 279 | |
| 280 | /* If the image is larger than 2^32 bytes, it's wrong. */ |
| 281 | if (sb.st_size < 0 || sb.st_size > UINT32_MAX) { |
| 282 | fprintf(stderr, "Image size is unreasonable\n"); |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 283 | return FILE_ERR_SIZE; |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 284 | } |
| 285 | reasonable_len = (uint32_t)sb.st_size; |
| 286 | |
| 287 | if (writeable) |
| 288 | mmap_ptr = mmap(0, sb.st_size, |
| 289 | PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); |
| 290 | else |
| 291 | mmap_ptr = mmap(0, sb.st_size, |
Bill Richardson | e192e7f | 2014-09-23 12:49:26 -0700 | [diff] [blame] | 292 | PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 293 | |
| 294 | if (mmap_ptr == (void *)-1) { |
| 295 | fprintf(stderr, "Can't mmap %s file: %s\n", |
| 296 | writeable ? "output" : "input", |
| 297 | strerror(errno)); |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 298 | return FILE_ERR_MMAP; |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 299 | } |
| 300 | |
Bill Richardson | e192e7f | 2014-09-23 12:49:26 -0700 | [diff] [blame] | 301 | *buf = (uint8_t *)mmap_ptr; |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 302 | *len = reasonable_len; |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 303 | return FILE_ERR_NONE; |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 304 | } |
| 305 | |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 306 | enum futil_file_err futil_unmap_file(int fd, int writeable, |
| 307 | uint8_t *buf, uint32_t len) |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 308 | { |
Bill Richardson | e192e7f | 2014-09-23 12:49:26 -0700 | [diff] [blame] | 309 | void *mmap_ptr = buf; |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 310 | enum futil_file_err err = FILE_ERR_NONE; |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 311 | |
| 312 | if (writeable && |
Bill Richardson | e192e7f | 2014-09-23 12:49:26 -0700 | [diff] [blame] | 313 | (0 != msync(mmap_ptr, len, MS_SYNC|MS_INVALIDATE))) { |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 314 | fprintf(stderr, "msync failed: %s\n", strerror(errno)); |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 315 | err = FILE_ERR_MSYNC; |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 316 | } |
| 317 | |
Bill Richardson | e192e7f | 2014-09-23 12:49:26 -0700 | [diff] [blame] | 318 | if (0 != munmap(mmap_ptr, len)) { |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 319 | fprintf(stderr, "Can't munmap pointer: %s\n", |
| 320 | strerror(errno)); |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 321 | if (err == FILE_ERR_NONE) |
| 322 | err = FILE_ERR_MUNMAP; |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 323 | } |
| 324 | |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 325 | return err; |
| 326 | } |
| 327 | |
| 328 | |
| 329 | #define DISK_SECTOR_SIZE 512 |
Bill Richardson | 35c69cc | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 330 | enum futil_file_type ft_recognize_gpt(uint8_t *buf, uint32_t len) |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 331 | { |
| 332 | GptHeader *h; |
| 333 | |
| 334 | /* GPT header starts at sector 1, is one sector long */ |
| 335 | if (len < 2 * DISK_SECTOR_SIZE) |
| 336 | return FILE_TYPE_UNKNOWN; |
| 337 | |
| 338 | h = (GptHeader *)(buf + DISK_SECTOR_SIZE); |
| 339 | |
| 340 | if (memcmp(h->signature, GPT_HEADER_SIGNATURE, |
| 341 | GPT_HEADER_SIGNATURE_SIZE) && |
| 342 | memcmp(h->signature, GPT_HEADER_SIGNATURE2, |
| 343 | GPT_HEADER_SIGNATURE_SIZE)) |
| 344 | return FILE_TYPE_UNKNOWN; |
| 345 | if (h->revision != GPT_HEADER_REVISION) |
| 346 | return FILE_TYPE_UNKNOWN; |
| 347 | if (h->size < MIN_SIZE_OF_HEADER || h->size > MAX_SIZE_OF_HEADER) |
| 348 | return FILE_TYPE_UNKNOWN; |
| 349 | |
| 350 | if (HeaderCrc(h) != h->header_crc32) |
| 351 | return FILE_TYPE_UNKNOWN; |
| 352 | |
| 353 | return FILE_TYPE_CHROMIUMOS_DISK; |
Bill Richardson | 15dc6fc | 2014-09-02 14:45:44 -0700 | [diff] [blame] | 354 | } |