1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2014 The ChromiumOS Authors
2*8617a60dSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
3*8617a60dSAndroid Build Coastguard Worker * found in the LICENSE file.
4*8617a60dSAndroid Build Coastguard Worker */
5*8617a60dSAndroid Build Coastguard Worker
6*8617a60dSAndroid Build Coastguard Worker #include <assert.h>
7*8617a60dSAndroid Build Coastguard Worker #include <errno.h>
8*8617a60dSAndroid Build Coastguard Worker #include <fcntl.h>
9*8617a60dSAndroid Build Coastguard Worker #if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
10*8617a60dSAndroid Build Coastguard Worker #include <linux/fs.h> /* For BLKGETSIZE64 */
11*8617a60dSAndroid Build Coastguard Worker #include <sys/sendfile.h>
12*8617a60dSAndroid Build Coastguard Worker #else
13*8617a60dSAndroid Build Coastguard Worker #include <copyfile.h>
14*8617a60dSAndroid Build Coastguard Worker #endif
15*8617a60dSAndroid Build Coastguard Worker #include <stdarg.h>
16*8617a60dSAndroid Build Coastguard Worker #include <stdint.h>
17*8617a60dSAndroid Build Coastguard Worker #include <stdio.h>
18*8617a60dSAndroid Build Coastguard Worker #include <stdlib.h>
19*8617a60dSAndroid Build Coastguard Worker #include <string.h>
20*8617a60dSAndroid Build Coastguard Worker #include <sys/ioctl.h>
21*8617a60dSAndroid Build Coastguard Worker #include <sys/mman.h>
22*8617a60dSAndroid Build Coastguard Worker #include <sys/stat.h>
23*8617a60dSAndroid Build Coastguard Worker #include <sys/types.h>
24*8617a60dSAndroid Build Coastguard Worker #include <sys/wait.h>
25*8617a60dSAndroid Build Coastguard Worker #include <unistd.h>
26*8617a60dSAndroid Build Coastguard Worker
27*8617a60dSAndroid Build Coastguard Worker #include "2common.h"
28*8617a60dSAndroid Build Coastguard Worker #include "2sha.h"
29*8617a60dSAndroid Build Coastguard Worker #include "2sysincludes.h"
30*8617a60dSAndroid Build Coastguard Worker #include "cgptlib_internal.h"
31*8617a60dSAndroid Build Coastguard Worker #include "file_type.h"
32*8617a60dSAndroid Build Coastguard Worker #include "futility.h"
33*8617a60dSAndroid Build Coastguard Worker #include "futility_options.h"
34*8617a60dSAndroid Build Coastguard Worker #include "host_misc.h"
35*8617a60dSAndroid Build Coastguard Worker
36*8617a60dSAndroid Build Coastguard Worker /* Default is to support everything we can */
37*8617a60dSAndroid Build Coastguard Worker enum vboot_version vboot_version = VBOOT_VERSION_ALL;
38*8617a60dSAndroid Build Coastguard Worker
39*8617a60dSAndroid Build Coastguard Worker int debugging_enabled;
vb2ex_printf(const char * func,const char * format,...)40*8617a60dSAndroid Build Coastguard Worker void vb2ex_printf(const char *func, const char *format, ...)
41*8617a60dSAndroid Build Coastguard Worker {
42*8617a60dSAndroid Build Coastguard Worker if (!debugging_enabled)
43*8617a60dSAndroid Build Coastguard Worker return;
44*8617a60dSAndroid Build Coastguard Worker
45*8617a60dSAndroid Build Coastguard Worker va_list ap;
46*8617a60dSAndroid Build Coastguard Worker va_start(ap, format);
47*8617a60dSAndroid Build Coastguard Worker if (func)
48*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: %s: ", func);
49*8617a60dSAndroid Build Coastguard Worker vfprintf(stderr, format, ap);
50*8617a60dSAndroid Build Coastguard Worker va_end(ap);
51*8617a60dSAndroid Build Coastguard Worker }
52*8617a60dSAndroid Build Coastguard Worker
is_null_terminated(const char * s,int len)53*8617a60dSAndroid Build Coastguard Worker static int is_null_terminated(const char *s, int len)
54*8617a60dSAndroid Build Coastguard Worker {
55*8617a60dSAndroid Build Coastguard Worker len--;
56*8617a60dSAndroid Build Coastguard Worker s += len;
57*8617a60dSAndroid Build Coastguard Worker while (len-- >= 0)
58*8617a60dSAndroid Build Coastguard Worker if (!*s--)
59*8617a60dSAndroid Build Coastguard Worker return 1;
60*8617a60dSAndroid Build Coastguard Worker return 0;
61*8617a60dSAndroid Build Coastguard Worker }
62*8617a60dSAndroid Build Coastguard Worker
max(uint32_t a,uint32_t b)63*8617a60dSAndroid Build Coastguard Worker static inline uint32_t max(uint32_t a, uint32_t b)
64*8617a60dSAndroid Build Coastguard Worker {
65*8617a60dSAndroid Build Coastguard Worker return a > b ? a : b;
66*8617a60dSAndroid Build Coastguard Worker }
67*8617a60dSAndroid Build Coastguard Worker
ft_recognize_gbb(uint8_t * buf,uint32_t len)68*8617a60dSAndroid Build Coastguard Worker enum futil_file_type ft_recognize_gbb(uint8_t *buf, uint32_t len)
69*8617a60dSAndroid Build Coastguard Worker {
70*8617a60dSAndroid Build Coastguard Worker struct vb2_gbb_header *gbb = (struct vb2_gbb_header *)buf;
71*8617a60dSAndroid Build Coastguard Worker
72*8617a60dSAndroid Build Coastguard Worker if (memcmp(gbb->signature, VB2_GBB_SIGNATURE, VB2_GBB_SIGNATURE_SIZE))
73*8617a60dSAndroid Build Coastguard Worker return FILE_TYPE_UNKNOWN;
74*8617a60dSAndroid Build Coastguard Worker if (gbb->major_version > VB2_GBB_MAJOR_VER)
75*8617a60dSAndroid Build Coastguard Worker return FILE_TYPE_UNKNOWN;
76*8617a60dSAndroid Build Coastguard Worker if (sizeof(struct vb2_gbb_header) > len)
77*8617a60dSAndroid Build Coastguard Worker return FILE_TYPE_UNKNOWN;
78*8617a60dSAndroid Build Coastguard Worker
79*8617a60dSAndroid Build Coastguard Worker /* close enough */
80*8617a60dSAndroid Build Coastguard Worker return FILE_TYPE_GBB;
81*8617a60dSAndroid Build Coastguard Worker }
82*8617a60dSAndroid Build Coastguard Worker
futil_valid_gbb_header(struct vb2_gbb_header * gbb,uint32_t len,uint32_t * maxlen_ptr)83*8617a60dSAndroid Build Coastguard Worker int futil_valid_gbb_header(struct vb2_gbb_header *gbb, uint32_t len,
84*8617a60dSAndroid Build Coastguard Worker uint32_t *maxlen_ptr)
85*8617a60dSAndroid Build Coastguard Worker {
86*8617a60dSAndroid Build Coastguard Worker if (len < sizeof(struct vb2_gbb_header))
87*8617a60dSAndroid Build Coastguard Worker return 0;
88*8617a60dSAndroid Build Coastguard Worker
89*8617a60dSAndroid Build Coastguard Worker if (memcmp(gbb->signature, VB2_GBB_SIGNATURE, VB2_GBB_SIGNATURE_SIZE))
90*8617a60dSAndroid Build Coastguard Worker return 0;
91*8617a60dSAndroid Build Coastguard Worker if (gbb->major_version != VB2_GBB_MAJOR_VER)
92*8617a60dSAndroid Build Coastguard Worker return 0;
93*8617a60dSAndroid Build Coastguard Worker
94*8617a60dSAndroid Build Coastguard Worker /* Check limits first, to help identify problems */
95*8617a60dSAndroid Build Coastguard Worker if (maxlen_ptr) {
96*8617a60dSAndroid Build Coastguard Worker uint32_t maxlen = gbb->header_size;
97*8617a60dSAndroid Build Coastguard Worker maxlen = max(maxlen,
98*8617a60dSAndroid Build Coastguard Worker gbb->hwid_offset + gbb->hwid_size);
99*8617a60dSAndroid Build Coastguard Worker maxlen = max(maxlen,
100*8617a60dSAndroid Build Coastguard Worker gbb->rootkey_offset + gbb->rootkey_size);
101*8617a60dSAndroid Build Coastguard Worker maxlen = max(maxlen,
102*8617a60dSAndroid Build Coastguard Worker gbb->bmpfv_offset + gbb->bmpfv_size);
103*8617a60dSAndroid Build Coastguard Worker maxlen = max(maxlen,
104*8617a60dSAndroid Build Coastguard Worker gbb->recovery_key_offset + gbb->recovery_key_size);
105*8617a60dSAndroid Build Coastguard Worker *maxlen_ptr = maxlen;
106*8617a60dSAndroid Build Coastguard Worker }
107*8617a60dSAndroid Build Coastguard Worker
108*8617a60dSAndroid Build Coastguard Worker if (gbb->header_size != EXPECTED_VB2_GBB_HEADER_SIZE ||
109*8617a60dSAndroid Build Coastguard Worker gbb->header_size > len)
110*8617a60dSAndroid Build Coastguard Worker return 0;
111*8617a60dSAndroid Build Coastguard Worker if (gbb->hwid_offset < EXPECTED_VB2_GBB_HEADER_SIZE)
112*8617a60dSAndroid Build Coastguard Worker return 0;
113*8617a60dSAndroid Build Coastguard Worker if ((uint64_t)gbb->hwid_offset + gbb->hwid_size > len)
114*8617a60dSAndroid Build Coastguard Worker return 0;
115*8617a60dSAndroid Build Coastguard Worker if (gbb->hwid_size) {
116*8617a60dSAndroid Build Coastguard Worker const char *s = (const char *)
117*8617a60dSAndroid Build Coastguard Worker ((uint8_t *)gbb + gbb->hwid_offset);
118*8617a60dSAndroid Build Coastguard Worker if (!is_null_terminated(s, gbb->hwid_size))
119*8617a60dSAndroid Build Coastguard Worker return 0;
120*8617a60dSAndroid Build Coastguard Worker }
121*8617a60dSAndroid Build Coastguard Worker if (gbb->rootkey_offset < EXPECTED_VB2_GBB_HEADER_SIZE)
122*8617a60dSAndroid Build Coastguard Worker return 0;
123*8617a60dSAndroid Build Coastguard Worker if ((uint64_t)gbb->rootkey_offset + gbb->rootkey_size > len)
124*8617a60dSAndroid Build Coastguard Worker return 0;
125*8617a60dSAndroid Build Coastguard Worker
126*8617a60dSAndroid Build Coastguard Worker if (gbb->bmpfv_offset < EXPECTED_VB2_GBB_HEADER_SIZE)
127*8617a60dSAndroid Build Coastguard Worker return 0;
128*8617a60dSAndroid Build Coastguard Worker if ((uint64_t)gbb->bmpfv_offset + gbb->bmpfv_size > len)
129*8617a60dSAndroid Build Coastguard Worker return 0;
130*8617a60dSAndroid Build Coastguard Worker if (gbb->recovery_key_offset < EXPECTED_VB2_GBB_HEADER_SIZE)
131*8617a60dSAndroid Build Coastguard Worker return 0;
132*8617a60dSAndroid Build Coastguard Worker if ((uint64_t)gbb->recovery_key_offset + gbb->recovery_key_size > len)
133*8617a60dSAndroid Build Coastguard Worker return 0;
134*8617a60dSAndroid Build Coastguard Worker
135*8617a60dSAndroid Build Coastguard Worker /* Seems legit... */
136*8617a60dSAndroid Build Coastguard Worker return 1;
137*8617a60dSAndroid Build Coastguard Worker }
138*8617a60dSAndroid Build Coastguard Worker
139*8617a60dSAndroid Build Coastguard Worker /* For GBB v1.2 and later, print the stored digest of the HWID (and whether
140*8617a60dSAndroid Build Coastguard Worker * it's correct). Return true if it is correct. */
print_hwid_digest(struct vb2_gbb_header * gbb,const char * banner)141*8617a60dSAndroid Build Coastguard Worker int print_hwid_digest(struct vb2_gbb_header *gbb, const char *banner)
142*8617a60dSAndroid Build Coastguard Worker {
143*8617a60dSAndroid Build Coastguard Worker FT_READABLE_PRINT("%s", banner);
144*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("hwid::digest::algorithm::2::SHA256\n");
145*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("hwid::digest::hex::");
146*8617a60dSAndroid Build Coastguard Worker
147*8617a60dSAndroid Build Coastguard Worker /* There isn't one for v1.1 and earlier, so assume it's good. */
148*8617a60dSAndroid Build Coastguard Worker if (gbb->minor_version < 2) {
149*8617a60dSAndroid Build Coastguard Worker printf("<none>\n");
150*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("hwid::digest::ignored\n");
151*8617a60dSAndroid Build Coastguard Worker return 1;
152*8617a60dSAndroid Build Coastguard Worker }
153*8617a60dSAndroid Build Coastguard Worker
154*8617a60dSAndroid Build Coastguard Worker uint8_t *buf = (uint8_t *)gbb;
155*8617a60dSAndroid Build Coastguard Worker char *hwid_str = (char *)(buf + gbb->hwid_offset);
156*8617a60dSAndroid Build Coastguard Worker int is_valid = 0;
157*8617a60dSAndroid Build Coastguard Worker struct vb2_hash hash;
158*8617a60dSAndroid Build Coastguard Worker
159*8617a60dSAndroid Build Coastguard Worker if (VB2_SUCCESS == vb2_hash_calculate(false, buf + gbb->hwid_offset,
160*8617a60dSAndroid Build Coastguard Worker strlen(hwid_str), VB2_HASH_SHA256,
161*8617a60dSAndroid Build Coastguard Worker &hash)) {
162*8617a60dSAndroid Build Coastguard Worker int i;
163*8617a60dSAndroid Build Coastguard Worker is_valid = 1;
164*8617a60dSAndroid Build Coastguard Worker /* print it, comparing as we go */
165*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < sizeof(hash.sha256); i++) {
166*8617a60dSAndroid Build Coastguard Worker printf("%02x", gbb->hwid_digest[i]);
167*8617a60dSAndroid Build Coastguard Worker if (gbb->hwid_digest[i] != hash.sha256[i])
168*8617a60dSAndroid Build Coastguard Worker is_valid = 0;
169*8617a60dSAndroid Build Coastguard Worker }
170*8617a60dSAndroid Build Coastguard Worker }
171*8617a60dSAndroid Build Coastguard Worker
172*8617a60dSAndroid Build Coastguard Worker FT_PRINT_RAW("", "\n");
173*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" %s\n", "hwid::digest::%s\n", is_valid ? "valid" : "invalid");
174*8617a60dSAndroid Build Coastguard Worker return is_valid;
175*8617a60dSAndroid Build Coastguard Worker }
176*8617a60dSAndroid Build Coastguard Worker
177*8617a60dSAndroid Build Coastguard Worker /* Deprecated. Use futil_set_gbb_hwid in future. */
178*8617a60dSAndroid Build Coastguard Worker /* For GBB v1.2 and later, update the hwid_digest field. */
update_hwid_digest(struct vb2_gbb_header * gbb)179*8617a60dSAndroid Build Coastguard Worker void update_hwid_digest(struct vb2_gbb_header *gbb)
180*8617a60dSAndroid Build Coastguard Worker {
181*8617a60dSAndroid Build Coastguard Worker /* There isn't one for v1.1 and earlier */
182*8617a60dSAndroid Build Coastguard Worker if (gbb->minor_version < 2)
183*8617a60dSAndroid Build Coastguard Worker return;
184*8617a60dSAndroid Build Coastguard Worker
185*8617a60dSAndroid Build Coastguard Worker uint8_t *buf = (uint8_t *)gbb;
186*8617a60dSAndroid Build Coastguard Worker char *hwid_str = (char *)(buf + gbb->hwid_offset);
187*8617a60dSAndroid Build Coastguard Worker struct vb2_hash hash;
188*8617a60dSAndroid Build Coastguard Worker
189*8617a60dSAndroid Build Coastguard Worker vb2_hash_calculate(false, buf + gbb->hwid_offset, strlen(hwid_str),
190*8617a60dSAndroid Build Coastguard Worker VB2_HASH_SHA256, &hash);
191*8617a60dSAndroid Build Coastguard Worker memcpy(gbb->hwid_digest, hash.raw, sizeof(gbb->hwid_digest));
192*8617a60dSAndroid Build Coastguard Worker }
193*8617a60dSAndroid Build Coastguard Worker
194*8617a60dSAndroid Build Coastguard Worker /* Sets the HWID string field inside a GBB header. */
futil_set_gbb_hwid(struct vb2_gbb_header * gbb,const char * hwid)195*8617a60dSAndroid Build Coastguard Worker int futil_set_gbb_hwid(struct vb2_gbb_header *gbb, const char *hwid)
196*8617a60dSAndroid Build Coastguard Worker {
197*8617a60dSAndroid Build Coastguard Worker uint8_t *to = (uint8_t *)gbb + gbb->hwid_offset;
198*8617a60dSAndroid Build Coastguard Worker struct vb2_hash hash;
199*8617a60dSAndroid Build Coastguard Worker size_t len;
200*8617a60dSAndroid Build Coastguard Worker
201*8617a60dSAndroid Build Coastguard Worker assert(hwid);
202*8617a60dSAndroid Build Coastguard Worker len = strlen(hwid);
203*8617a60dSAndroid Build Coastguard Worker if (len >= gbb->hwid_size)
204*8617a60dSAndroid Build Coastguard Worker return -1;
205*8617a60dSAndroid Build Coastguard Worker
206*8617a60dSAndroid Build Coastguard Worker /* Zero whole area so we won't have garbage after NUL. */
207*8617a60dSAndroid Build Coastguard Worker memset(to, 0, gbb->hwid_size);
208*8617a60dSAndroid Build Coastguard Worker memcpy(to, hwid, len);
209*8617a60dSAndroid Build Coastguard Worker
210*8617a60dSAndroid Build Coastguard Worker /* major_version starts from 1 and digest must be updated since v1.2. */
211*8617a60dSAndroid Build Coastguard Worker if (gbb->major_version == 1 && gbb->minor_version < 2)
212*8617a60dSAndroid Build Coastguard Worker return 0;
213*8617a60dSAndroid Build Coastguard Worker
214*8617a60dSAndroid Build Coastguard Worker VB2_TRY(vb2_hash_calculate(false, to, len, VB2_HASH_SHA256, &hash));
215*8617a60dSAndroid Build Coastguard Worker memcpy(gbb->hwid_digest, hash.raw, sizeof(gbb->hwid_digest));
216*8617a60dSAndroid Build Coastguard Worker return VB2_SUCCESS;
217*8617a60dSAndroid Build Coastguard Worker }
218*8617a60dSAndroid Build Coastguard Worker
futil_copy_file(const char * infile,const char * outfile)219*8617a60dSAndroid Build Coastguard Worker int futil_copy_file(const char *infile, const char *outfile)
220*8617a60dSAndroid Build Coastguard Worker {
221*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("%s -> %s\n", infile, outfile);
222*8617a60dSAndroid Build Coastguard Worker
223*8617a60dSAndroid Build Coastguard Worker int ifd, ofd;
224*8617a60dSAndroid Build Coastguard Worker if ((ifd = open(infile, O_RDONLY)) == -1) {
225*8617a60dSAndroid Build Coastguard Worker ERROR("Cannot open '%s', %s.\n", infile, strerror(errno));
226*8617a60dSAndroid Build Coastguard Worker return -1;
227*8617a60dSAndroid Build Coastguard Worker }
228*8617a60dSAndroid Build Coastguard Worker if ((ofd = creat(outfile, 0660)) == -1) {
229*8617a60dSAndroid Build Coastguard Worker ERROR("Cannot open '%s', %s.\n", outfile, strerror(errno));
230*8617a60dSAndroid Build Coastguard Worker close(ifd);
231*8617a60dSAndroid Build Coastguard Worker return -1;
232*8617a60dSAndroid Build Coastguard Worker }
233*8617a60dSAndroid Build Coastguard Worker struct stat finfo = {0};
234*8617a60dSAndroid Build Coastguard Worker if (fstat(ifd, &finfo) < 0) {
235*8617a60dSAndroid Build Coastguard Worker ERROR("Cannot fstat '%s' as %s.\n", infile, strerror(errno));
236*8617a60dSAndroid Build Coastguard Worker close (ifd);
237*8617a60dSAndroid Build Coastguard Worker close (ofd);
238*8617a60dSAndroid Build Coastguard Worker return -1;
239*8617a60dSAndroid Build Coastguard Worker }
240*8617a60dSAndroid Build Coastguard Worker #if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
241*8617a60dSAndroid Build Coastguard Worker ssize_t ret = sendfile(ofd, ifd, NULL, finfo.st_size);
242*8617a60dSAndroid Build Coastguard Worker #else
243*8617a60dSAndroid Build Coastguard Worker ssize_t ret = fcopyfile(ifd, ofd, 0, COPYFILE_ALL);
244*8617a60dSAndroid Build Coastguard Worker #endif
245*8617a60dSAndroid Build Coastguard Worker close(ifd);
246*8617a60dSAndroid Build Coastguard Worker close(ofd);
247*8617a60dSAndroid Build Coastguard Worker if (ret == -1) {
248*8617a60dSAndroid Build Coastguard Worker ERROR("Cannot copy '%s'->'%s', %s.\n", infile,
249*8617a60dSAndroid Build Coastguard Worker outfile, strerror(errno));
250*8617a60dSAndroid Build Coastguard Worker }
251*8617a60dSAndroid Build Coastguard Worker return ret;
252*8617a60dSAndroid Build Coastguard Worker }
253*8617a60dSAndroid Build Coastguard Worker
futil_open_file(const char * infile,int * fd,enum file_mode mode)254*8617a60dSAndroid Build Coastguard Worker enum futil_file_err futil_open_file(const char *infile, int *fd,
255*8617a60dSAndroid Build Coastguard Worker enum file_mode mode)
256*8617a60dSAndroid Build Coastguard Worker {
257*8617a60dSAndroid Build Coastguard Worker if (mode == FILE_RW) {
258*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("open RW %s\n", infile);
259*8617a60dSAndroid Build Coastguard Worker *fd = open(infile, O_RDWR);
260*8617a60dSAndroid Build Coastguard Worker if (*fd < 0) {
261*8617a60dSAndroid Build Coastguard Worker ERROR("Can't open %s for writing: %s\n", infile,
262*8617a60dSAndroid Build Coastguard Worker strerror(errno));
263*8617a60dSAndroid Build Coastguard Worker return FILE_ERR_OPEN;
264*8617a60dSAndroid Build Coastguard Worker }
265*8617a60dSAndroid Build Coastguard Worker } else {
266*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("open RO %s\n", infile);
267*8617a60dSAndroid Build Coastguard Worker *fd = open(infile, O_RDONLY);
268*8617a60dSAndroid Build Coastguard Worker if (*fd < 0) {
269*8617a60dSAndroid Build Coastguard Worker ERROR("Can't open %s for reading: %s\n", infile,
270*8617a60dSAndroid Build Coastguard Worker strerror(errno));
271*8617a60dSAndroid Build Coastguard Worker return FILE_ERR_OPEN;
272*8617a60dSAndroid Build Coastguard Worker }
273*8617a60dSAndroid Build Coastguard Worker }
274*8617a60dSAndroid Build Coastguard Worker return FILE_ERR_NONE;
275*8617a60dSAndroid Build Coastguard Worker }
276*8617a60dSAndroid Build Coastguard Worker
futil_close_file(int fd)277*8617a60dSAndroid Build Coastguard Worker enum futil_file_err futil_close_file(int fd)
278*8617a60dSAndroid Build Coastguard Worker {
279*8617a60dSAndroid Build Coastguard Worker if (fd >= 0 && close(fd)) {
280*8617a60dSAndroid Build Coastguard Worker ERROR("Closing ifd: %s\n", strerror(errno));
281*8617a60dSAndroid Build Coastguard Worker return FILE_ERR_CLOSE;
282*8617a60dSAndroid Build Coastguard Worker }
283*8617a60dSAndroid Build Coastguard Worker return FILE_ERR_NONE;
284*8617a60dSAndroid Build Coastguard Worker }
285*8617a60dSAndroid Build Coastguard Worker
futil_map_file(int fd,enum file_mode mode,uint8_t ** buf,uint32_t * len)286*8617a60dSAndroid Build Coastguard Worker enum futil_file_err futil_map_file(int fd, enum file_mode mode,
287*8617a60dSAndroid Build Coastguard Worker uint8_t **buf, uint32_t *len)
288*8617a60dSAndroid Build Coastguard Worker {
289*8617a60dSAndroid Build Coastguard Worker struct stat sb;
290*8617a60dSAndroid Build Coastguard Worker void *mmap_ptr;
291*8617a60dSAndroid Build Coastguard Worker uint32_t reasonable_len;
292*8617a60dSAndroid Build Coastguard Worker
293*8617a60dSAndroid Build Coastguard Worker if (0 != fstat(fd, &sb)) {
294*8617a60dSAndroid Build Coastguard Worker ERROR("Can't stat input file: %s\n", strerror(errno));
295*8617a60dSAndroid Build Coastguard Worker return FILE_ERR_STAT;
296*8617a60dSAndroid Build Coastguard Worker }
297*8617a60dSAndroid Build Coastguard Worker
298*8617a60dSAndroid Build Coastguard Worker #if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
299*8617a60dSAndroid Build Coastguard Worker if (S_ISBLK(sb.st_mode))
300*8617a60dSAndroid Build Coastguard Worker ioctl(fd, BLKGETSIZE64, &sb.st_size);
301*8617a60dSAndroid Build Coastguard Worker #endif
302*8617a60dSAndroid Build Coastguard Worker
303*8617a60dSAndroid Build Coastguard Worker /* If the image is larger than 2^32 bytes, it's wrong. */
304*8617a60dSAndroid Build Coastguard Worker if (sb.st_size < 0 || sb.st_size > UINT32_MAX) {
305*8617a60dSAndroid Build Coastguard Worker ERROR("Image size is unreasonable\n");
306*8617a60dSAndroid Build Coastguard Worker return FILE_ERR_SIZE;
307*8617a60dSAndroid Build Coastguard Worker }
308*8617a60dSAndroid Build Coastguard Worker reasonable_len = (uint32_t)sb.st_size;
309*8617a60dSAndroid Build Coastguard Worker
310*8617a60dSAndroid Build Coastguard Worker if (mode == FILE_RW)
311*8617a60dSAndroid Build Coastguard Worker mmap_ptr = mmap(0, sb.st_size,
312*8617a60dSAndroid Build Coastguard Worker PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
313*8617a60dSAndroid Build Coastguard Worker else
314*8617a60dSAndroid Build Coastguard Worker mmap_ptr = mmap(0, sb.st_size,
315*8617a60dSAndroid Build Coastguard Worker PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
316*8617a60dSAndroid Build Coastguard Worker
317*8617a60dSAndroid Build Coastguard Worker if (mmap_ptr == MAP_FAILED) {
318*8617a60dSAndroid Build Coastguard Worker ERROR("Can't mmap %s file: %s\n",
319*8617a60dSAndroid Build Coastguard Worker mode == FILE_RW ? "output" : "input", strerror(errno));
320*8617a60dSAndroid Build Coastguard Worker return FILE_ERR_MMAP;
321*8617a60dSAndroid Build Coastguard Worker }
322*8617a60dSAndroid Build Coastguard Worker
323*8617a60dSAndroid Build Coastguard Worker *buf = (uint8_t *)mmap_ptr;
324*8617a60dSAndroid Build Coastguard Worker *len = reasonable_len;
325*8617a60dSAndroid Build Coastguard Worker return FILE_ERR_NONE;
326*8617a60dSAndroid Build Coastguard Worker }
327*8617a60dSAndroid Build Coastguard Worker
futil_unmap_file(int fd,enum file_mode mode,uint8_t * buf,uint32_t len)328*8617a60dSAndroid Build Coastguard Worker enum futil_file_err futil_unmap_file(int fd, enum file_mode mode,
329*8617a60dSAndroid Build Coastguard Worker uint8_t *buf, uint32_t len)
330*8617a60dSAndroid Build Coastguard Worker {
331*8617a60dSAndroid Build Coastguard Worker void *mmap_ptr = buf;
332*8617a60dSAndroid Build Coastguard Worker enum futil_file_err err = FILE_ERR_NONE;
333*8617a60dSAndroid Build Coastguard Worker
334*8617a60dSAndroid Build Coastguard Worker if (mode == FILE_RW &&
335*8617a60dSAndroid Build Coastguard Worker (0 != msync(mmap_ptr, len, MS_SYNC | MS_INVALIDATE))) {
336*8617a60dSAndroid Build Coastguard Worker ERROR("msync failed: %s\n", strerror(errno));
337*8617a60dSAndroid Build Coastguard Worker err = FILE_ERR_MSYNC;
338*8617a60dSAndroid Build Coastguard Worker }
339*8617a60dSAndroid Build Coastguard Worker
340*8617a60dSAndroid Build Coastguard Worker if (0 != munmap(mmap_ptr, len)) {
341*8617a60dSAndroid Build Coastguard Worker ERROR("Can't munmap pointer: %s\n", strerror(errno));
342*8617a60dSAndroid Build Coastguard Worker if (err == FILE_ERR_NONE)
343*8617a60dSAndroid Build Coastguard Worker err = FILE_ERR_MUNMAP;
344*8617a60dSAndroid Build Coastguard Worker }
345*8617a60dSAndroid Build Coastguard Worker
346*8617a60dSAndroid Build Coastguard Worker return err;
347*8617a60dSAndroid Build Coastguard Worker }
348*8617a60dSAndroid Build Coastguard Worker
futil_open_and_map_file(const char * infile,int * fd,enum file_mode mode,uint8_t ** buf,uint32_t * len)349*8617a60dSAndroid Build Coastguard Worker enum futil_file_err futil_open_and_map_file(const char *infile, int *fd,
350*8617a60dSAndroid Build Coastguard Worker enum file_mode mode, uint8_t **buf,
351*8617a60dSAndroid Build Coastguard Worker uint32_t *len)
352*8617a60dSAndroid Build Coastguard Worker {
353*8617a60dSAndroid Build Coastguard Worker enum futil_file_err rv = futil_open_file(infile, fd, mode);
354*8617a60dSAndroid Build Coastguard Worker if (rv != FILE_ERR_NONE)
355*8617a60dSAndroid Build Coastguard Worker return rv;
356*8617a60dSAndroid Build Coastguard Worker
357*8617a60dSAndroid Build Coastguard Worker rv = futil_map_file(*fd, mode, buf, len);
358*8617a60dSAndroid Build Coastguard Worker if (rv != FILE_ERR_NONE)
359*8617a60dSAndroid Build Coastguard Worker futil_close_file(*fd);
360*8617a60dSAndroid Build Coastguard Worker
361*8617a60dSAndroid Build Coastguard Worker return rv;
362*8617a60dSAndroid Build Coastguard Worker }
363*8617a60dSAndroid Build Coastguard Worker
futil_unmap_and_close_file(int fd,enum file_mode mode,uint8_t * buf,uint32_t len)364*8617a60dSAndroid Build Coastguard Worker enum futil_file_err futil_unmap_and_close_file(int fd, enum file_mode mode,
365*8617a60dSAndroid Build Coastguard Worker uint8_t *buf, uint32_t len)
366*8617a60dSAndroid Build Coastguard Worker {
367*8617a60dSAndroid Build Coastguard Worker enum futil_file_err rv = FILE_ERR_NONE;
368*8617a60dSAndroid Build Coastguard Worker
369*8617a60dSAndroid Build Coastguard Worker if (buf)
370*8617a60dSAndroid Build Coastguard Worker rv = futil_unmap_file(fd, mode, buf, len);
371*8617a60dSAndroid Build Coastguard Worker if (rv != FILE_ERR_NONE)
372*8617a60dSAndroid Build Coastguard Worker return rv;
373*8617a60dSAndroid Build Coastguard Worker
374*8617a60dSAndroid Build Coastguard Worker if (fd != -1)
375*8617a60dSAndroid Build Coastguard Worker return futil_close_file(fd);
376*8617a60dSAndroid Build Coastguard Worker else
377*8617a60dSAndroid Build Coastguard Worker return FILE_ERR_NONE;
378*8617a60dSAndroid Build Coastguard Worker }
379*8617a60dSAndroid Build Coastguard Worker
380*8617a60dSAndroid Build Coastguard Worker #define DISK_SECTOR_SIZE 512
ft_recognize_gpt(uint8_t * buf,uint32_t len)381*8617a60dSAndroid Build Coastguard Worker enum futil_file_type ft_recognize_gpt(uint8_t *buf, uint32_t len)
382*8617a60dSAndroid Build Coastguard Worker {
383*8617a60dSAndroid Build Coastguard Worker GptHeader *h;
384*8617a60dSAndroid Build Coastguard Worker
385*8617a60dSAndroid Build Coastguard Worker /* GPT header starts at sector 1, is one sector long */
386*8617a60dSAndroid Build Coastguard Worker if (len < 2 * DISK_SECTOR_SIZE)
387*8617a60dSAndroid Build Coastguard Worker return FILE_TYPE_UNKNOWN;
388*8617a60dSAndroid Build Coastguard Worker
389*8617a60dSAndroid Build Coastguard Worker h = (GptHeader *)(buf + DISK_SECTOR_SIZE);
390*8617a60dSAndroid Build Coastguard Worker
391*8617a60dSAndroid Build Coastguard Worker if (memcmp(h->signature, GPT_HEADER_SIGNATURE,
392*8617a60dSAndroid Build Coastguard Worker GPT_HEADER_SIGNATURE_SIZE) &&
393*8617a60dSAndroid Build Coastguard Worker memcmp(h->signature, GPT_HEADER_SIGNATURE2,
394*8617a60dSAndroid Build Coastguard Worker GPT_HEADER_SIGNATURE_SIZE))
395*8617a60dSAndroid Build Coastguard Worker return FILE_TYPE_UNKNOWN;
396*8617a60dSAndroid Build Coastguard Worker if (h->revision != GPT_HEADER_REVISION)
397*8617a60dSAndroid Build Coastguard Worker return FILE_TYPE_UNKNOWN;
398*8617a60dSAndroid Build Coastguard Worker if (h->size < MIN_SIZE_OF_HEADER || h->size > MAX_SIZE_OF_HEADER)
399*8617a60dSAndroid Build Coastguard Worker return FILE_TYPE_UNKNOWN;
400*8617a60dSAndroid Build Coastguard Worker
401*8617a60dSAndroid Build Coastguard Worker if (HeaderCrc(h) != h->header_crc32)
402*8617a60dSAndroid Build Coastguard Worker return FILE_TYPE_UNKNOWN;
403*8617a60dSAndroid Build Coastguard Worker
404*8617a60dSAndroid Build Coastguard Worker return FILE_TYPE_CHROMIUMOS_DISK;
405*8617a60dSAndroid Build Coastguard Worker }
406*8617a60dSAndroid Build Coastguard Worker
parse_digest_or_die(uint8_t * buf,int len,const char * str)407*8617a60dSAndroid Build Coastguard Worker void parse_digest_or_die(uint8_t *buf, int len, const char *str)
408*8617a60dSAndroid Build Coastguard Worker {
409*8617a60dSAndroid Build Coastguard Worker if (!parse_hash(buf, len, str)) {
410*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid DIGEST \"%s\"\n", str);
411*8617a60dSAndroid Build Coastguard Worker exit(1);
412*8617a60dSAndroid Build Coastguard Worker }
413*8617a60dSAndroid Build Coastguard Worker }
414*8617a60dSAndroid Build Coastguard Worker
print_bytes(const void * ptr,size_t len)415*8617a60dSAndroid Build Coastguard Worker void print_bytes(const void *ptr, size_t len)
416*8617a60dSAndroid Build Coastguard Worker {
417*8617a60dSAndroid Build Coastguard Worker const uint8_t *buf = (const uint8_t *)ptr;
418*8617a60dSAndroid Build Coastguard Worker
419*8617a60dSAndroid Build Coastguard Worker for (size_t i = 0; i < len; i++)
420*8617a60dSAndroid Build Coastguard Worker printf("%02x", *buf++);
421*8617a60dSAndroid Build Coastguard Worker }
422*8617a60dSAndroid Build Coastguard Worker
write_to_file(const char * msg,const char * filename,uint8_t * start,size_t size)423*8617a60dSAndroid Build Coastguard Worker int write_to_file(const char *msg, const char *filename, uint8_t *start,
424*8617a60dSAndroid Build Coastguard Worker size_t size)
425*8617a60dSAndroid Build Coastguard Worker {
426*8617a60dSAndroid Build Coastguard Worker FILE *fp;
427*8617a60dSAndroid Build Coastguard Worker int r = 0;
428*8617a60dSAndroid Build Coastguard Worker
429*8617a60dSAndroid Build Coastguard Worker fp = fopen(filename, "wb");
430*8617a60dSAndroid Build Coastguard Worker if (!fp) {
431*8617a60dSAndroid Build Coastguard Worker r = errno;
432*8617a60dSAndroid Build Coastguard Worker ERROR("Unable to open %s for writing: %s\n", filename,
433*8617a60dSAndroid Build Coastguard Worker strerror(r));
434*8617a60dSAndroid Build Coastguard Worker return r;
435*8617a60dSAndroid Build Coastguard Worker }
436*8617a60dSAndroid Build Coastguard Worker
437*8617a60dSAndroid Build Coastguard Worker /* Don't write zero bytes */
438*8617a60dSAndroid Build Coastguard Worker if (size && 1 != fwrite(start, size, 1, fp)) {
439*8617a60dSAndroid Build Coastguard Worker r = errno;
440*8617a60dSAndroid Build Coastguard Worker ERROR("Unable to write to %s: %s\n", filename, strerror(r));
441*8617a60dSAndroid Build Coastguard Worker }
442*8617a60dSAndroid Build Coastguard Worker
443*8617a60dSAndroid Build Coastguard Worker if (fclose(fp) != 0) {
444*8617a60dSAndroid Build Coastguard Worker int e = errno;
445*8617a60dSAndroid Build Coastguard Worker ERROR("Unable to close %s: %s\n", filename, strerror(e));
446*8617a60dSAndroid Build Coastguard Worker if (!r)
447*8617a60dSAndroid Build Coastguard Worker r = e;
448*8617a60dSAndroid Build Coastguard Worker }
449*8617a60dSAndroid Build Coastguard Worker
450*8617a60dSAndroid Build Coastguard Worker if (!r && msg)
451*8617a60dSAndroid Build Coastguard Worker printf("%s %s\n", msg, filename);
452*8617a60dSAndroid Build Coastguard Worker
453*8617a60dSAndroid Build Coastguard Worker return r;
454*8617a60dSAndroid Build Coastguard Worker }
455