12559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson/*
22559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson * Copyright 2015 The Chromium OS Authors. All rights reserved.
32559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson * Use of this source code is governed by a BSD-style license that can be
42559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson * found in the LICENSE file.
52559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson */
62559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
72559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson#include <errno.h>
82559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson#include <fcntl.h>
92559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson#include <stdint.h>
102559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson#include <stdio.h>
112559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson#include <stdlib.h>
122559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson#include <string.h>
132559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson#include <sys/stat.h>
142559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson#include <sys/types.h>
152559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson#include <unistd.h>
162559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
172559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson#include "file_type.h"
182559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson#include "futility.h"
192559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson#include "gbb_header.h"
202559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
212559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson/* Human-readable strings */
222559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardsonstatic const char * const type_strings[] = {
232559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	"unknown",
242559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	"VbPublicKey",
252559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	"VbKeyBlock",
262559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	"VbFirmwarePreamble",
272559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	"GBB",
282559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	"Chrome OS BIOS image",
292559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	"Cr-48 Chrome OS BIOS image",
302559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	"VbKernelPreamble",
312559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	"raw firmware",
322559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	"raw kernel",
332559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	"chromiumos disk image",
344805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson	"VbPrivateKey",
352559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson};
362559338dbdacbcbd3ae426337403196135bbc7e8Bill RichardsonBUILD_ASSERT(ARRAY_SIZE(type_strings) == NUM_FILE_TYPES);
372559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
382559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardsonconst char * const futil_file_type_str(enum futil_file_type type)
392559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson{
4005987b159acb9737707b9ef92b818ac434ef8c3dDavid Riley	if ((int) type < 0 || type >= NUM_FILE_TYPES)
412559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		type = FILE_TYPE_UNKNOWN;
422559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
432559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	return type_strings[type];
442559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson}
452559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
462559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson/* Try these in order so we recognize the larger objects first */
472559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardsonenum futil_file_type (*recognizers[])(uint8_t *buf, uint32_t len) = {
482559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	&recognize_gpt,
492559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	&recognize_bios_image,
502559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	&recognize_gbb,
512559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	&recognize_vblock1,
524805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson	&recognize_privkey,
532559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson};
542559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
552559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson/* Try to figure out what we're looking at */
562559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardsonenum futil_file_type futil_file_type_buf(uint8_t *buf, uint32_t len)
572559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson{
582559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	enum futil_file_type type;
592559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	int i;
602559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
612559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	for (i = 0; i < ARRAY_SIZE(recognizers); i++) {
622559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		type = recognizers[i](buf, len);
632559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		if (type != FILE_TYPE_UNKNOWN)
642559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson			return type;
652559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	}
662559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
672559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	return FILE_TYPE_UNKNOWN;
682559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson}
692559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
702559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardsonenum futil_file_err futil_file_type(const char *filename,
712559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson				    enum futil_file_type *type)
722559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson{
732559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	int ifd;
742559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	uint8_t *buf;
752559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	uint32_t buf_len;
762559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	struct stat sb;
772559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	enum futil_file_err err = FILE_ERR_NONE;
782559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
792559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	*type = FILE_TYPE_UNKNOWN;
802559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
812559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	ifd = open(filename, O_RDONLY);
822559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	if (ifd < 0) {
832559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		fprintf(stderr, "Can't open %s: %s\n",
842559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson			filename, strerror(errno));
852559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		return FILE_ERR_OPEN;
862559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	}
872559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
882559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	if (0 != fstat(ifd, &sb)) {
892559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		fprintf(stderr, "Can't stat input file: %s\n",
902559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson			strerror(errno));
912559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		return FILE_ERR_STAT;
922559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	}
932559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
942559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	if (S_ISREG(sb.st_mode) || S_ISBLK(sb.st_mode)) {
952559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		err = futil_map_file(ifd, MAP_RO, &buf, &buf_len);
962559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		if (err) {
972559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson			close(ifd);
982559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson			return err;
992559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		}
1002559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
1012559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		*type = futil_file_type_buf(buf, buf_len);
1022559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
1032559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		err = futil_unmap_file(ifd, MAP_RO, buf, buf_len);
1042559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		if (err) {
1052559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson			close(ifd);
1062559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson			return err;
1072559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		}
1082559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	} else if (S_ISDIR(sb.st_mode)) {
1092559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		err = FILE_ERR_DIR;
1102559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	} else if (S_ISCHR(sb.st_mode)) {
1112559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		err = FILE_ERR_CHR;
1122559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	} else if (S_ISFIFO(sb.st_mode)) {
1132559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		err = FILE_ERR_FIFO;
1142559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	} else if (S_ISSOCK(sb.st_mode)) {
1152559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		err = FILE_ERR_SOCK;
1162559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	}
1172559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
1182559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	if (close(ifd)) {
1192559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		fprintf(stderr, "Error when closing %s: %s\n",
1202559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson			filename, strerror(errno));
1212559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		return FILE_ERR_CLOSE;
1222559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	}
1232559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
1242559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	return err;
1252559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson}
126