mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-30 13:14:02 +00:00
futility: Reformat to use kernel coding style
This just reformats the futility sources to conform to the Linux kernel coding style. No functional changes. BUG=chromium:224734 BRANCH=ToT TEST=make runtests Change-Id: I82df07dd3f8be2ad2f3df24cebe00a9a378b13f4 Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/213915 Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
committed by
chrome-internal-fetch
parent
8f15d74fd6
commit
31d95c2386
@@ -23,7 +23,6 @@
|
|||||||
#include "kernel_blob.h"
|
#include "kernel_blob.h"
|
||||||
#include "vboot_common.h"
|
#include "vboot_common.h"
|
||||||
|
|
||||||
|
|
||||||
/* Global opt */
|
/* Global opt */
|
||||||
static int opt_debug = 0;
|
static int opt_debug = 0;
|
||||||
|
|
||||||
@@ -37,20 +36,20 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct option long_opts[] = {
|
static const struct option long_opts[] = {
|
||||||
{"sign", 1, 0, OPT_MODE_SIGN },
|
{"sign", 1, 0, OPT_MODE_SIGN},
|
||||||
{"verify", 1, 0, OPT_MODE_VERIFY },
|
{"verify", 1, 0, OPT_MODE_VERIFY},
|
||||||
{"keyblock", 1, 0, OPT_KEYBLOCK },
|
{"keyblock", 1, 0, OPT_KEYBLOCK},
|
||||||
{"signprivate", 1, 0, OPT_SIGNPRIVATE },
|
{"signprivate", 1, 0, OPT_SIGNPRIVATE},
|
||||||
{"vblock", 1, 0, OPT_VBLOCK },
|
{"vblock", 1, 0, OPT_VBLOCK},
|
||||||
{"debug", 0, &opt_debug, 1 },
|
{"debug", 0, &opt_debug, 1},
|
||||||
{NULL, 0, 0, 0}
|
{NULL, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Print help and return error */
|
/* Print help and return error */
|
||||||
static int PrintHelp(const char *progname) {
|
static int PrintHelp(const char *progname)
|
||||||
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"This program is used to sign and verify developer-mode files\n");
|
"This is used to sign and verify developer-mode files\n");
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\n"
|
"\n"
|
||||||
"Usage: %s --sign <file> [PARAMETERS]\n"
|
"Usage: %s --sign <file> [PARAMETERS]\n"
|
||||||
@@ -59,25 +58,26 @@ static int PrintHelp(const char *progname) {
|
|||||||
" --keyblock <file> Key block in .keyblock format\n"
|
" --keyblock <file> Key block in .keyblock format\n"
|
||||||
" --signprivate <file>"
|
" --signprivate <file>"
|
||||||
" Private key to sign file data, in .vbprivk format\n"
|
" Private key to sign file data, in .vbprivk format\n"
|
||||||
" --vblock <file> Output signature in .vblock format\n"
|
" --vblock <file>"
|
||||||
"\n",
|
" Output signature in .vblock format\n"
|
||||||
progname);
|
"\n", progname);
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"OR\n\n"
|
"OR\n\n"
|
||||||
"Usage: %s --verify <file> [PARAMETERS]\n"
|
"Usage: %s --verify <file> [PARAMETERS]\n"
|
||||||
"\n"
|
"\n"
|
||||||
" Required parameters:\n"
|
" Required parameters:\n"
|
||||||
" --vblock <file> Signature file in .vblock format\n"
|
" --vblock <file>"
|
||||||
|
" Signature file in .vblock format\n"
|
||||||
"\n"
|
"\n"
|
||||||
" Optional parameters:\n"
|
" Optional parameters:\n"
|
||||||
" --keyblock <file>"
|
" --keyblock <file>"
|
||||||
" Extract .keyblock to file if verification succeeds\n"
|
" Extract .keyblock to file if verification succeeds\n"
|
||||||
"\n",
|
"\n", progname);
|
||||||
progname);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Debug(const char *format, ...) {
|
static void Debug(const char *format, ...)
|
||||||
|
{
|
||||||
if (!opt_debug)
|
if (!opt_debug)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -88,19 +88,19 @@ static void Debug(const char *format, ...) {
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Sign a file. We'll reuse the same structs used to sign kernels, to avoid
|
/* Sign a file. We'll reuse the same structs used to sign kernels, to avoid
|
||||||
having to declare yet another one for just this purpose. */
|
having to declare yet another one for just this purpose. */
|
||||||
static int Sign(const char* filename, const char* keyblock_file,
|
static int Sign(const char *filename, const char *keyblock_file,
|
||||||
const char* signprivate_file, const char* outfile) {
|
const char *signprivate_file, const char *outfile)
|
||||||
uint8_t* file_data;
|
{
|
||||||
|
uint8_t *file_data;
|
||||||
uint64_t file_size;
|
uint64_t file_size;
|
||||||
VbKeyBlockHeader* key_block;
|
VbKeyBlockHeader *key_block;
|
||||||
uint64_t key_block_size;
|
uint64_t key_block_size;
|
||||||
VbPrivateKey* signing_key;
|
VbPrivateKey *signing_key;
|
||||||
VbSignature* body_sig;
|
VbSignature *body_sig;
|
||||||
VbKernelPreambleHeader* preamble;
|
VbKernelPreambleHeader *preamble;
|
||||||
FILE* output_fp;
|
FILE *output_fp;
|
||||||
|
|
||||||
/* Read the file that we're going to sign. */
|
/* Read the file that we're going to sign. */
|
||||||
file_data = ReadFile(filename, &file_size);
|
file_data = ReadFile(filename, &file_size);
|
||||||
@@ -110,7 +110,8 @@ static int Sign(const char* filename, const char* keyblock_file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get the key block and read the private key corresponding to it. */
|
/* Get the key block and read the private key corresponding to it. */
|
||||||
key_block = (VbKeyBlockHeader*)ReadFile(keyblock_file, &key_block_size);
|
key_block =
|
||||||
|
(VbKeyBlockHeader *) ReadFile(keyblock_file, &key_block_size);
|
||||||
if (!key_block) {
|
if (!key_block) {
|
||||||
VbExError("Error reading key block.\n");
|
VbExError("Error reading key block.\n");
|
||||||
return 1;
|
return 1;
|
||||||
@@ -129,13 +130,11 @@ static int Sign(const char* filename, const char* keyblock_file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create preamble */
|
/* Create preamble */
|
||||||
preamble = CreateKernelPreamble((uint64_t)0,
|
preamble = CreateKernelPreamble((uint64_t) 0,
|
||||||
(uint64_t)0,
|
(uint64_t) 0,
|
||||||
(uint64_t)0,
|
(uint64_t) 0,
|
||||||
(uint64_t)0,
|
(uint64_t) 0,
|
||||||
body_sig,
|
body_sig, (uint64_t) 0, signing_key);
|
||||||
(uint64_t)0,
|
|
||||||
signing_key);
|
|
||||||
if (!preamble) {
|
if (!preamble) {
|
||||||
VbExError("Error creating preamble.\n");
|
VbExError("Error creating preamble.\n");
|
||||||
return 1;
|
return 1;
|
||||||
@@ -170,16 +169,17 @@ static int Sign(const char* filename, const char* keyblock_file,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Verify(const char* filename, const char* vblock_file,
|
static int Verify(const char *filename, const char *vblock_file,
|
||||||
const char* keyblock_file) {
|
const char *keyblock_file)
|
||||||
uint8_t* file_data;
|
{
|
||||||
|
uint8_t *file_data;
|
||||||
uint64_t file_size;
|
uint64_t file_size;
|
||||||
uint8_t* buf;
|
uint8_t *buf;
|
||||||
uint64_t buf_size;
|
uint64_t buf_size;
|
||||||
VbKeyBlockHeader* key_block;
|
VbKeyBlockHeader *key_block;
|
||||||
VbKernelPreambleHeader* preamble;
|
VbKernelPreambleHeader *preamble;
|
||||||
VbPublicKey* data_key;
|
VbPublicKey *data_key;
|
||||||
RSAPublicKey* rsa;
|
RSAPublicKey *rsa;
|
||||||
uint64_t current_buf_offset = 0;
|
uint64_t current_buf_offset = 0;
|
||||||
|
|
||||||
/* Read the file that we're going to verify. */
|
/* Read the file that we're going to verify. */
|
||||||
@@ -197,40 +197,46 @@ static int Verify(const char* filename, const char* vblock_file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Find the key block */
|
/* Find the key block */
|
||||||
key_block = (VbKeyBlockHeader*)buf;
|
key_block = (VbKeyBlockHeader *) buf;
|
||||||
Debug("Keyblock is 0x%" PRIx64 " bytes\n", key_block->key_block_size);
|
Debug("Keyblock is 0x%" PRIx64 " bytes\n", key_block->key_block_size);
|
||||||
current_buf_offset += key_block->key_block_size;
|
current_buf_offset += key_block->key_block_size;
|
||||||
if (current_buf_offset > buf_size) {
|
if (current_buf_offset > buf_size) {
|
||||||
VbExError("key_block_size advances past the end of the buffer\n");
|
VbExError
|
||||||
|
("key_block_size advances past the end of the buffer\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the preamble */
|
/* Find the preamble */
|
||||||
preamble = (VbKernelPreambleHeader*)(buf + current_buf_offset);
|
preamble = (VbKernelPreambleHeader *) (buf + current_buf_offset);
|
||||||
Debug("Preamble is 0x%" PRIx64 " bytes\n", preamble->preamble_size);
|
Debug("Preamble is 0x%" PRIx64 " bytes\n", preamble->preamble_size);
|
||||||
current_buf_offset += preamble->preamble_size;
|
current_buf_offset += preamble->preamble_size;
|
||||||
if (current_buf_offset > buf_size ) {
|
if (current_buf_offset > buf_size) {
|
||||||
VbExError("preamble_size advances past the end of the buffer\n");
|
VbExError
|
||||||
|
("preamble_size advances past the end of the buffer\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug("Current buf offset is at 0x%" PRIx64 " bytes\n", current_buf_offset);
|
Debug("Current buf offset is at 0x%" PRIx64 " bytes\n",
|
||||||
|
current_buf_offset);
|
||||||
|
|
||||||
/* Check the key block (hash only) */
|
/* Check the key block (hash only) */
|
||||||
if (0 != KeyBlockVerify(key_block, key_block->key_block_size, NULL, 1)) {
|
if (0 != KeyBlockVerify(key_block, key_block->key_block_size,
|
||||||
|
NULL, 1)) {
|
||||||
VbExError("Error verifying key block.\n");
|
VbExError("Error verifying key block.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Key block:\n");
|
printf("Key block:\n");
|
||||||
data_key = &key_block->data_key;
|
data_key = &key_block->data_key;
|
||||||
printf(" Size: 0x%" PRIx64 "\n", key_block->key_block_size);
|
printf(" Size: 0x%" PRIx64 "\n",
|
||||||
|
key_block->key_block_size);
|
||||||
printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
|
printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
|
||||||
(data_key->algorithm < kNumAlgorithms ?
|
(data_key->algorithm <
|
||||||
algo_strings[data_key->algorithm] : "(invalid)"));
|
kNumAlgorithms ? algo_strings[data_key->
|
||||||
|
algorithm] : "(invalid)"));
|
||||||
printf(" Data key version: %" PRIu64 "\n", data_key->key_version);
|
printf(" Data key version: %" PRIu64 "\n", data_key->key_version);
|
||||||
printf(" Flags: %" PRIu64 "\n", key_block->key_block_flags);
|
printf(" Flags: %" PRIu64 "\n",
|
||||||
|
key_block->key_block_flags);
|
||||||
|
|
||||||
/* Verify preamble */
|
/* Verify preamble */
|
||||||
rsa = PublicKeyToRSA(&key_block->data_key);
|
rsa = PublicKeyToRSA(&key_block->data_key);
|
||||||
@@ -244,26 +250,33 @@ static int Verify(const char* filename, const char* vblock_file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf("Preamble:\n");
|
printf("Preamble:\n");
|
||||||
printf(" Size: 0x%" PRIx64 "\n", preamble->preamble_size);
|
printf(" Size: 0x%" PRIx64 "\n",
|
||||||
printf(" Header version: %" PRIu32 ".%" PRIu32"\n",
|
preamble->preamble_size);
|
||||||
|
printf(" Header version: %" PRIu32 ".%" PRIu32 "\n",
|
||||||
preamble->header_version_major, preamble->header_version_minor);
|
preamble->header_version_major, preamble->header_version_minor);
|
||||||
printf(" Kernel version: %" PRIu64 "\n", preamble->kernel_version);
|
printf(" Kernel version: %" PRIu64 "\n",
|
||||||
printf(" Body load address: 0x%" PRIx64 "\n", preamble->body_load_address);
|
preamble->kernel_version);
|
||||||
|
printf(" Body load address: 0x%" PRIx64 "\n",
|
||||||
|
preamble->body_load_address);
|
||||||
printf(" Body size: 0x%" PRIx64 "\n",
|
printf(" Body size: 0x%" PRIx64 "\n",
|
||||||
preamble->body_signature.data_size);
|
preamble->body_signature.data_size);
|
||||||
printf(" Bootloader address: 0x%" PRIx64 "\n",
|
printf(" Bootloader address: 0x%" PRIx64 "\n",
|
||||||
preamble->bootloader_address);
|
preamble->bootloader_address);
|
||||||
printf(" Bootloader size: 0x%" PRIx64 "\n", preamble->bootloader_size);
|
printf(" Bootloader size: 0x%" PRIx64 "\n",
|
||||||
|
preamble->bootloader_size);
|
||||||
|
|
||||||
/* Verify body */
|
/* Verify body */
|
||||||
if (0 != VerifyData(file_data, file_size, &preamble->body_signature, rsa)) {
|
if (0 !=
|
||||||
|
VerifyData(file_data, file_size, &preamble->body_signature, rsa)) {
|
||||||
VbExError("Error verifying kernel body.\n");
|
VbExError("Error verifying kernel body.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
printf("Body verification succeeded.\n");
|
printf("Body verification succeeded.\n");
|
||||||
|
|
||||||
if (keyblock_file) {
|
if (keyblock_file) {
|
||||||
if (0 != WriteFile(keyblock_file, key_block, key_block->key_block_size)) {
|
if (0 !=
|
||||||
|
WriteFile(keyblock_file, key_block,
|
||||||
|
key_block->key_block_size)) {
|
||||||
VbExError("Unable to export keyblock file\n");
|
VbExError("Unable to export keyblock file\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -273,12 +286,12 @@ static int Verify(const char* filename, const char* vblock_file,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_dev_sign_file(int argc, char *argv[])
|
||||||
static int do_dev_sign_file(int argc, char* argv[]) {
|
{
|
||||||
char* filename = NULL;
|
char *filename = NULL;
|
||||||
char* keyblock_file = NULL;
|
char *keyblock_file = NULL;
|
||||||
char* signprivate_file = NULL;
|
char *signprivate_file = NULL;
|
||||||
char* vblock_file = NULL;
|
char *vblock_file = NULL;
|
||||||
int mode = 0;
|
int mode = 0;
|
||||||
int parse_error = 0;
|
int parse_error = 0;
|
||||||
int option_index;
|
int option_index;
|
||||||
@@ -289,8 +302,9 @@ static int do_dev_sign_file(int argc, char* argv[]) {
|
|||||||
else
|
else
|
||||||
progname = argv[0];
|
progname = argv[0];
|
||||||
|
|
||||||
while ((option_index = getopt_long(argc, argv, ":", long_opts, NULL)) != -1 &&
|
while ((option_index =
|
||||||
!parse_error) {
|
getopt_long(argc, argv, ":", long_opts, NULL)) != -1
|
||||||
|
&& !parse_error) {
|
||||||
switch (option_index) {
|
switch (option_index) {
|
||||||
default:
|
default:
|
||||||
case '?':
|
case '?':
|
||||||
@@ -305,7 +319,8 @@ static int do_dev_sign_file(int argc, char* argv[]) {
|
|||||||
case OPT_MODE_SIGN:
|
case OPT_MODE_SIGN:
|
||||||
case OPT_MODE_VERIFY:
|
case OPT_MODE_VERIFY:
|
||||||
if (mode && (mode != option_index)) {
|
if (mode && (mode != option_index)) {
|
||||||
fprintf(stderr, "Only a single mode can be specified\n");
|
fprintf(stderr,
|
||||||
|
"Only one mode can be specified\n");
|
||||||
parse_error = 1;
|
parse_error = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -330,13 +345,14 @@ static int do_dev_sign_file(int argc, char* argv[]) {
|
|||||||
if (parse_error)
|
if (parse_error)
|
||||||
return PrintHelp(progname);
|
return PrintHelp(progname);
|
||||||
|
|
||||||
switch(mode) {
|
switch (mode) {
|
||||||
case OPT_MODE_SIGN:
|
case OPT_MODE_SIGN:
|
||||||
if (!keyblock_file || !signprivate_file || !vblock_file) {
|
if (!keyblock_file || !signprivate_file || !vblock_file) {
|
||||||
fprintf(stderr, "Some required options are missing\n");
|
fprintf(stderr, "Some required options are missing\n");
|
||||||
return PrintHelp(progname);
|
return PrintHelp(progname);
|
||||||
}
|
}
|
||||||
return Sign(filename, keyblock_file, signprivate_file, vblock_file);
|
return Sign(filename, keyblock_file, signprivate_file,
|
||||||
|
vblock_file);
|
||||||
|
|
||||||
case OPT_MODE_VERIFY:
|
case OPT_MODE_VERIFY:
|
||||||
if (!vblock_file) {
|
if (!vblock_file) {
|
||||||
@@ -346,8 +362,7 @@ static int do_dev_sign_file(int argc, char* argv[]) {
|
|||||||
return Verify(filename, vblock_file, keyblock_file);
|
return Verify(filename, vblock_file, keyblock_file);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr,
|
fprintf(stderr, "You must specify either --sign or --verify\n");
|
||||||
"You must specify either --sign or --verify\n");
|
|
||||||
return PrintHelp(progname);
|
return PrintHelp(progname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,32 +29,34 @@ static void *base_of_rom;
|
|||||||
static size_t size_of_rom;
|
static size_t size_of_rom;
|
||||||
static int opt_gaps = 0;
|
static int opt_gaps = 0;
|
||||||
|
|
||||||
|
|
||||||
/* Return 0 if successful */
|
/* Return 0 if successful */
|
||||||
static int dump_fmap(const void *ptr, int argc, char *argv[])
|
static int dump_fmap(const void *ptr, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int i, retval = 0;
|
int i, retval = 0;
|
||||||
char buf[80]; // DWR: magic number
|
char buf[80]; /* DWR: magic number */
|
||||||
const FmapHeader *fmh = (const FmapHeader*)ptr;
|
const FmapHeader *fmh = (const FmapHeader *)ptr;
|
||||||
const FmapAreaHeader *ah = (const FmapAreaHeader*)(ptr + sizeof(FmapHeader));
|
const FmapAreaHeader *ah =
|
||||||
|
(const FmapAreaHeader *)(ptr + sizeof(FmapHeader));
|
||||||
|
|
||||||
if (FMT_NORMAL == opt_format) {
|
if (FMT_NORMAL == opt_format) {
|
||||||
snprintf(buf, FMAP_SIGNATURE_SIZE+1, "%s", fmh->fmap_signature);
|
snprintf(buf, FMAP_SIGNATURE_SIZE + 1, "%s",
|
||||||
|
fmh->fmap_signature);
|
||||||
printf("fmap_signature %s\n", buf);
|
printf("fmap_signature %s\n", buf);
|
||||||
printf("fmap_version: %d.%d\n",
|
printf("fmap_version: %d.%d\n",
|
||||||
fmh->fmap_ver_major, fmh->fmap_ver_minor);
|
fmh->fmap_ver_major, fmh->fmap_ver_minor);
|
||||||
printf("fmap_base: 0x%" PRIx64 "\n", fmh->fmap_base);
|
printf("fmap_base: 0x%" PRIx64 "\n", fmh->fmap_base);
|
||||||
printf("fmap_size: 0x%08x (%d)\n", fmh->fmap_size, fmh->fmap_size);
|
printf("fmap_size: 0x%08x (%d)\n", fmh->fmap_size,
|
||||||
snprintf(buf, FMAP_NAMELEN+1, "%s", fmh->fmap_name);
|
fmh->fmap_size);
|
||||||
|
snprintf(buf, FMAP_NAMELEN + 1, "%s", fmh->fmap_name);
|
||||||
printf("fmap_name: %s\n", buf);
|
printf("fmap_name: %s\n", buf);
|
||||||
printf("fmap_nareas: %d\n", fmh->fmap_nareas);
|
printf("fmap_nareas: %d\n", fmh->fmap_nareas);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < fmh->fmap_nareas; i++, ah++) {
|
for (i = 0; i < fmh->fmap_nareas; i++, ah++) {
|
||||||
snprintf(buf, FMAP_NAMELEN+1, "%s", ah->area_name);
|
snprintf(buf, FMAP_NAMELEN + 1, "%s", ah->area_name);
|
||||||
|
|
||||||
if (argc) {
|
if (argc) {
|
||||||
int j, found=0;
|
int j, found = 0;
|
||||||
for (j = 0; j < argc; j++)
|
for (j = 0; j < argc; j++)
|
||||||
if (!strcmp(argv[j], buf)) {
|
if (!strcmp(argv[j], buf)) {
|
||||||
found = 1;
|
found = 1;
|
||||||
@@ -67,17 +69,20 @@ static int dump_fmap(const void *ptr, int argc, char *argv[])
|
|||||||
|
|
||||||
switch (opt_format) {
|
switch (opt_format) {
|
||||||
case FMT_PRETTY:
|
case FMT_PRETTY:
|
||||||
printf("%s %d %d\n", buf, ah->area_offset, ah->area_size);
|
printf("%s %d %d\n", buf, ah->area_offset,
|
||||||
|
ah->area_size);
|
||||||
break;
|
break;
|
||||||
case FMT_FLASHROM:
|
case FMT_FLASHROM:
|
||||||
if (ah->area_size)
|
if (ah->area_size)
|
||||||
printf("0x%08x:0x%08x %s\n", ah->area_offset,
|
printf("0x%08x:0x%08x %s\n", ah->area_offset,
|
||||||
ah->area_offset + ah->area_size - 1, buf);
|
ah->area_offset + ah->area_size - 1,
|
||||||
|
buf);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("area: %d\n", i+1);
|
printf("area: %d\n", i + 1);
|
||||||
printf("area_offset: 0x%08x\n", ah->area_offset);
|
printf("area_offset: 0x%08x\n", ah->area_offset);
|
||||||
printf("area_size: 0x%08x (%d)\n", ah->area_size, ah->area_size);
|
printf("area_size: 0x%08x (%d)\n", ah->area_size,
|
||||||
|
ah->area_size);
|
||||||
printf("area_name: %s\n", buf);
|
printf("area_name: %s\n", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,16 +91,19 @@ static int dump_fmap(const void *ptr, int argc, char *argv[])
|
|||||||
for (s = buf; *s; s++)
|
for (s = buf; *s; s++)
|
||||||
if (*s == ' ')
|
if (*s == ' ')
|
||||||
*s = '_';
|
*s = '_';
|
||||||
FILE *fp = fopen(buf,"wb");
|
FILE *fp = fopen(buf, "wb");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
fprintf(stderr, "%s: can't open %s: %s\n",
|
fprintf(stderr, "%s: can't open %s: %s\n",
|
||||||
progname, buf, strerror(errno));
|
progname, buf, strerror(errno));
|
||||||
retval = 1;
|
retval = 1;
|
||||||
} else if (!ah->area_size) {
|
} else if (!ah->area_size) {
|
||||||
fprintf(stderr, "%s: section %s has zero size\n", progname, buf);
|
fprintf(stderr,
|
||||||
} else if (ah->area_offset + ah->area_size > size_of_rom) {
|
"%s: section %s has zero size\n",
|
||||||
fprintf(stderr, "%s: section %s is larger than the image\n",
|
|
||||||
progname, buf);
|
progname, buf);
|
||||||
|
} else if (ah->area_offset + ah->area_size >
|
||||||
|
size_of_rom) {
|
||||||
|
fprintf(stderr, "%s: section %s is larger"
|
||||||
|
" than the image\n", progname, buf);
|
||||||
retval = 1;
|
retval = 1;
|
||||||
} else if (1 != fwrite(base_of_rom + ah->area_offset,
|
} else if (1 != fwrite(base_of_rom + ah->area_offset,
|
||||||
ah->area_size, 1, fp)) {
|
ah->area_size, 1, fp)) {
|
||||||
@@ -113,7 +121,6 @@ static int dump_fmap(const void *ptr, int argc, char *argv[])
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* Stuff for human-readable form */
|
/* Stuff for human-readable form */
|
||||||
|
|
||||||
@@ -135,7 +142,7 @@ typedef struct node_s {
|
|||||||
|
|
||||||
static node_t *all_nodes;
|
static node_t *all_nodes;
|
||||||
|
|
||||||
static void sort_nodes(int num, node_t *ary[])
|
static void sort_nodes(int num, node_t * ary[])
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
node_t *tmp;
|
node_t *tmp;
|
||||||
@@ -152,7 +159,6 @@ static void sort_nodes(int num, node_t *ary[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void line(int indent, char *name,
|
static void line(int indent, char *name,
|
||||||
uint32_t start, uint32_t end, uint32_t size, char *append)
|
uint32_t start, uint32_t end, uint32_t size, char *append)
|
||||||
{
|
{
|
||||||
@@ -174,22 +180,25 @@ static void empty(int indent, uint32_t start, uint32_t end, char *name)
|
|||||||
gapcount++;
|
gapcount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show(node_t *p, int indent, int show_first)
|
static void show(node_t * p, int indent, int show_first)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
dupe_t *alias;
|
dupe_t *alias;
|
||||||
if (show_first) {
|
if (show_first) {
|
||||||
line(indent, p->name, p->start, p->end, p->size, 0);
|
line(indent, p->name, p->start, p->end, p->size, 0);
|
||||||
for (alias = p->alias; alias; alias = alias->next)
|
for (alias = p->alias; alias; alias = alias->next)
|
||||||
line(indent, alias->name, p->start, p->end, p->size, " // DUPLICATE");
|
line(indent, alias->name, p->start, p->end, p->size,
|
||||||
|
" // DUPLICATE");
|
||||||
}
|
}
|
||||||
sort_nodes(p->num_children, p->child);
|
sort_nodes(p->num_children, p->child);
|
||||||
for (i = 0; i < p->num_children; i++) {
|
for (i = 0; i < p->num_children; i++) {
|
||||||
if (i == 0 && p->end != p->child[i]->end)
|
if (i == 0 && p->end != p->child[i]->end)
|
||||||
empty(indent, p->child[i]->end, p->end, p->name);
|
empty(indent, p->child[i]->end, p->end, p->name);
|
||||||
show(p->child[i], indent + show_first, 1);
|
show(p->child[i], indent + show_first, 1);
|
||||||
if (i < p->num_children - 1 && p->child[i]->start != p->child[i+1]->end)
|
if (i < p->num_children - 1
|
||||||
empty(indent, p->child[i+1]->end, p->child[i]->start, p->name);
|
&& p->child[i]->start != p->child[i + 1]->end)
|
||||||
|
empty(indent, p->child[i + 1]->end, p->child[i]->start,
|
||||||
|
p->name);
|
||||||
if (i == p->num_children - 1 && p->child[i]->start != p->start)
|
if (i == p->num_children - 1 && p->child[i]->start != p->start)
|
||||||
empty(indent, p->start, p->child[i]->start, p->name);
|
empty(indent, p->start, p->child[i]->start, p->name);
|
||||||
}
|
}
|
||||||
@@ -209,8 +218,7 @@ static int encloses(int i, int j)
|
|||||||
node_t *a = all_nodes + i;
|
node_t *a = all_nodes + i;
|
||||||
node_t *b = all_nodes + j;
|
node_t *b = all_nodes + j;
|
||||||
|
|
||||||
return ((a->start <= b->start) &&
|
return ((a->start <= b->start) && (a->end >= b->end));
|
||||||
(a->end >= b->end));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int duplicates(int i, int j)
|
static int duplicates(int i, int j)
|
||||||
@@ -218,8 +226,7 @@ static int duplicates(int i, int j)
|
|||||||
node_t *a = all_nodes + i;
|
node_t *a = all_nodes + i;
|
||||||
node_t *b = all_nodes + j;
|
node_t *b = all_nodes + j;
|
||||||
|
|
||||||
return ((a->start == b->start) &&
|
return ((a->start == b->start) && (a->end == b->end));
|
||||||
(a->end == b->end));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_dupe(int i, int j, int numnodes)
|
static void add_dupe(int i, int j, int numnodes)
|
||||||
@@ -227,19 +234,20 @@ static void add_dupe(int i, int j, int numnodes)
|
|||||||
int k;
|
int k;
|
||||||
dupe_t *alias;
|
dupe_t *alias;
|
||||||
|
|
||||||
alias = (dupe_t *)malloc(sizeof(dupe_t));
|
alias = (dupe_t *) malloc(sizeof(dupe_t));
|
||||||
alias->name = all_nodes[j].name;
|
alias->name = all_nodes[j].name;
|
||||||
alias->next = all_nodes[i].alias;
|
alias->next = all_nodes[i].alias;
|
||||||
all_nodes[i].alias = alias;
|
all_nodes[i].alias = alias;
|
||||||
for (k = j; k < numnodes; k++ )
|
for (k = j; k < numnodes; k++)
|
||||||
all_nodes[k] = all_nodes[k + 1];
|
all_nodes[k] = all_nodes[k + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_child(node_t *p, int n)
|
static void add_child(node_t * p, int n)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
if (p->num_children && !p->child) {
|
if (p->num_children && !p->child) {
|
||||||
p->child = (struct node_s **)calloc(p->num_children, sizeof(node_t *));
|
p->child =
|
||||||
|
(struct node_s **)calloc(p->num_children, sizeof(node_t *));
|
||||||
if (!p->child) {
|
if (!p->child) {
|
||||||
perror("calloc failed");
|
perror("calloc failed");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -256,11 +264,11 @@ static int human_fmap(void *p)
|
|||||||
{
|
{
|
||||||
FmapHeader *fmh;
|
FmapHeader *fmh;
|
||||||
FmapAreaHeader *ah;
|
FmapAreaHeader *ah;
|
||||||
int i, j, errorcnt=0;
|
int i, j, errorcnt = 0;
|
||||||
int numnodes;
|
int numnodes;
|
||||||
|
|
||||||
fmh = (FmapHeader *)p;
|
fmh = (FmapHeader *) p;
|
||||||
ah = (FmapAreaHeader *)(fmh + 1);
|
ah = (FmapAreaHeader *) (fmh + 1);
|
||||||
|
|
||||||
/* The challenge here is to generate a directed graph from the
|
/* The challenge here is to generate a directed graph from the
|
||||||
* arbitrarily-ordered FMAP entries, and then to prune it until it's as
|
* arbitrarily-ordered FMAP entries, and then to prune it until it's as
|
||||||
@@ -271,13 +279,13 @@ static int human_fmap(void *p)
|
|||||||
numnodes = fmh->fmap_nareas;
|
numnodes = fmh->fmap_nareas;
|
||||||
|
|
||||||
/* plus one for the all-enclosing "root" */
|
/* plus one for the all-enclosing "root" */
|
||||||
all_nodes = (node_t *)calloc(numnodes+1, sizeof(node_t));
|
all_nodes = (node_t *) calloc(numnodes + 1, sizeof(node_t));
|
||||||
if (!all_nodes) {
|
if (!all_nodes) {
|
||||||
perror("calloc failed");
|
perror("calloc failed");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
for (i = 0; i < numnodes; i++) {
|
for (i = 0; i < numnodes; i++) {
|
||||||
char buf[FMAP_NAMELEN+1];
|
char buf[FMAP_NAMELEN + 1];
|
||||||
strncpy(buf, ah[i].area_name, FMAP_NAMELEN);
|
strncpy(buf, ah[i].area_name, FMAP_NAMELEN);
|
||||||
buf[FMAP_NAMELEN] = '\0';
|
buf[FMAP_NAMELEN] = '\0';
|
||||||
if (!(all_nodes[i].name = strdup(buf))) {
|
if (!(all_nodes[i].name = strdup(buf))) {
|
||||||
@@ -294,7 +302,6 @@ static int human_fmap(void *p)
|
|||||||
all_nodes[numnodes].size = fmh->fmap_size;
|
all_nodes[numnodes].size = fmh->fmap_size;
|
||||||
all_nodes[numnodes].end = fmh->fmap_base + fmh->fmap_size;
|
all_nodes[numnodes].end = fmh->fmap_base + fmh->fmap_size;
|
||||||
|
|
||||||
|
|
||||||
/* First, coalesce any duplicates */
|
/* First, coalesce any duplicates */
|
||||||
for (i = 0; i < numnodes; i++) {
|
for (i = 0; i < numnodes; i++) {
|
||||||
for (j = i + 1; j < numnodes; j++) {
|
for (j = i + 1; j < numnodes; j++) {
|
||||||
@@ -305,13 +312,14 @@ static int human_fmap(void *p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Each node should have at most one parent, which is the smallest enclosing
|
/* Each node should have at most one parent, which is the smallest
|
||||||
* node. Duplicate nodes "enclose" each other, but if there's already a
|
* enclosing node. Duplicate nodes "enclose" each other, but if there's
|
||||||
* relationship in one direction, we won't create another. */
|
* already a relationship in one direction, we won't create another.
|
||||||
|
*/
|
||||||
for (i = 0; i < numnodes; i++) {
|
for (i = 0; i < numnodes; i++) {
|
||||||
/* Find the smallest parent, which might be the root node. */
|
/* Find the smallest parent, which might be the root node. */
|
||||||
int k = numnodes;
|
int k = numnodes;
|
||||||
for (j = 0; j < numnodes; j++) { /* full O(N^2), not triangular */
|
for (j = 0; j < numnodes; j++) { /* full O(N^2) comparison */
|
||||||
if (i == j)
|
if (i == j)
|
||||||
continue;
|
continue;
|
||||||
if (overlaps(i, j)) {
|
if (overlaps(i, j)) {
|
||||||
@@ -322,12 +330,14 @@ static int human_fmap(void *p)
|
|||||||
printf(" %s: 0x%x - 0x%x\n", all_nodes[j].name,
|
printf(" %s: 0x%x - 0x%x\n", all_nodes[j].name,
|
||||||
all_nodes[j].start, all_nodes[j].end);
|
all_nodes[j].start, all_nodes[j].end);
|
||||||
if (opt_overlap < 2) {
|
if (opt_overlap < 2) {
|
||||||
printf("Use more -h args to ignore this error\n");
|
printf("Use more -h args to ignore"
|
||||||
|
" this error\n");
|
||||||
errorcnt++;
|
errorcnt++;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (encloses(j, i) && all_nodes[j].size < all_nodes[k].size)
|
if (encloses(j, i)
|
||||||
|
&& all_nodes[j].size < all_nodes[k].size)
|
||||||
k = j;
|
k = j;
|
||||||
}
|
}
|
||||||
all_nodes[i].parent = all_nodes + k;
|
all_nodes[i].parent = all_nodes + k;
|
||||||
@@ -356,6 +366,18 @@ static int human_fmap(void *p)
|
|||||||
/* End of human-reable stuff */
|
/* End of human-reable stuff */
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
|
static const char usage[] =
|
||||||
|
"\nUsage: %s [-x] [-p|-f|-h] FLASHIMAGE [NAME...]\n\n"
|
||||||
|
"Display (and extract with -x) the FMAP components from a BIOS image.\n"
|
||||||
|
"The -p option makes the output easier to parse by scripts.\n"
|
||||||
|
"The -f option emits the FMAP in the format used by flashrom.\n"
|
||||||
|
"\n"
|
||||||
|
"Specify one or more NAMEs to only print sections that exactly match.\n"
|
||||||
|
"\n"
|
||||||
|
"The -h option shows the whole FMAP in human-readable form.\n"
|
||||||
|
" Use -H to also display any gaps.\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
static int do_dump_fmap(int argc, char *argv[])
|
static int do_dump_fmap(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
@@ -407,69 +429,54 @@ static int do_dump_fmap(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (errorcnt || optind >= argc) {
|
if (errorcnt || optind >= argc) {
|
||||||
fprintf(stderr,
|
fprintf(stderr, usage, progname);
|
||||||
"\nUsage: %s [-x] [-p|-f|-h] FLASHIMAGE [NAME...]\n\n"
|
|
||||||
"Display (and extract with -x) the FMAP components from a BIOS image.\n"
|
|
||||||
"The -p option makes the output easier to parse by scripts.\n"
|
|
||||||
"The -f option emits the FMAP in the format used by flashrom.\n"
|
|
||||||
"\n"
|
|
||||||
"Specify one or more NAMEs to only print sections that exactly match.\n"
|
|
||||||
"\n"
|
|
||||||
"The -h option shows the whole FMAP in human-readable form.\n"
|
|
||||||
" Use -H to also display any gaps.\n"
|
|
||||||
"\n",
|
|
||||||
progname);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != stat(argv[optind], &sb)) {
|
if (0 != stat(argv[optind], &sb)) {
|
||||||
fprintf(stderr, "%s: can't stat %s: %s\n",
|
fprintf(stderr, "%s: can't stat %s: %s\n",
|
||||||
progname,
|
progname, argv[optind], strerror(errno));
|
||||||
argv[optind],
|
|
||||||
strerror(errno));
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = open(argv[optind], O_RDONLY);
|
fd = open(argv[optind], O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fprintf(stderr, "%s: can't open %s: %s\n",
|
fprintf(stderr, "%s: can't open %s: %s\n",
|
||||||
progname,
|
progname, argv[optind], strerror(errno));
|
||||||
argv[optind],
|
|
||||||
strerror(errno));
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
base_of_rom = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
|
base_of_rom =
|
||||||
if (base_of_rom == (char*)-1) {
|
mmap(0, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
|
||||||
|
if (base_of_rom == (char *)-1) {
|
||||||
fprintf(stderr, "%s: can't mmap %s: %s\n",
|
fprintf(stderr, "%s: can't mmap %s: %s\n",
|
||||||
progname,
|
progname, argv[optind], strerror(errno));
|
||||||
argv[optind],
|
|
||||||
strerror(errno));
|
|
||||||
close(fd);
|
close(fd);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
close(fd); /* done with this now */
|
close(fd); /* done with this now */
|
||||||
size_of_rom = sb.st_size;
|
size_of_rom = sb.st_size;
|
||||||
|
|
||||||
fmap = FmapFind((char*) base_of_rom, size_of_rom);
|
fmap = FmapFind((char *)base_of_rom, size_of_rom);
|
||||||
if (fmap) {
|
if (fmap) {
|
||||||
switch (opt_format) {
|
switch (opt_format) {
|
||||||
case FMT_HUMAN:
|
case FMT_HUMAN:
|
||||||
retval = human_fmap((void *)fmap);
|
retval = human_fmap((void *)fmap);
|
||||||
break;
|
break;
|
||||||
case FMT_NORMAL:
|
case FMT_NORMAL:
|
||||||
printf("hit at 0x%08x\n", (uint32_t) (fmap - (char*) base_of_rom));
|
printf("hit at 0x%08x\n",
|
||||||
|
(uint32_t) (fmap - (char *)base_of_rom));
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
default:
|
default:
|
||||||
retval = dump_fmap(fmap, argc-optind-1, argv+optind+1);
|
retval =
|
||||||
|
dump_fmap(fmap, argc - optind - 1,
|
||||||
|
argv + optind + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != munmap(base_of_rom, sb.st_size)) {
|
if (0 != munmap(base_of_rom, sb.st_size)) {
|
||||||
fprintf(stderr, "%s: can't munmap %s: %s\n",
|
fprintf(stderr, "%s: can't munmap %s: %s\n",
|
||||||
progname,
|
progname, argv[optind], strerror(errno));
|
||||||
argv[optind],
|
|
||||||
strerror(errno));
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
* Exports the kernel commandline from a given partition/image.
|
* Exports the kernel commandline from a given partition/image.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
@@ -19,22 +18,22 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct option long_opts[] = {
|
static const struct option long_opts[] = {
|
||||||
{ "kloadaddr", 1, NULL, OPT_KLOADADDR },
|
{"kloadaddr", 1, NULL, OPT_KLOADADDR},
|
||||||
{ NULL, 0, NULL, 0 }
|
{NULL, 0, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Print help and return error */
|
/* Print help and return error */
|
||||||
static int PrintHelp(void) {
|
static int PrintHelp(void)
|
||||||
|
{
|
||||||
puts("dump_kernel_config - Prints the kernel command line\n"
|
puts("dump_kernel_config - Prints the kernel command line\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Usage: dump_kernel_config [--kloadaddr <ADDRESS>] "
|
"Usage: dump_kernel_config [--kloadaddr <ADDRESS>] "
|
||||||
"<image/blockdevice>\n"
|
"<image/blockdevice>\n" "\n" "");
|
||||||
"\n"
|
|
||||||
"");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_dump_kernel_config(int argc, char* argv[]) {
|
static int do_dump_kernel_config(int argc, char *argv[])
|
||||||
|
{
|
||||||
char *infile = NULL;
|
char *infile = NULL;
|
||||||
char *config = NULL;
|
char *config = NULL;
|
||||||
uint64_t kernel_body_load_address = USE_PREAMBLE_LOAD_ADDR;
|
uint64_t kernel_body_load_address = USE_PREAMBLE_LOAD_ADDR;
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
#include "futility.h"
|
#include "futility.h"
|
||||||
#include "gbb_header.h"
|
#include "gbb_header.h"
|
||||||
|
|
||||||
static void help_and_quit(const char *prog) {
|
static void help_and_quit(const char *prog)
|
||||||
|
{
|
||||||
fprintf(stderr, "\n"
|
fprintf(stderr, "\n"
|
||||||
"Usage: %s [-g|-s|-c] [OPTIONS] bios_file [output_file]\n"
|
"Usage: %s [-g|-s|-c] [OPTIONS] bios_file [output_file]\n"
|
||||||
"\n"
|
"\n"
|
||||||
@@ -42,11 +43,13 @@ static void help_and_quit(const char *prog) {
|
|||||||
" -r --recoverykey=FILE\tFile name of new Recovery Key.\n"
|
" -r --recoverykey=FILE\tFile name of new Recovery Key.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"CREATE MODE:\n"
|
"CREATE MODE:\n"
|
||||||
"-c, --create=hwid_size,rootkey_size,bmpfv_size,recoverykey_size\n"
|
"-c, --create=hwid_size,rootkey_size,bmpfv_size,"
|
||||||
|
"recoverykey_size\n"
|
||||||
" \tCreate a GBB blob by given size list.\n"
|
" \tCreate a GBB blob by given size list.\n"
|
||||||
"SAMPLE:\n"
|
"SAMPLE:\n"
|
||||||
" %s -g bios.bin\n"
|
" %s -g bios.bin\n"
|
||||||
" %s --set --hwid='New Model' -k key.bin bios.bin newbios.bin\n"
|
" %s --set --hwid='New Model' -k key.bin"
|
||||||
|
" bios.bin newbios.bin\n"
|
||||||
" %s -c 0x100,0x1000,0x03DE80,0x1000 gbb.blob\n\n",
|
" %s -c 0x100,0x1000,0x03DE80,0x1000 gbb.blob\n\n",
|
||||||
prog, prog, prog, prog);
|
prog, prog, prog, prog);
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -55,22 +58,23 @@ static void help_and_quit(const char *prog) {
|
|||||||
/* Command line options */
|
/* Command line options */
|
||||||
static const struct option long_opts[] = {
|
static const struct option long_opts[] = {
|
||||||
/* name hasarg *flag val */
|
/* name hasarg *flag val */
|
||||||
{"get", 0, NULL, 'g' },
|
{"get", 0, NULL, 'g'},
|
||||||
{"set", 0, NULL, 's' },
|
{"set", 0, NULL, 's'},
|
||||||
{"create", 1, NULL, 'c' },
|
{"create", 1, NULL, 'c'},
|
||||||
{"output", 1, NULL, 'o' },
|
{"output", 1, NULL, 'o'},
|
||||||
{"rootkey", 1, NULL, 'k' },
|
{"rootkey", 1, NULL, 'k'},
|
||||||
{"bmpfv", 1, NULL, 'b' },
|
{"bmpfv", 1, NULL, 'b'},
|
||||||
{"recoverykey", 1, NULL, 'R' },
|
{"recoverykey", 1, NULL, 'R'},
|
||||||
{"hwid", 2, NULL, 'i' },
|
{"hwid", 2, NULL, 'i'},
|
||||||
{"flags", 2, NULL, 'L' },
|
{"flags", 2, NULL, 'L'},
|
||||||
{ NULL, 0, NULL, 0 },
|
{NULL, 0, NULL, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *short_opts = ":gsc:o:k:b:R:r:h:i:L:f:";
|
static char *short_opts = ":gsc:o:k:b:R:r:h:i:L:f:";
|
||||||
|
|
||||||
static int errorcnt;
|
static int errorcnt;
|
||||||
|
|
||||||
static int ValidGBB(GoogleBinaryBlockHeader *gbb, size_t maxlen)
|
static int ValidGBB(GoogleBinaryBlockHeader * gbb, size_t maxlen)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
char *s;
|
char *s;
|
||||||
@@ -84,7 +88,7 @@ static int ValidGBB(GoogleBinaryBlockHeader *gbb, size_t maxlen)
|
|||||||
if (gbb->hwid_offset + gbb->hwid_size > maxlen)
|
if (gbb->hwid_offset + gbb->hwid_size > maxlen)
|
||||||
goto bad;
|
goto bad;
|
||||||
if (gbb->hwid_size) {
|
if (gbb->hwid_size) {
|
||||||
/* Make sure the HWID is null-terminated (assumes ASCII, not unicode). */
|
/* Make sure the HWID is null-terminated (ASCII, not unicode) */
|
||||||
s = (char *)((char *)gbb + gbb->hwid_offset);
|
s = (char *)((char *)gbb + gbb->hwid_offset);
|
||||||
for (i = 0; i < gbb->hwid_size; i++)
|
for (i = 0; i < gbb->hwid_size; i++)
|
||||||
if (*s++ == '\0')
|
if (*s++ == '\0')
|
||||||
@@ -113,20 +117,18 @@ bad:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define GBB_SEARCH_STRIDE 4
|
#define GBB_SEARCH_STRIDE 4
|
||||||
GoogleBinaryBlockHeader *FindGbbHeader(uint8_t *ptr, size_t size)
|
GoogleBinaryBlockHeader *FindGbbHeader(uint8_t * ptr, size_t size)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
GoogleBinaryBlockHeader *tmp, *gbb_header = NULL;
|
GoogleBinaryBlockHeader *tmp, *gbb_header = NULL;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
for (i = 0;
|
for (i = 0; i <= size - GBB_SEARCH_STRIDE; i += GBB_SEARCH_STRIDE) {
|
||||||
i <= size - GBB_SEARCH_STRIDE;
|
|
||||||
i += GBB_SEARCH_STRIDE) {
|
|
||||||
if (0 != memcmp(ptr + i, GBB_SIGNATURE, GBB_SIGNATURE_SIZE))
|
if (0 != memcmp(ptr + i, GBB_SIGNATURE, GBB_SIGNATURE_SIZE))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Found something. See if it's any good. */
|
/* Found something. See if it's any good. */
|
||||||
tmp = (GoogleBinaryBlockHeader *)(ptr + i);
|
tmp = (GoogleBinaryBlockHeader *) (ptr + i);
|
||||||
if (ValidGBB(tmp, size - i))
|
if (ValidGBB(tmp, size - i))
|
||||||
if (!count++)
|
if (!count++)
|
||||||
gbb_header = tmp;
|
gbb_header = tmp;
|
||||||
@@ -145,28 +147,31 @@ GoogleBinaryBlockHeader *FindGbbHeader(uint8_t *ptr, size_t size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t *create_gbb(const char *desc, off_t *sizeptr)
|
static uint8_t *create_gbb(const char *desc, off_t * sizeptr)
|
||||||
{
|
{
|
||||||
char *str, *sizes, *param, *e = NULL;
|
char *str, *sizes, *param, *e = NULL;
|
||||||
size_t size = GBB_HEADER_SIZE;
|
size_t size = GBB_HEADER_SIZE;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
/* Danger Will Robinson! four entries ==> four paramater blocks */
|
/* Danger Will Robinson! four entries ==> four paramater blocks */
|
||||||
uint32_t val[] = {0, 0, 0, 0};
|
uint32_t val[] = { 0, 0, 0, 0 };
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
GoogleBinaryBlockHeader *gbb;
|
GoogleBinaryBlockHeader *gbb;
|
||||||
|
|
||||||
sizes = strdup(desc);
|
sizes = strdup(desc);
|
||||||
if (!sizes) {
|
if (!sizes) {
|
||||||
errorcnt++;
|
errorcnt++;
|
||||||
fprintf(stderr, "ERROR: strdup() failed: %s\n", strerror(errno));
|
fprintf(stderr, "ERROR: strdup() failed: %s\n",
|
||||||
|
strerror(errno));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (str = sizes; (param = strtok(str, ", ")) != NULL; str = NULL) {
|
for (str = sizes; (param = strtok(str, ", ")) != NULL; str = NULL) {
|
||||||
val[i] = (uint32_t)strtoul(param, &e, 0);
|
val[i] = (uint32_t) strtoul(param, &e, 0);
|
||||||
if (e && *e) {
|
if (e && *e) {
|
||||||
errorcnt++;
|
errorcnt++;
|
||||||
fprintf(stderr, "ERROR: invalid creation parameter: \"%s\"\n", param);
|
fprintf(stderr,
|
||||||
|
"ERROR: invalid creation parameter: \"%s\"\n",
|
||||||
|
param);
|
||||||
free(sizes);
|
free(sizes);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -175,7 +180,7 @@ static uint8_t *create_gbb(const char *desc, off_t *sizeptr)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = (uint8_t *)calloc(1, size);
|
buf = (uint8_t *) calloc(1, size);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
errorcnt++;
|
errorcnt++;
|
||||||
fprintf(stderr, "ERROR: can't malloc %zu bytes: %s\n",
|
fprintf(stderr, "ERROR: can't malloc %zu bytes: %s\n",
|
||||||
@@ -186,7 +191,7 @@ static uint8_t *create_gbb(const char *desc, off_t *sizeptr)
|
|||||||
*sizeptr = size;
|
*sizeptr = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
gbb = (GoogleBinaryBlockHeader *)buf;
|
gbb = (GoogleBinaryBlockHeader *) buf;
|
||||||
memcpy(gbb->signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE);
|
memcpy(gbb->signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE);
|
||||||
gbb->major_version = GBB_MAJOR_VER;
|
gbb->major_version = GBB_MAJOR_VER;
|
||||||
gbb->minor_version = GBB_MINOR_VER;
|
gbb->minor_version = GBB_MINOR_VER;
|
||||||
@@ -214,7 +219,7 @@ static uint8_t *create_gbb(const char *desc, off_t *sizeptr)
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *read_entire_file(const char *filename, off_t *sizeptr)
|
uint8_t *read_entire_file(const char *filename, off_t * sizeptr)
|
||||||
{
|
{
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
uint8_t *buf = NULL;
|
uint8_t *buf = NULL;
|
||||||
@@ -235,7 +240,7 @@ uint8_t *read_entire_file(const char *filename, off_t *sizeptr)
|
|||||||
if (sizeptr)
|
if (sizeptr)
|
||||||
*sizeptr = sb.st_size;
|
*sizeptr = sb.st_size;
|
||||||
|
|
||||||
buf = (uint8_t *)malloc(sb.st_size);
|
buf = (uint8_t *) malloc(sb.st_size);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
fprintf(stderr, "ERROR: can't malloc %" PRIi64 " bytes: %s\n",
|
fprintf(stderr, "ERROR: can't malloc %" PRIi64 " bytes: %s\n",
|
||||||
sb.st_size, strerror(errno));
|
sb.st_size, strerror(errno));
|
||||||
@@ -269,7 +274,7 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int write_to_file(const char *msg, const char *filename,
|
static int write_to_file(const char *msg, const char *filename,
|
||||||
uint8_t *start, size_t size)
|
uint8_t * start, size_t size)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
@@ -305,7 +310,7 @@ static int write_to_file(const char *msg, const char *filename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int read_from_file(const char *msg, const char *filename,
|
static int read_from_file(const char *msg, const char *filename,
|
||||||
uint8_t *start, uint32_t size)
|
uint8_t * start, uint32_t size)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
@@ -329,7 +334,8 @@ static int read_from_file(const char *msg, const char *filename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sb.st_size > size) {
|
if (sb.st_size > size) {
|
||||||
fprintf(stderr, "ERROR: file %s exceeds capacity (%" PRIu32 ")\n",
|
fprintf(stderr,
|
||||||
|
"ERROR: file %s exceeds capacity (%" PRIu32 ")\n",
|
||||||
filename, size);
|
filename, size);
|
||||||
errorcnt++;
|
errorcnt++;
|
||||||
r = errno;
|
r = errno;
|
||||||
@@ -339,7 +345,8 @@ static int read_from_file(const char *msg, const char *filename,
|
|||||||
/* It's okay if we read less than size. That's just the max. */
|
/* It's okay if we read less than size. That's just the max. */
|
||||||
count = fread(start, 1, size, fp);
|
count = fread(start, 1, size, fp);
|
||||||
if (ferror(fp)) {
|
if (ferror(fp)) {
|
||||||
fprintf(stderr, "ERROR: Read %zu/%" PRIi64 " bytes from %s: %s\n",
|
fprintf(stderr,
|
||||||
|
"ERROR: Read %zu/%" PRIi64 " bytes from %s: %s\n",
|
||||||
count, sb.st_size, filename, strerror(errno));
|
count, sb.st_size, filename, strerror(errno));
|
||||||
errorcnt++;
|
errorcnt++;
|
||||||
r = errno;
|
r = errno;
|
||||||
@@ -362,7 +369,7 @@ done_close:
|
|||||||
|
|
||||||
static int do_gbb_utility(int argc, char *argv[])
|
static int do_gbb_utility(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
enum do_what_now {DO_GET, DO_SET, DO_CREATE} mode = DO_GET;
|
enum do_what_now { DO_GET, DO_SET, DO_CREATE } mode = DO_GET;
|
||||||
char *infile = NULL;
|
char *infile = NULL;
|
||||||
char *outfile = NULL;
|
char *outfile = NULL;
|
||||||
char *opt_create = NULL;
|
char *opt_create = NULL;
|
||||||
@@ -402,25 +409,32 @@ static int do_gbb_utility(int argc, char *argv[])
|
|||||||
case 'b':
|
case 'b':
|
||||||
opt_bmpfv = optarg;
|
opt_bmpfv = optarg;
|
||||||
break;
|
break;
|
||||||
case 'R': case 'r':
|
case 'R':
|
||||||
|
case 'r':
|
||||||
opt_recoverykey = optarg;
|
opt_recoverykey = optarg;
|
||||||
break;
|
break;
|
||||||
case 'i': case 'h':
|
case 'i':
|
||||||
/* --hwid is optional: might be null, which could be okay */
|
case 'h':
|
||||||
|
/* --hwid is optional: null might be okay */
|
||||||
opt_hwid = optarg;
|
opt_hwid = optarg;
|
||||||
sel_hwid = 1;
|
sel_hwid = 1;
|
||||||
break;
|
break;
|
||||||
case 'L': case 'f':
|
case 'L':
|
||||||
/* --flags is optional: might be null, which could be okay */
|
case 'f':
|
||||||
|
/* --flags is optional: null might be okay */
|
||||||
opt_flags = optarg;
|
opt_flags = optarg;
|
||||||
sel_flags = 1;
|
sel_flags = 1;
|
||||||
break;
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
errorcnt++;
|
errorcnt++;
|
||||||
if (optopt)
|
if (optopt)
|
||||||
fprintf(stderr, "ERROR: unrecognized option: -%c\n", optopt);
|
fprintf(stderr,
|
||||||
else if (argv[optind - 1] )
|
"ERROR: unrecognized option: -%c\n",
|
||||||
fprintf(stderr, "ERROR: unrecognized option (possibly \"%s\")\n",
|
optopt);
|
||||||
|
else if (argv[optind - 1])
|
||||||
|
fprintf(stderr,
|
||||||
|
"ERROR: unrecognized option "
|
||||||
|
"(possibly \"%s\")\n",
|
||||||
argv[optind - 1]);
|
argv[optind - 1]);
|
||||||
else
|
else
|
||||||
fprintf(stderr, "ERROR: unrecognized option\n");
|
fprintf(stderr, "ERROR: unrecognized option\n");
|
||||||
@@ -428,14 +442,18 @@ static int do_gbb_utility(int argc, char *argv[])
|
|||||||
case ':':
|
case ':':
|
||||||
errorcnt++;
|
errorcnt++;
|
||||||
if (argv[optind - 1])
|
if (argv[optind - 1])
|
||||||
fprintf(stderr, "ERROR: missing argument to -%c (%s)\n",
|
fprintf(stderr,
|
||||||
|
"ERROR: missing argument to -%c (%s)\n",
|
||||||
optopt, argv[optind - 1]);
|
optopt, argv[optind - 1]);
|
||||||
else
|
else
|
||||||
fprintf(stderr, "ERROR: missing argument to -%c\n", optopt);
|
fprintf(stderr,
|
||||||
|
"ERROR: missing argument to -%c\n",
|
||||||
|
optopt);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
errorcnt++;
|
errorcnt++;
|
||||||
fprintf(stderr, "ERROR: unexpected error while parsing options\n");
|
fprintf(stderr,
|
||||||
|
"ERROR: error while parsing options\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -454,7 +472,8 @@ static int do_gbb_utility(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* With no args, show the HWID */
|
/* With no args, show the HWID */
|
||||||
if (!opt_rootkey && !opt_bmpfv && !opt_recoverykey && !sel_flags)
|
if (!opt_rootkey && !opt_bmpfv && !opt_recoverykey
|
||||||
|
&& !sel_flags)
|
||||||
sel_hwid = 1;
|
sel_hwid = 1;
|
||||||
|
|
||||||
inbuf = read_entire_file(infile, &filesize);
|
inbuf = read_entire_file(infile, &filesize);
|
||||||
@@ -466,16 +485,19 @@ static int do_gbb_utility(int argc, char *argv[])
|
|||||||
fprintf(stderr, "ERROR: No GBB found in %s\n", infile);
|
fprintf(stderr, "ERROR: No GBB found in %s\n", infile);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
gbb_base = (uint8_t *)gbb;
|
gbb_base = (uint8_t *) gbb;
|
||||||
|
|
||||||
/* Get the stuff */
|
/* Get the stuff */
|
||||||
if (sel_hwid)
|
if (sel_hwid)
|
||||||
printf("hardware_id: %s\n",
|
printf("hardware_id: %s\n",
|
||||||
gbb->hwid_size ? (char *)(gbb_base + gbb->hwid_offset) : "");
|
gbb->hwid_size ? (char *)(gbb_base +
|
||||||
|
gbb->
|
||||||
|
hwid_offset) : "");
|
||||||
if (sel_flags)
|
if (sel_flags)
|
||||||
printf("flags: 0x%08x\n", gbb->flags);
|
printf("flags: 0x%08x\n", gbb->flags);
|
||||||
if (opt_rootkey)
|
if (opt_rootkey)
|
||||||
write_to_file(" - exported root_key to file:", opt_rootkey,
|
write_to_file(" - exported root_key to file:",
|
||||||
|
opt_rootkey,
|
||||||
gbb_base + gbb->rootkey_offset,
|
gbb_base + gbb->rootkey_offset,
|
||||||
gbb->rootkey_size);
|
gbb->rootkey_size);
|
||||||
if (opt_bmpfv)
|
if (opt_bmpfv)
|
||||||
@@ -483,7 +505,8 @@ static int do_gbb_utility(int argc, char *argv[])
|
|||||||
gbb_base + gbb->bmpfv_offset,
|
gbb_base + gbb->bmpfv_offset,
|
||||||
gbb->bmpfv_size);
|
gbb->bmpfv_size);
|
||||||
if (opt_recoverykey)
|
if (opt_recoverykey)
|
||||||
write_to_file(" - exported recovery_key to file:", opt_recoverykey,
|
write_to_file(" - exported recovery_key to file:",
|
||||||
|
opt_recoverykey,
|
||||||
gbb_base + gbb->recovery_key_offset,
|
gbb_base + gbb->recovery_key_offset,
|
||||||
gbb->recovery_key_size);
|
gbb->recovery_key_size);
|
||||||
break;
|
break;
|
||||||
@@ -516,12 +539,13 @@ static int do_gbb_utility(int argc, char *argv[])
|
|||||||
fprintf(stderr, "ERROR: No GBB found in %s\n", infile);
|
fprintf(stderr, "ERROR: No GBB found in %s\n", infile);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
gbb_base = (uint8_t *)gbb;
|
gbb_base = (uint8_t *) gbb;
|
||||||
|
|
||||||
outbuf = (uint8_t *)malloc(filesize);
|
outbuf = (uint8_t *) malloc(filesize);
|
||||||
if (!outbuf) {
|
if (!outbuf) {
|
||||||
errorcnt++;
|
errorcnt++;
|
||||||
fprintf(stderr, "ERROR: can't malloc %" PRIi64 " bytes: %s\n",
|
fprintf(stderr,
|
||||||
|
"ERROR: can't malloc %" PRIi64 " bytes: %s\n",
|
||||||
filesize, strerror(errno));
|
filesize, strerror(errno));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -530,28 +554,33 @@ static int do_gbb_utility(int argc, char *argv[])
|
|||||||
memcpy(outbuf, inbuf, filesize);
|
memcpy(outbuf, inbuf, filesize);
|
||||||
gbb = FindGbbHeader(outbuf, filesize);
|
gbb = FindGbbHeader(outbuf, filesize);
|
||||||
if (!gbb) {
|
if (!gbb) {
|
||||||
fprintf(stderr, "INTERNAL ERROR: No GBB found in outbuf\n");
|
fprintf(stderr,
|
||||||
|
"INTERNAL ERROR: No GBB found in outbuf\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
gbb_base = (uint8_t *)gbb;
|
gbb_base = (uint8_t *) gbb;
|
||||||
|
|
||||||
if (opt_hwid) {
|
if (opt_hwid) {
|
||||||
if (strlen(opt_hwid) + 1 > gbb->hwid_size) {
|
if (strlen(opt_hwid) + 1 > gbb->hwid_size) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"ERROR: null-terminated HWID exceeds capacity (%d)\n",
|
"ERROR: null-terminated HWID"
|
||||||
|
" exceeds capacity (%d)\n",
|
||||||
gbb->hwid_size);
|
gbb->hwid_size);
|
||||||
errorcnt++;
|
errorcnt++;
|
||||||
} else {
|
} else {
|
||||||
strcpy((char *)(gbb_base + gbb->hwid_offset), opt_hwid);
|
strcpy((char *)(gbb_base + gbb->hwid_offset),
|
||||||
|
opt_hwid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt_flags) {
|
if (opt_flags) {
|
||||||
char *e = NULL;
|
char *e = NULL;
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
val = (uint32_t)strtoul(opt_flags, &e, 0);
|
val = (uint32_t) strtoul(opt_flags, &e, 0);
|
||||||
if (e && *e) {
|
if (e && *e) {
|
||||||
fprintf(stderr, "ERROR: invalid flags value: %s\n", opt_flags);
|
fprintf(stderr,
|
||||||
|
"ERROR: invalid flags value: %s\n",
|
||||||
|
opt_flags);
|
||||||
errorcnt++;
|
errorcnt++;
|
||||||
} else {
|
} else {
|
||||||
gbb->flags = val;
|
gbb->flags = val;
|
||||||
@@ -581,7 +610,8 @@ static int do_gbb_utility(int argc, char *argv[])
|
|||||||
case DO_CREATE:
|
case DO_CREATE:
|
||||||
if (!outfile) {
|
if (!outfile) {
|
||||||
if (argc - optind < 1) {
|
if (argc - optind < 1) {
|
||||||
fprintf(stderr, "\nERROR: missing output filename\n");
|
fprintf(stderr,
|
||||||
|
"\nERROR: missing output filename\n");
|
||||||
help_and_quit(argv[0]);
|
help_and_quit(argv[0]);
|
||||||
}
|
}
|
||||||
outfile = argv[optind++];
|
outfile = argv[optind++];
|
||||||
@@ -590,7 +620,8 @@ static int do_gbb_utility(int argc, char *argv[])
|
|||||||
outbuf = create_gbb(opt_create, &filesize);
|
outbuf = create_gbb(opt_create, &filesize);
|
||||||
if (!outbuf) {
|
if (!outbuf) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\nERROR: unable to parse creation spec (%s)\n", opt_create);
|
"\nERROR: unable to parse creation spec (%s)\n",
|
||||||
|
opt_create);
|
||||||
help_and_quit(argv[0]);
|
help_and_quit(argv[0]);
|
||||||
}
|
}
|
||||||
if (!errorcnt)
|
if (!errorcnt)
|
||||||
@@ -599,12 +630,11 @@ static int do_gbb_utility(int argc, char *argv[])
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (inbuf)
|
if (inbuf)
|
||||||
free(inbuf);
|
free(inbuf);
|
||||||
if (outbuf)
|
if (outbuf)
|
||||||
free(outbuf);
|
free(outbuf);
|
||||||
return !!errorcnt;
|
return ! !errorcnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLARE_FUTIL_COMMAND(gbb_utility, do_gbb_utility,
|
DECLARE_FUTIL_COMMAND(gbb_utility, do_gbb_utility,
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
#include "util_misc.h"
|
#include "util_misc.h"
|
||||||
#include "vboot_common.h"
|
#include "vboot_common.h"
|
||||||
|
|
||||||
|
|
||||||
/* Command line options */
|
/* Command line options */
|
||||||
enum {
|
enum {
|
||||||
OPT_MODE_VBLOCK = 1000,
|
OPT_MODE_VBLOCK = 1000,
|
||||||
@@ -34,21 +33,21 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct option long_opts[] = {
|
static const struct option long_opts[] = {
|
||||||
{"vblock", 1, 0, OPT_MODE_VBLOCK },
|
{"vblock", 1, 0, OPT_MODE_VBLOCK},
|
||||||
{"verify", 1, 0, OPT_MODE_VERIFY },
|
{"verify", 1, 0, OPT_MODE_VERIFY},
|
||||||
{"keyblock", 1, 0, OPT_KEYBLOCK },
|
{"keyblock", 1, 0, OPT_KEYBLOCK},
|
||||||
{"signpubkey", 1, 0, OPT_SIGNPUBKEY },
|
{"signpubkey", 1, 0, OPT_SIGNPUBKEY},
|
||||||
{"signprivate", 1, 0, OPT_SIGNPRIVATE },
|
{"signprivate", 1, 0, OPT_SIGNPRIVATE},
|
||||||
{"version", 1, 0, OPT_VERSION },
|
{"version", 1, 0, OPT_VERSION},
|
||||||
{"fv", 1, 0, OPT_FV },
|
{"fv", 1, 0, OPT_FV},
|
||||||
{"kernelkey", 1, 0, OPT_KERNELKEY },
|
{"kernelkey", 1, 0, OPT_KERNELKEY},
|
||||||
{"flags", 1, 0, OPT_FLAGS },
|
{"flags", 1, 0, OPT_FLAGS},
|
||||||
{NULL, 0, 0, 0}
|
{NULL, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Print help and return error */
|
/* Print help and return error */
|
||||||
static int PrintHelp(void) {
|
static int PrintHelp(void)
|
||||||
|
{
|
||||||
|
|
||||||
puts("vbutil_firmware - Verified boot key block utility\n"
|
puts("vbutil_firmware - Verified boot key block utility\n"
|
||||||
"\n"
|
"\n"
|
||||||
@@ -56,7 +55,8 @@ static int PrintHelp(void) {
|
|||||||
"\n"
|
"\n"
|
||||||
"For '--vblock <file>', required OPTIONS are:\n"
|
"For '--vblock <file>', required OPTIONS are:\n"
|
||||||
" --keyblock <file> Key block in .keyblock format\n"
|
" --keyblock <file> Key block in .keyblock format\n"
|
||||||
" --signprivate <file> Signing private key in .vbprivk format\n"
|
" --signprivate <file>"
|
||||||
|
" Signing private key in .vbprivk format\n"
|
||||||
" --version <number> Firmware version\n"
|
" --version <number> Firmware version\n"
|
||||||
" --fv <file> Firmware volume to sign\n"
|
" --fv <file> Firmware volume to sign\n"
|
||||||
" --kernelkey <file> Kernel subkey in .vbpubk format\n"
|
" --kernelkey <file> Kernel subkey in .vbpubk format\n"
|
||||||
@@ -64,31 +64,33 @@ static int PrintHelp(void) {
|
|||||||
" --flags <number> Preamble flags (defaults to 0)\n"
|
" --flags <number> Preamble flags (defaults to 0)\n"
|
||||||
"\n"
|
"\n"
|
||||||
"For '--verify <file>', required OPTIONS are:\n"
|
"For '--verify <file>', required OPTIONS are:\n"
|
||||||
" --signpubkey <file> Signing public key in .vbpubk format\n"
|
" --signpubkey <file>"
|
||||||
|
" Signing public key in .vbpubk format\n"
|
||||||
" --fv <file> Firmware volume to verify\n"
|
" --fv <file> Firmware volume to verify\n"
|
||||||
"\n"
|
"\n"
|
||||||
"For '--verify <file>', optional OPTIONS are:\n"
|
"For '--verify <file>', optional OPTIONS are:\n"
|
||||||
" --kernelkey <file> Write the kernel subkey to this file\n"
|
" --kernelkey <file>"
|
||||||
|
" Write the kernel subkey to this file\n"
|
||||||
"");
|
"");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Create a firmware .vblock */
|
/* Create a firmware .vblock */
|
||||||
static int Vblock(const char* outfile, const char* keyblock_file,
|
static int Vblock(const char *outfile, const char *keyblock_file,
|
||||||
const char* signprivate, uint64_t version,
|
const char *signprivate, uint64_t version,
|
||||||
const char* fv_file, const char* kernelkey_file,
|
const char *fv_file, const char *kernelkey_file,
|
||||||
uint32_t preamble_flags) {
|
uint32_t preamble_flags)
|
||||||
|
{
|
||||||
|
|
||||||
VbPrivateKey* signing_key;
|
VbPrivateKey *signing_key;
|
||||||
VbPublicKey* kernel_subkey;
|
VbPublicKey *kernel_subkey;
|
||||||
VbSignature* body_sig;
|
VbSignature *body_sig;
|
||||||
VbFirmwarePreambleHeader* preamble;
|
VbFirmwarePreambleHeader *preamble;
|
||||||
VbKeyBlockHeader* key_block;
|
VbKeyBlockHeader *key_block;
|
||||||
uint64_t key_block_size;
|
uint64_t key_block_size;
|
||||||
uint8_t* fv_data;
|
uint8_t *fv_data;
|
||||||
uint64_t fv_size;
|
uint64_t fv_size;
|
||||||
FILE* f;
|
FILE *f;
|
||||||
uint64_t i;
|
uint64_t i;
|
||||||
|
|
||||||
if (!outfile) {
|
if (!outfile) {
|
||||||
@@ -105,7 +107,8 @@ static int Vblock(const char* outfile, const char* keyblock_file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Read the key block and keys */
|
/* Read the key block and keys */
|
||||||
key_block = (VbKeyBlockHeader*)ReadFile(keyblock_file, &key_block_size);
|
key_block =
|
||||||
|
(VbKeyBlockHeader *) ReadFile(keyblock_file, &key_block_size);
|
||||||
if (!key_block) {
|
if (!key_block) {
|
||||||
VbExError("Error reading key block.\n");
|
VbExError("Error reading key block.\n");
|
||||||
return 1;
|
return 1;
|
||||||
@@ -142,8 +145,7 @@ static int Vblock(const char* outfile, const char* keyblock_file,
|
|||||||
preamble = CreateFirmwarePreamble(version,
|
preamble = CreateFirmwarePreamble(version,
|
||||||
kernel_subkey,
|
kernel_subkey,
|
||||||
body_sig,
|
body_sig,
|
||||||
signing_key,
|
signing_key, preamble_flags);
|
||||||
preamble_flags);
|
|
||||||
if (!preamble) {
|
if (!preamble) {
|
||||||
VbExError("Error creating preamble.\n");
|
VbExError("Error creating preamble.\n");
|
||||||
return 1;
|
return 1;
|
||||||
@@ -168,18 +170,19 @@ static int Vblock(const char* outfile, const char* keyblock_file,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Verify(const char* infile, const char* signpubkey,
|
static int Verify(const char *infile, const char *signpubkey,
|
||||||
const char* fv_file, const char* kernelkey_file) {
|
const char *fv_file, const char *kernelkey_file)
|
||||||
|
{
|
||||||
|
|
||||||
VbKeyBlockHeader* key_block;
|
VbKeyBlockHeader *key_block;
|
||||||
VbFirmwarePreambleHeader* preamble;
|
VbFirmwarePreambleHeader *preamble;
|
||||||
VbPublicKey* data_key;
|
VbPublicKey *data_key;
|
||||||
VbPublicKey* sign_key;
|
VbPublicKey *sign_key;
|
||||||
VbPublicKey* kernel_subkey;
|
VbPublicKey *kernel_subkey;
|
||||||
RSAPublicKey* rsa;
|
RSAPublicKey *rsa;
|
||||||
uint8_t* blob;
|
uint8_t *blob;
|
||||||
uint64_t blob_size;
|
uint64_t blob_size;
|
||||||
uint8_t* fv_data;
|
uint8_t *fv_data;
|
||||||
uint64_t fv_size;
|
uint64_t fv_size;
|
||||||
uint64_t now = 0;
|
uint64_t now = 0;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
@@ -211,7 +214,7 @@ static int Verify(const char* infile, const char* signpubkey,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Verify key block */
|
/* Verify key block */
|
||||||
key_block = (VbKeyBlockHeader*)blob;
|
key_block = (VbKeyBlockHeader *) blob;
|
||||||
if (0 != KeyBlockVerify(key_block, blob_size, sign_key, 0)) {
|
if (0 != KeyBlockVerify(key_block, blob_size, sign_key, 0)) {
|
||||||
VbExError("Error verifying key block.\n");
|
VbExError("Error verifying key block.\n");
|
||||||
return 1;
|
return 1;
|
||||||
@@ -221,12 +224,14 @@ static int Verify(const char* infile, const char* signpubkey,
|
|||||||
|
|
||||||
printf("Key block:\n");
|
printf("Key block:\n");
|
||||||
data_key = &key_block->data_key;
|
data_key = &key_block->data_key;
|
||||||
printf(" Size: %" PRIu64 "\n", key_block->key_block_size);
|
printf(" Size: %" PRIu64 "\n",
|
||||||
|
key_block->key_block_size);
|
||||||
printf(" Flags: %" PRIu64 " (ignored)\n",
|
printf(" Flags: %" PRIu64 " (ignored)\n",
|
||||||
key_block->key_block_flags);
|
key_block->key_block_flags);
|
||||||
printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
|
printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
|
||||||
(data_key->algorithm < kNumAlgorithms ?
|
(data_key->algorithm <
|
||||||
algo_strings[data_key->algorithm] : "(invalid)"));
|
kNumAlgorithms ? algo_strings[data_key->
|
||||||
|
algorithm] : "(invalid)"));
|
||||||
printf(" Data key version: %" PRIu64 "\n", data_key->key_version);
|
printf(" Data key version: %" PRIu64 "\n", data_key->key_version);
|
||||||
printf(" Data key sha1sum: ");
|
printf(" Data key sha1sum: ");
|
||||||
PrintPubKeySha1Sum(data_key);
|
PrintPubKeySha1Sum(data_key);
|
||||||
@@ -239,7 +244,7 @@ static int Verify(const char* infile, const char* signpubkey,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Verify preamble */
|
/* Verify preamble */
|
||||||
preamble = (VbFirmwarePreambleHeader*)(blob + now);
|
preamble = (VbFirmwarePreambleHeader *) (blob + now);
|
||||||
if (0 != VerifyFirmwarePreamble(preamble, blob_size - now, rsa)) {
|
if (0 != VerifyFirmwarePreamble(preamble, blob_size - now, rsa)) {
|
||||||
VbExError("Error verifying preamble.\n");
|
VbExError("Error verifying preamble.\n");
|
||||||
return 1;
|
return 1;
|
||||||
@@ -248,10 +253,12 @@ static int Verify(const char* infile, const char* signpubkey,
|
|||||||
|
|
||||||
flags = VbGetFirmwarePreambleFlags(preamble);
|
flags = VbGetFirmwarePreambleFlags(preamble);
|
||||||
printf("Preamble:\n");
|
printf("Preamble:\n");
|
||||||
printf(" Size: %" PRIu64 "\n", preamble->preamble_size);
|
printf(" Size: %" PRIu64 "\n",
|
||||||
printf(" Header version: %" PRIu32 ".%" PRIu32"\n",
|
preamble->preamble_size);
|
||||||
|
printf(" Header version: %" PRIu32 ".%" PRIu32 "\n",
|
||||||
preamble->header_version_major, preamble->header_version_minor);
|
preamble->header_version_major, preamble->header_version_minor);
|
||||||
printf(" Firmware version: %" PRIu64 "\n", preamble->firmware_version);
|
printf(" Firmware version: %" PRIu64 "\n",
|
||||||
|
preamble->firmware_version);
|
||||||
kernel_subkey = &preamble->kernel_subkey;
|
kernel_subkey = &preamble->kernel_subkey;
|
||||||
printf(" Kernel key algorithm: %" PRIu64 " %s\n",
|
printf(" Kernel key algorithm: %" PRIu64 " %s\n",
|
||||||
kernel_subkey->algorithm,
|
kernel_subkey->algorithm,
|
||||||
@@ -270,9 +277,13 @@ static int Verify(const char* infile, const char* signpubkey,
|
|||||||
|
|
||||||
/* Verify body */
|
/* Verify body */
|
||||||
if (flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL) {
|
if (flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL) {
|
||||||
printf("Preamble requests USE_RO_NORMAL; skipping body verification.\n");
|
printf
|
||||||
|
("Preamble requests USE_RO_NORMAL;"
|
||||||
|
" skipping body verification.\n");
|
||||||
} else {
|
} else {
|
||||||
if (0 != VerifyData(fv_data, fv_size, &preamble->body_signature, rsa)) {
|
if (0 !=
|
||||||
|
VerifyData(fv_data, fv_size, &preamble->body_signature,
|
||||||
|
rsa)) {
|
||||||
VbExError("Error verifying firmware body.\n");
|
VbExError("Error verifying firmware body.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -281,8 +292,7 @@ static int Verify(const char* infile, const char* signpubkey,
|
|||||||
|
|
||||||
if (kernelkey_file) {
|
if (kernelkey_file) {
|
||||||
if (0 != PublicKeyWrite(kernelkey_file, kernel_subkey)) {
|
if (0 != PublicKeyWrite(kernelkey_file, kernel_subkey)) {
|
||||||
fprintf(stderr,
|
VbExError("Unable to write kernel subkey\n");
|
||||||
"vbutil_firmware: unable to write kernel subkey\n");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -290,20 +300,20 @@ static int Verify(const char* infile, const char* signpubkey,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_vbutil_firmware(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
|
||||||
static int do_vbutil_firmware(int argc, char* argv[]) {
|
char *filename = NULL;
|
||||||
|
char *key_block_file = NULL;
|
||||||
char* filename = NULL;
|
char *signpubkey = NULL;
|
||||||
char* key_block_file = NULL;
|
char *signprivate = NULL;
|
||||||
char* signpubkey = NULL;
|
|
||||||
char* signprivate = NULL;
|
|
||||||
uint64_t version = 0;
|
uint64_t version = 0;
|
||||||
char* fv_file = NULL;
|
char *fv_file = NULL;
|
||||||
char* kernelkey_file = NULL;
|
char *kernelkey_file = NULL;
|
||||||
uint32_t preamble_flags = 0;
|
uint32_t preamble_flags = 0;
|
||||||
int mode = 0;
|
int mode = 0;
|
||||||
int parse_error = 0;
|
int parse_error = 0;
|
||||||
char* e;
|
char *e;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
|
while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
|
||||||
@@ -361,10 +371,10 @@ static int do_vbutil_firmware(int argc, char* argv[]) {
|
|||||||
if (parse_error)
|
if (parse_error)
|
||||||
return PrintHelp();
|
return PrintHelp();
|
||||||
|
|
||||||
switch(mode) {
|
switch (mode) {
|
||||||
case OPT_MODE_VBLOCK:
|
case OPT_MODE_VBLOCK:
|
||||||
return Vblock(filename, key_block_file, signprivate, version, fv_file,
|
return Vblock(filename, key_block_file, signprivate, version,
|
||||||
kernelkey_file, preamble_flags);
|
fv_file, kernelkey_file, preamble_flags);
|
||||||
case OPT_MODE_VERIFY:
|
case OPT_MODE_VERIFY:
|
||||||
return Verify(filename, signpubkey, fv_file, kernelkey_file);
|
return Verify(filename, signpubkey, fv_file, kernelkey_file);
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ static int opt_verbose = 0;
|
|||||||
static int opt_vblockonly = 0;
|
static int opt_vblockonly = 0;
|
||||||
static uint64_t opt_pad = 65536;
|
static uint64_t opt_pad = 65536;
|
||||||
|
|
||||||
|
|
||||||
/* Command line options */
|
/* Command line options */
|
||||||
enum {
|
enum {
|
||||||
OPT_MODE_PACK = 1000,
|
OPT_MODE_PACK = 1000,
|
||||||
@@ -62,33 +61,31 @@ typedef enum {
|
|||||||
} arch_t;
|
} arch_t;
|
||||||
|
|
||||||
static const struct option long_opts[] = {
|
static const struct option long_opts[] = {
|
||||||
{"pack", 1, 0, OPT_MODE_PACK },
|
{"pack", 1, 0, OPT_MODE_PACK},
|
||||||
{"repack", 1, 0, OPT_MODE_REPACK },
|
{"repack", 1, 0, OPT_MODE_REPACK},
|
||||||
{"verify", 1, 0, OPT_MODE_VERIFY },
|
{"verify", 1, 0, OPT_MODE_VERIFY},
|
||||||
{"arch", 1, 0, OPT_ARCH },
|
{"arch", 1, 0, OPT_ARCH},
|
||||||
{"oldblob", 1, 0, OPT_OLDBLOB },
|
{"oldblob", 1, 0, OPT_OLDBLOB},
|
||||||
{"kloadaddr", 1, 0, OPT_KLOADADDR },
|
{"kloadaddr", 1, 0, OPT_KLOADADDR},
|
||||||
{"keyblock", 1, 0, OPT_KEYBLOCK },
|
{"keyblock", 1, 0, OPT_KEYBLOCK},
|
||||||
{"signpubkey", 1, 0, OPT_SIGNPUBKEY },
|
{"signpubkey", 1, 0, OPT_SIGNPUBKEY},
|
||||||
{"signprivate", 1, 0, OPT_SIGNPRIVATE },
|
{"signprivate", 1, 0, OPT_SIGNPRIVATE},
|
||||||
{"version", 1, 0, OPT_VERSION },
|
{"version", 1, 0, OPT_VERSION},
|
||||||
{"minversion", 1, 0, OPT_MINVERSION },
|
{"minversion", 1, 0, OPT_MINVERSION},
|
||||||
{"vmlinuz", 1, 0, OPT_VMLINUZ },
|
{"vmlinuz", 1, 0, OPT_VMLINUZ},
|
||||||
{"bootloader", 1, 0, OPT_BOOTLOADER },
|
{"bootloader", 1, 0, OPT_BOOTLOADER},
|
||||||
{"config", 1, 0, OPT_CONFIG },
|
{"config", 1, 0, OPT_CONFIG},
|
||||||
{"vblockonly", 0, 0, OPT_VBLOCKONLY },
|
{"vblockonly", 0, 0, OPT_VBLOCKONLY},
|
||||||
{"pad", 1, 0, OPT_PAD },
|
{"pad", 1, 0, OPT_PAD},
|
||||||
{"verbose", 0, &opt_verbose, 1 },
|
{"verbose", 0, &opt_verbose, 1},
|
||||||
{"debug", 0, &opt_debug, 1 },
|
{"debug", 0, &opt_debug, 1},
|
||||||
{NULL, 0, 0, 0}
|
{NULL, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Print help and return error */
|
|
||||||
static int PrintHelp(char *progname) {
|
static const char usage[] =
|
||||||
fprintf(stderr,
|
"This program creates, signs, and verifies the kernel blob\n"
|
||||||
"This program creates, signs, and verifies the kernel blob\n");
|
|
||||||
fprintf(stderr,
|
|
||||||
"\n"
|
"\n"
|
||||||
"Usage: %s --pack <file> [PARAMETERS]\n"
|
"Usage: %s --pack <file> [PARAMETERS]\n"
|
||||||
"\n"
|
"\n"
|
||||||
@@ -105,9 +102,7 @@ static int PrintHelp(char *progname) {
|
|||||||
" Optional:\n"
|
" Optional:\n"
|
||||||
" --kloadaddr <address> Assign kernel body load address\n"
|
" --kloadaddr <address> Assign kernel body load address\n"
|
||||||
" --pad <number> Verification padding size in bytes\n"
|
" --pad <number> Verification padding size in bytes\n"
|
||||||
" --vblockonly Emit just the verification blob\n",
|
" --vblockonly Emit just the verification blob\n"
|
||||||
progname);
|
|
||||||
fprintf(stderr,
|
|
||||||
"\nOR\n\n"
|
"\nOR\n\n"
|
||||||
"Usage: %s --repack <file> [PARAMETERS]\n"
|
"Usage: %s --repack <file> [PARAMETERS]\n"
|
||||||
"\n"
|
"\n"
|
||||||
@@ -123,9 +118,7 @@ static int PrintHelp(char *progname) {
|
|||||||
" --version <number> Kernel version\n"
|
" --version <number> Kernel version\n"
|
||||||
" --kloadaddr <address> Assign kernel body load address\n"
|
" --kloadaddr <address> Assign kernel body load address\n"
|
||||||
" --pad <number> Verification blob size in bytes\n"
|
" --pad <number> Verification blob size in bytes\n"
|
||||||
" --vblockonly Emit just the verification blob\n",
|
" --vblockonly Emit just the verification blob\n"
|
||||||
progname);
|
|
||||||
fprintf(stderr,
|
|
||||||
"\nOR\n\n"
|
"\nOR\n\n"
|
||||||
"Usage: %s --verify <file> [PARAMETERS]\n"
|
"Usage: %s --verify <file> [PARAMETERS]\n"
|
||||||
"\n"
|
"\n"
|
||||||
@@ -139,12 +132,18 @@ static int PrintHelp(char *progname) {
|
|||||||
" --pad <number> Verification padding size in bytes\n"
|
" --pad <number> Verification padding size in bytes\n"
|
||||||
" --minversion <number> Minimum combined kernel key version\n"
|
" --minversion <number> Minimum combined kernel key version\n"
|
||||||
" and kernel version\n"
|
" and kernel version\n"
|
||||||
"\n",
|
"\n";
|
||||||
progname);
|
|
||||||
|
|
||||||
|
/* Print help and return error */
|
||||||
|
static int PrintHelp(char *progname)
|
||||||
|
{
|
||||||
|
fprintf(stderr, usage, progname, progname, progname);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Debug(const char *format, ...) {
|
static void Debug(const char *format, ...)
|
||||||
|
{
|
||||||
if (!opt_debug)
|
if (!opt_debug)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -155,7 +154,8 @@ static void Debug(const char *format, ...) {
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Fatal(const char *format, ...) {
|
static void Fatal(const char *format, ...)
|
||||||
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
fprintf(stderr, "ERROR: ");
|
fprintf(stderr, "ERROR: ");
|
||||||
@@ -165,7 +165,8 @@ static void Fatal(const char *format, ...) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return an explanation when fread() fails. */
|
/* Return an explanation when fread() fails. */
|
||||||
static const char *error_fread(FILE *fp) {
|
static const char *error_fread(FILE * fp)
|
||||||
|
{
|
||||||
const char *retval = "beats me why";
|
const char *retval = "beats me why";
|
||||||
if (feof(fp))
|
if (feof(fp))
|
||||||
retval = "EOF";
|
retval = "EOF";
|
||||||
@@ -179,35 +180,36 @@ static const char *error_fread(FILE *fp) {
|
|||||||
* to or greater than [val]. Used to determine the number of
|
* to or greater than [val]. Used to determine the number of
|
||||||
* pages/sectors/blocks/whatever needed to contain [val]
|
* pages/sectors/blocks/whatever needed to contain [val]
|
||||||
* items/bytes/etc. */
|
* items/bytes/etc. */
|
||||||
static uint64_t roundup(uint64_t val, uint64_t alignment) {
|
static uint64_t roundup(uint64_t val, uint64_t alignment)
|
||||||
|
{
|
||||||
uint64_t rem = val % alignment;
|
uint64_t rem = val % alignment;
|
||||||
if ( rem )
|
if (rem)
|
||||||
return val + (alignment - rem);
|
return val + (alignment - rem);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Match regexp /\b--\b/ to delimit the start of the kernel commandline. If we
|
/* Match regexp /\b--\b/ to delimit the start of the kernel commandline. If we
|
||||||
* don't find one, we'll use the whole thing. */
|
* don't find one, we'll use the whole thing. */
|
||||||
static unsigned int find_cmdline_start(char *input, unsigned int max_len) {
|
static unsigned int find_cmdline_start(char *input, unsigned int max_len)
|
||||||
|
{
|
||||||
int start = 0;
|
int start = 0;
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < max_len - 1 && input[i]; i++) {
|
for (i = 0; i < max_len - 1 && input[i]; i++) {
|
||||||
if ('-' == input[i] && '-' == input[i + 1]) { /* found a "--" */
|
if ('-' == input[i] && '-' == input[i + 1]) {
|
||||||
if ((i == 0 || ' ' == input[i - 1]) && /* nothing before it */
|
if ((i == 0 || ' ' == input[i - 1]) &&
|
||||||
(i + 2 >= max_len || ' ' == input[i+2])) { /* nothing after it */
|
(i + 2 >= max_len || ' ' == input[i + 2])) {
|
||||||
start = i+2; /* note: hope there's a trailing '\0' */
|
/* found "--" with nothing before or after it */
|
||||||
|
start = i + 2; /* hope for a trailing '\0' */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while(' ' == input[start]) /* skip leading spaces */
|
while (' ' == input[start]) /* skip leading spaces */
|
||||||
start++;
|
start++;
|
||||||
|
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* Here are globals containing all the bits & pieces I'm working on. */
|
/* Here are globals containing all the bits & pieces I'm working on. */
|
||||||
|
|
||||||
@@ -222,11 +224,10 @@ static uint8_t *g_bootloader_data;
|
|||||||
static uint64_t g_bootloader_size;
|
static uint64_t g_bootloader_size;
|
||||||
static uint64_t g_bootloader_address;
|
static uint64_t g_bootloader_address;
|
||||||
|
|
||||||
|
|
||||||
/* The individual parts of the verification blob (including the data that
|
/* The individual parts of the verification blob (including the data that
|
||||||
* immediately follows the headers) */
|
* immediately follows the headers) */
|
||||||
static VbKeyBlockHeader* g_keyblock;
|
static VbKeyBlockHeader *g_keyblock;
|
||||||
static VbKernelPreambleHeader* g_preamble;
|
static VbKernelPreambleHeader *g_preamble;
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
@@ -237,14 +238,14 @@ static VbKernelPreambleHeader* g_preamble;
|
|||||||
* Return the buffer contaning the line on success (and set the line length
|
* Return the buffer contaning the line on success (and set the line length
|
||||||
* using the passed in parameter), or NULL in case something goes wrong.
|
* using the passed in parameter), or NULL in case something goes wrong.
|
||||||
*/
|
*/
|
||||||
static uint8_t* ReadConfigFile(const char* config_file, uint64_t* config_size)
|
static uint8_t *ReadConfigFile(const char *config_file, uint64_t * config_size)
|
||||||
{
|
{
|
||||||
uint8_t* config_buf;
|
uint8_t *config_buf;
|
||||||
int ii;
|
int ii;
|
||||||
|
|
||||||
config_buf = ReadFile(config_file, config_size);
|
config_buf = ReadFile(config_file, config_size);
|
||||||
Debug(" config file size=0x%" PRIx64 "\n", *config_size);
|
Debug(" config file size=0x%" PRIx64 "\n", *config_size);
|
||||||
if (CROS_CONFIG_SIZE <= *config_size) { /* need room for trailing '\0' */
|
if (CROS_CONFIG_SIZE <= *config_size) { /* room for trailing '\0' */
|
||||||
VbExError("Config file %s is too large (>= %d bytes)\n",
|
VbExError("Config file %s is too large (>= %d bytes)\n",
|
||||||
config_file, CROS_CONFIG_SIZE);
|
config_file, CROS_CONFIG_SIZE);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -259,9 +260,9 @@ static uint8_t* ReadConfigFile(const char* config_file, uint64_t* config_size)
|
|||||||
return config_buf;
|
return config_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Offset of kernel command line string from start of packed kernel blob */
|
/* Offset of kernel command line string from start of packed kernel blob */
|
||||||
static uint64_t CmdLineOffset(VbKernelPreambleHeader *preamble) {
|
static uint64_t CmdLineOffset(VbKernelPreambleHeader * preamble)
|
||||||
|
{
|
||||||
return preamble->bootloader_address - preamble->body_load_address -
|
return preamble->bootloader_address - preamble->body_load_address -
|
||||||
CROS_CONFIG_SIZE - CROS_PARAMS_SIZE;
|
CROS_CONFIG_SIZE - CROS_PARAMS_SIZE;
|
||||||
}
|
}
|
||||||
@@ -269,7 +270,8 @@ static uint64_t CmdLineOffset(VbKernelPreambleHeader *preamble) {
|
|||||||
/* This initializes g_vmlinuz and g_param from a standard vmlinuz file.
|
/* This initializes g_vmlinuz and g_param from a standard vmlinuz file.
|
||||||
* It returns 0 on error. */
|
* It returns 0 on error. */
|
||||||
static int ImportVmlinuzFile(const char *vmlinuz_file, arch_t arch,
|
static int ImportVmlinuzFile(const char *vmlinuz_file, arch_t arch,
|
||||||
uint64_t kernel_body_load_address) {
|
uint64_t kernel_body_load_address)
|
||||||
|
{
|
||||||
uint8_t *kernel_buf;
|
uint8_t *kernel_buf;
|
||||||
uint64_t kernel_size;
|
uint64_t kernel_size;
|
||||||
uint64_t kernel32_start = 0;
|
uint64_t kernel32_start = 0;
|
||||||
@@ -285,21 +287,21 @@ static int ImportVmlinuzFile(const char *vmlinuz_file, arch_t arch,
|
|||||||
if (!kernel_size)
|
if (!kernel_size)
|
||||||
Fatal("Empty kernel file\n");
|
Fatal("Empty kernel file\n");
|
||||||
|
|
||||||
/* Go ahead and allocate the param region anyway. I don't think we need it
|
/* Go ahead and allocate the param region anyway. I don't think we need
|
||||||
* for non-x86, but let's keep it for now. */
|
* it for non-x86, but let's keep it for now. */
|
||||||
g_param_size = CROS_PARAMS_SIZE;
|
g_param_size = CROS_PARAMS_SIZE;
|
||||||
g_param_data= VbExMalloc(g_param_size);
|
g_param_data = VbExMalloc(g_param_size);
|
||||||
Memset(g_param_data, 0, g_param_size);
|
Memset(g_param_data, 0, g_param_size);
|
||||||
|
|
||||||
/* Unless we're handling x86, the kernel is the kernel, so we're done. */
|
/* Unless we're handling x86, the kernel is the kernel; we're done. */
|
||||||
if (arch != ARCH_X86) {
|
if (arch != ARCH_X86) {
|
||||||
g_kernel_data = kernel_buf;
|
g_kernel_data = kernel_buf;
|
||||||
g_kernel_size = kernel_size;
|
g_kernel_size = kernel_size;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The first part of the x86 vmlinuz is a header, followed by a real-mode
|
/* The first part of the x86 vmlinuz is a header, followed by a
|
||||||
* boot stub. We only want the 32-bit part. */
|
* real-mode boot stub. We only want the 32-bit part. */
|
||||||
lh = (struct linux_kernel_params *)kernel_buf;
|
lh = (struct linux_kernel_params *)kernel_buf;
|
||||||
kernel32_start = (lh->setup_sects + 1) << 9;
|
kernel32_start = (lh->setup_sects + 1) << 9;
|
||||||
if (kernel32_start >= kernel_size)
|
if (kernel32_start >= kernel_size)
|
||||||
@@ -313,11 +315,12 @@ static int ImportVmlinuzFile(const char *vmlinuz_file, arch_t arch,
|
|||||||
if (kernel32_size) {
|
if (kernel32_size) {
|
||||||
g_kernel_size = kernel32_size;
|
g_kernel_size = kernel32_size;
|
||||||
g_kernel_data = VbExMalloc(g_kernel_size);
|
g_kernel_data = VbExMalloc(g_kernel_size);
|
||||||
Memcpy(g_kernel_data, kernel_buf + kernel32_start, kernel32_size);
|
Memcpy(g_kernel_data, kernel_buf + kernel32_start,
|
||||||
|
kernel32_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the original zeropage data from kernel_buf into g_param_data, then
|
/* Copy the original zeropage data from kernel_buf into g_param_data,
|
||||||
* tweak a few fields for our purposes */
|
* then tweak a few fields for our purposes */
|
||||||
params = (struct linux_kernel_params *)(g_param_data);
|
params = (struct linux_kernel_params *)(g_param_data);
|
||||||
Memcpy(&(params->setup_sects), &(lh->setup_sects),
|
Memcpy(&(params->setup_sects), &(lh->setup_sects),
|
||||||
offsetof(struct linux_kernel_params, e820_entries)
|
offsetof(struct linux_kernel_params, e820_entries)
|
||||||
@@ -351,15 +354,16 @@ static int ImportVmlinuzFile(const char *vmlinuz_file, arch_t arch,
|
|||||||
|
|
||||||
/* This returns just the kernel blob, with the verification blob separated
|
/* This returns just the kernel blob, with the verification blob separated
|
||||||
* and copied to new memory in g_keyblock and g_preamble. */
|
* and copied to new memory in g_keyblock and g_preamble. */
|
||||||
static uint8_t* ReadOldBlobFromFileOrDie(const char *filename,
|
static uint8_t *ReadOldBlobFromFileOrDie(const char *filename,
|
||||||
uint64_t* size_ptr) {
|
uint64_t * size_ptr)
|
||||||
FILE* fp = NULL;
|
{
|
||||||
|
FILE *fp = NULL;
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
VbKeyBlockHeader* key_block;
|
VbKeyBlockHeader *key_block;
|
||||||
VbKernelPreambleHeader* preamble;
|
VbKernelPreambleHeader *preamble;
|
||||||
uint64_t now = 0;
|
uint64_t now = 0;
|
||||||
uint8_t* buf;
|
uint8_t *buf;
|
||||||
uint8_t* kernel_blob_data;
|
uint8_t *kernel_blob_data;
|
||||||
uint64_t kernel_blob_size;
|
uint64_t kernel_blob_size;
|
||||||
uint64_t file_size = 0;
|
uint64_t file_size = 0;
|
||||||
|
|
||||||
@@ -383,14 +387,16 @@ static uint8_t* ReadOldBlobFromFileOrDie(const char *filename,
|
|||||||
Debug("Reading %s\n", filename);
|
Debug("Reading %s\n", filename);
|
||||||
fp = fopen(filename, "rb");
|
fp = fopen(filename, "rb");
|
||||||
if (!fp)
|
if (!fp)
|
||||||
Fatal("Unable to open file %s: %s\n", filename, strerror(errno));
|
Fatal("Unable to open file %s: %s\n", filename,
|
||||||
|
strerror(errno));
|
||||||
|
|
||||||
buf = VbExMalloc(opt_pad);
|
buf = VbExMalloc(opt_pad);
|
||||||
if (1 != fread(buf, opt_pad, 1, fp))
|
if (1 != fread(buf, opt_pad, 1, fp))
|
||||||
Fatal("Unable to read header from %s: %s\n", filename, error_fread(fp));
|
Fatal("Unable to read header from %s: %s\n", filename,
|
||||||
|
error_fread(fp));
|
||||||
|
|
||||||
/* Sanity-check the key_block */
|
/* Sanity-check the key_block */
|
||||||
key_block = (VbKeyBlockHeader*)buf;
|
key_block = (VbKeyBlockHeader *) buf;
|
||||||
Debug("Keyblock is 0x%" PRIx64 " bytes\n", key_block->key_block_size);
|
Debug("Keyblock is 0x%" PRIx64 " bytes\n", key_block->key_block_size);
|
||||||
now += key_block->key_block_size;
|
now += key_block->key_block_size;
|
||||||
if (now > file_size)
|
if (now > file_size)
|
||||||
@@ -399,11 +405,11 @@ static uint8_t* ReadOldBlobFromFileOrDie(const char *filename,
|
|||||||
Fatal("key_block_size advances past %" PRIu64 " byte padding\n",
|
Fatal("key_block_size advances past %" PRIu64 " byte padding\n",
|
||||||
opt_pad);
|
opt_pad);
|
||||||
/* LGTM */
|
/* LGTM */
|
||||||
g_keyblock = (VbKeyBlockHeader*)VbExMalloc(key_block->key_block_size);
|
g_keyblock = (VbKeyBlockHeader *) VbExMalloc(key_block->key_block_size);
|
||||||
Memcpy(g_keyblock, key_block, key_block->key_block_size);
|
Memcpy(g_keyblock, key_block, key_block->key_block_size);
|
||||||
|
|
||||||
/* And the preamble */
|
/* And the preamble */
|
||||||
preamble = (VbKernelPreambleHeader*)(buf + now);
|
preamble = (VbKernelPreambleHeader *) (buf + now);
|
||||||
Debug("Preamble is 0x%" PRIx64 " bytes\n", preamble->preamble_size);
|
Debug("Preamble is 0x%" PRIx64 " bytes\n", preamble->preamble_size);
|
||||||
now += preamble->preamble_size;
|
now += preamble->preamble_size;
|
||||||
if (now > file_size)
|
if (now > file_size)
|
||||||
@@ -413,25 +419,28 @@ static uint8_t* ReadOldBlobFromFileOrDie(const char *filename,
|
|||||||
opt_pad);
|
opt_pad);
|
||||||
/* LGTM */
|
/* LGTM */
|
||||||
Debug(" kernel_version = %d\n", preamble->kernel_version);
|
Debug(" kernel_version = %d\n", preamble->kernel_version);
|
||||||
Debug(" bootloader_address = 0x%" PRIx64 "\n", preamble->bootloader_address);
|
Debug(" bootloader_address = 0x%" PRIx64 "\n",
|
||||||
|
preamble->bootloader_address);
|
||||||
Debug(" bootloader_size = 0x%" PRIx64 "\n", preamble->bootloader_size);
|
Debug(" bootloader_size = 0x%" PRIx64 "\n", preamble->bootloader_size);
|
||||||
Debug(" kern_blob_size = 0x%" PRIx64 "\n",
|
Debug(" kern_blob_size = 0x%" PRIx64 "\n",
|
||||||
preamble->body_signature.data_size);
|
preamble->body_signature.data_size);
|
||||||
g_preamble = (VbKernelPreambleHeader*)VbExMalloc(preamble->preamble_size);
|
g_preamble =
|
||||||
|
(VbKernelPreambleHeader *) VbExMalloc(preamble->preamble_size);
|
||||||
Memcpy(g_preamble, preamble, preamble->preamble_size);
|
Memcpy(g_preamble, preamble, preamble->preamble_size);
|
||||||
|
|
||||||
/* Now for the kernel blob */
|
/* Now for the kernel blob */
|
||||||
Debug("kernel blob is at offset 0x%" PRIx64 "\n", now);
|
Debug("kernel blob is at offset 0x%" PRIx64 "\n", now);
|
||||||
if (0 != fseek(fp, now, SEEK_SET))
|
if (0 != fseek(fp, now, SEEK_SET))
|
||||||
Fatal("Unable to seek to 0x%" PRIx64 " in %s: %s\n", now, filename,
|
Fatal("Unable to seek to 0x%" PRIx64 " in %s: %s\n", now,
|
||||||
strerror(errno));
|
filename, strerror(errno));
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
kernel_blob_size = file_size - now;
|
kernel_blob_size = file_size - now;
|
||||||
if (!kernel_blob_size)
|
if (!kernel_blob_size)
|
||||||
Fatal("No kernel blob found\n");
|
Fatal("No kernel blob found\n");
|
||||||
if (kernel_blob_size < preamble->body_signature.data_size)
|
if (kernel_blob_size < preamble->body_signature.data_size)
|
||||||
fprintf(stderr, "Warning: kernel file only has 0x%" PRIx64 " bytes\n",
|
fprintf(stderr,
|
||||||
|
"Warning: kernel file only has 0x%" PRIx64 " bytes\n",
|
||||||
kernel_blob_size);
|
kernel_blob_size);
|
||||||
kernel_blob_data = VbExMalloc(kernel_blob_size);
|
kernel_blob_data = VbExMalloc(kernel_blob_size);
|
||||||
|
|
||||||
@@ -449,11 +458,11 @@ static uint8_t* ReadOldBlobFromFileOrDie(const char *filename,
|
|||||||
return kernel_blob_data;
|
return kernel_blob_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Split a kernel blob into separate g_kernel, g_param, g_config, and
|
/* Split a kernel blob into separate g_kernel, g_param, g_config, and
|
||||||
* g_bootloader parts. */
|
* g_bootloader parts. */
|
||||||
static void UnpackKernelBlob(uint8_t *kernel_blob_data,
|
static void UnpackKernelBlob(uint8_t * kernel_blob_data,
|
||||||
uint64_t kernel_blob_size) {
|
uint64_t kernel_blob_size)
|
||||||
|
{
|
||||||
|
|
||||||
uint64_t k_blob_size = g_preamble->body_signature.data_size;
|
uint64_t k_blob_size = g_preamble->body_signature.data_size;
|
||||||
uint64_t k_blob_ofs = 0;
|
uint64_t k_blob_ofs = 0;
|
||||||
@@ -463,12 +472,12 @@ static void UnpackKernelBlob(uint8_t *kernel_blob_data,
|
|||||||
uint64_t p_ofs = b_ofs - CROS_CONFIG_SIZE;
|
uint64_t p_ofs = b_ofs - CROS_CONFIG_SIZE;
|
||||||
uint64_t c_ofs = p_ofs - CROS_PARAMS_SIZE;
|
uint64_t c_ofs = p_ofs - CROS_PARAMS_SIZE;
|
||||||
|
|
||||||
Debug("k_blob_size = 0x%" PRIx64 "\n", k_blob_size );
|
Debug("k_blob_size = 0x%" PRIx64 "\n", k_blob_size);
|
||||||
Debug("k_blob_ofs = 0x%" PRIx64 "\n", k_blob_ofs );
|
Debug("k_blob_ofs = 0x%" PRIx64 "\n", k_blob_ofs);
|
||||||
Debug("b_size = 0x%" PRIx64 "\n", b_size );
|
Debug("b_size = 0x%" PRIx64 "\n", b_size);
|
||||||
Debug("b_ofs = 0x%" PRIx64 "\n", b_ofs );
|
Debug("b_ofs = 0x%" PRIx64 "\n", b_ofs);
|
||||||
Debug("p_ofs = 0x%" PRIx64 "\n", p_ofs );
|
Debug("p_ofs = 0x%" PRIx64 "\n", p_ofs);
|
||||||
Debug("c_ofs = 0x%" PRIx64 "\n", c_ofs );
|
Debug("c_ofs = 0x%" PRIx64 "\n", c_ofs);
|
||||||
|
|
||||||
g_kernel_size = c_ofs;
|
g_kernel_size = c_ofs;
|
||||||
g_kernel_data = VbExMalloc(g_kernel_size);
|
g_kernel_data = VbExMalloc(g_kernel_size);
|
||||||
@@ -487,13 +496,11 @@ static void UnpackKernelBlob(uint8_t *kernel_blob_data,
|
|||||||
Memcpy(g_bootloader_data, kernel_blob_data + b_ofs, g_bootloader_size);
|
Memcpy(g_bootloader_data, kernel_blob_data + b_ofs, g_bootloader_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
static uint8_t* CreateKernelBlob(uint64_t kernel_body_load_address,
|
static uint8_t *CreateKernelBlob(uint64_t kernel_body_load_address,
|
||||||
arch_t arch,
|
arch_t arch, uint64_t * size_ptr)
|
||||||
uint64_t *size_ptr) {
|
{
|
||||||
uint8_t *kern_blob;
|
uint8_t *kern_blob;
|
||||||
uint64_t kern_blob_size;
|
uint64_t kern_blob_size;
|
||||||
uint64_t now;
|
uint64_t now;
|
||||||
@@ -509,7 +516,7 @@ static uint8_t* CreateKernelBlob(uint64_t kernel_body_load_address,
|
|||||||
|
|
||||||
Debug("kernel goes at kern_blob+0x%" PRIx64 "\n", now);
|
Debug("kernel goes at kern_blob+0x%" PRIx64 "\n", now);
|
||||||
|
|
||||||
Memcpy(kern_blob+now, g_kernel_data, g_kernel_size);
|
Memcpy(kern_blob + now, g_kernel_data, g_kernel_size);
|
||||||
now += roundup(g_kernel_size, CROS_ALIGN);
|
now += roundup(g_kernel_size, CROS_ALIGN);
|
||||||
|
|
||||||
Debug("config goes at kern_blob+0x%" PRIx64 "\n", now);
|
Debug("config goes at kern_blob+0x%" PRIx64 "\n", now);
|
||||||
@@ -539,14 +546,14 @@ static uint8_t* CreateKernelBlob(uint64_t kernel_body_load_address,
|
|||||||
return kern_blob;
|
return kern_blob;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Pack(const char* outfile,
|
static int Pack(const char *outfile,
|
||||||
uint8_t *kernel_blob,
|
uint8_t * kernel_blob,
|
||||||
uint64_t kernel_size,
|
uint64_t kernel_size,
|
||||||
int version,
|
int version,
|
||||||
uint64_t kernel_body_load_address,
|
uint64_t kernel_body_load_address, VbPrivateKey * signpriv_key)
|
||||||
VbPrivateKey* signpriv_key) {
|
{
|
||||||
VbSignature* body_sig;
|
VbSignature *body_sig;
|
||||||
FILE* f;
|
FILE *f;
|
||||||
uint64_t i;
|
uint64_t i;
|
||||||
uint64_t written = 0;
|
uint64_t written = 0;
|
||||||
|
|
||||||
@@ -559,8 +566,8 @@ static int Pack(const char* outfile,
|
|||||||
g_preamble = CreateKernelPreamble(version,
|
g_preamble = CreateKernelPreamble(version,
|
||||||
kernel_body_load_address,
|
kernel_body_load_address,
|
||||||
g_bootloader_address,
|
g_bootloader_address,
|
||||||
roundup(g_bootloader_size, CROS_ALIGN),
|
roundup(g_bootloader_size,
|
||||||
body_sig,
|
CROS_ALIGN), body_sig,
|
||||||
opt_pad - g_keyblock->key_block_size,
|
opt_pad - g_keyblock->key_block_size,
|
||||||
signpriv_key);
|
signpriv_key);
|
||||||
if (!g_preamble) {
|
if (!g_preamble) {
|
||||||
@@ -604,13 +611,13 @@ static int Pack(const char* outfile,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Verify(uint8_t* kernel_blob,
|
static int Verify(uint8_t * kernel_blob,
|
||||||
uint64_t kernel_size,
|
uint64_t kernel_size,
|
||||||
VbPublicKey* signpub_key,
|
VbPublicKey * signpub_key,
|
||||||
const char* keyblock_outfile,
|
const char *keyblock_outfile, uint64_t min_version)
|
||||||
uint64_t min_version) {
|
{
|
||||||
VbPublicKey* data_key;
|
VbPublicKey *data_key;
|
||||||
RSAPublicKey* rsa;
|
RSAPublicKey *rsa;
|
||||||
|
|
||||||
if (0 != KeyBlockVerify(g_keyblock, g_keyblock->key_block_size,
|
if (0 != KeyBlockVerify(g_keyblock, g_keyblock->key_block_size,
|
||||||
signpub_key, (0 == signpub_key)))
|
signpub_key, (0 == signpub_key)))
|
||||||
@@ -619,9 +626,12 @@ static int Verify(uint8_t* kernel_blob,
|
|||||||
printf("Key block:\n");
|
printf("Key block:\n");
|
||||||
data_key = &g_keyblock->data_key;
|
data_key = &g_keyblock->data_key;
|
||||||
if (opt_verbose)
|
if (opt_verbose)
|
||||||
printf(" Signature: %s\n", signpub_key ? "valid" : "ignored");
|
printf(" Signature: %s\n",
|
||||||
printf(" Size: 0x%" PRIx64 "\n", g_keyblock->key_block_size);
|
signpub_key ? "valid" : "ignored");
|
||||||
printf(" Flags: %" PRIu64 " ", g_keyblock->key_block_flags);
|
printf(" Size: 0x%" PRIx64 "\n",
|
||||||
|
g_keyblock->key_block_size);
|
||||||
|
printf(" Flags: %" PRIu64 " ",
|
||||||
|
g_keyblock->key_block_flags);
|
||||||
if (g_keyblock->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0)
|
if (g_keyblock->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0)
|
||||||
printf(" !DEV");
|
printf(" !DEV");
|
||||||
if (g_keyblock->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1)
|
if (g_keyblock->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1)
|
||||||
@@ -640,18 +650,20 @@ static int Verify(uint8_t* kernel_blob,
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
if (keyblock_outfile) {
|
if (keyblock_outfile) {
|
||||||
FILE* f = NULL;
|
FILE *f = NULL;
|
||||||
f = fopen(keyblock_outfile, "wb");
|
f = fopen(keyblock_outfile, "wb");
|
||||||
if (!f)
|
if (!f)
|
||||||
Fatal("Can't open key block file %s\n", keyblock_outfile);
|
Fatal("Can't open key block file %s\n",
|
||||||
|
keyblock_outfile);
|
||||||
if (1 != fwrite(g_keyblock, g_keyblock->key_block_size, 1, f))
|
if (1 != fwrite(g_keyblock, g_keyblock->key_block_size, 1, f))
|
||||||
Fatal("Can't write key block file %s\n", keyblock_outfile);
|
Fatal("Can't write key block file %s\n",
|
||||||
|
keyblock_outfile);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data_key->key_version < (min_version >> 16))
|
if (data_key->key_version < (min_version >> 16))
|
||||||
Fatal("Data key version %" PRIu64
|
Fatal("Data key version %" PRIu64
|
||||||
" is lower than minimum %" PRIu64".\n",
|
" is lower than minimum %" PRIu64 ".\n",
|
||||||
data_key->key_version, (min_version >> 16));
|
data_key->key_version, (min_version >> 16));
|
||||||
|
|
||||||
rsa = PublicKeyToRSA(data_key);
|
rsa = PublicKeyToRSA(data_key);
|
||||||
@@ -659,15 +671,18 @@ static int Verify(uint8_t* kernel_blob,
|
|||||||
Fatal("Error parsing data key.\n");
|
Fatal("Error parsing data key.\n");
|
||||||
|
|
||||||
/* Verify preamble */
|
/* Verify preamble */
|
||||||
if (0 != VerifyKernelPreamble(
|
if (0 !=
|
||||||
g_preamble, g_preamble->preamble_size, rsa))
|
VerifyKernelPreamble(g_preamble, g_preamble->preamble_size, rsa))
|
||||||
Fatal("Error verifying preamble.\n");
|
Fatal("Error verifying preamble.\n");
|
||||||
|
|
||||||
printf("Preamble:\n");
|
printf("Preamble:\n");
|
||||||
printf(" Size: 0x%" PRIx64 "\n", g_preamble->preamble_size);
|
printf(" Size: 0x%" PRIx64 "\n",
|
||||||
printf(" Header version: %" PRIu32 ".%" PRIu32"\n",
|
g_preamble->preamble_size);
|
||||||
g_preamble->header_version_major, g_preamble->header_version_minor);
|
printf(" Header version: %" PRIu32 ".%" PRIu32 "\n",
|
||||||
printf(" Kernel version: %" PRIu64 "\n", g_preamble->kernel_version);
|
g_preamble->header_version_major,
|
||||||
|
g_preamble->header_version_minor);
|
||||||
|
printf(" Kernel version: %" PRIu64 "\n",
|
||||||
|
g_preamble->kernel_version);
|
||||||
printf(" Body load address: 0x%" PRIx64 "\n",
|
printf(" Body load address: 0x%" PRIx64 "\n",
|
||||||
g_preamble->body_load_address);
|
g_preamble->body_load_address);
|
||||||
printf(" Body size: 0x%" PRIx64 "\n",
|
printf(" Body size: 0x%" PRIx64 "\n",
|
||||||
@@ -678,8 +693,9 @@ static int Verify(uint8_t* kernel_blob,
|
|||||||
g_preamble->bootloader_size);
|
g_preamble->bootloader_size);
|
||||||
|
|
||||||
if (g_preamble->kernel_version < (min_version & 0xFFFF))
|
if (g_preamble->kernel_version < (min_version & 0xFFFF))
|
||||||
Fatal("Kernel version %" PRIu64 " is lower than minimum %" PRIu64 ".\n",
|
Fatal("Kernel version %" PRIu64 " is lower than minimum %"
|
||||||
g_preamble->kernel_version, (min_version & 0xFFFF));
|
PRIu64 ".\n", g_preamble->kernel_version,
|
||||||
|
(min_version & 0xFFFF));
|
||||||
|
|
||||||
/* Verify body */
|
/* Verify body */
|
||||||
if (0 != VerifyData(kernel_blob, kernel_size,
|
if (0 != VerifyData(kernel_blob, kernel_size,
|
||||||
@@ -687,37 +703,38 @@ static int Verify(uint8_t* kernel_blob,
|
|||||||
Fatal("Error verifying kernel body.\n");
|
Fatal("Error verifying kernel body.\n");
|
||||||
printf("Body verification succeeded.\n");
|
printf("Body verification succeeded.\n");
|
||||||
|
|
||||||
|
|
||||||
if (opt_verbose)
|
if (opt_verbose)
|
||||||
printf("Config:\n%s\n", kernel_blob + CmdLineOffset(g_preamble));
|
printf("Config:\n%s\n",
|
||||||
|
kernel_blob + CmdLineOffset(g_preamble));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
static int do_vbutil_kernel(int argc, char* argv[]) {
|
static int do_vbutil_kernel(int argc, char *argv[])
|
||||||
char* filename = NULL;
|
{
|
||||||
char* oldfile = NULL;
|
char *filename = NULL;
|
||||||
char* keyblock_file = NULL;
|
char *oldfile = NULL;
|
||||||
char* signpubkey_file = NULL;
|
char *keyblock_file = NULL;
|
||||||
char* signprivkey_file = NULL;
|
char *signpubkey_file = NULL;
|
||||||
char* version_str = NULL;
|
char *signprivkey_file = NULL;
|
||||||
|
char *version_str = NULL;
|
||||||
int version = -1;
|
int version = -1;
|
||||||
char* vmlinuz_file = NULL;
|
char *vmlinuz_file = NULL;
|
||||||
char* bootloader_file = NULL;
|
char *bootloader_file = NULL;
|
||||||
char* config_file = NULL;
|
char *config_file = NULL;
|
||||||
arch_t arch = ARCH_X86;
|
arch_t arch = ARCH_X86;
|
||||||
char *address_str = NULL;
|
char *address_str = NULL;
|
||||||
uint64_t kernel_body_load_address = CROS_32BIT_ENTRY_ADDR;
|
uint64_t kernel_body_load_address = CROS_32BIT_ENTRY_ADDR;
|
||||||
int mode = 0;
|
int mode = 0;
|
||||||
int parse_error = 0;
|
int parse_error = 0;
|
||||||
uint64_t min_version = 0;
|
uint64_t min_version = 0;
|
||||||
char* e;
|
char *e;
|
||||||
int i;
|
int i;
|
||||||
VbPrivateKey* signpriv_key = NULL;
|
VbPrivateKey *signpriv_key = NULL;
|
||||||
VbPublicKey* signpub_key = NULL;
|
VbPublicKey *signpub_key = NULL;
|
||||||
uint8_t* kernel_blob = NULL;
|
uint8_t *kernel_blob = NULL;
|
||||||
uint64_t kernel_size = 0;
|
uint64_t kernel_size = 0;
|
||||||
|
|
||||||
char *progname = strrchr(argv[0], '/');
|
char *progname = strrchr(argv[0], '/');
|
||||||
@@ -743,7 +760,8 @@ static int do_vbutil_kernel(int argc, char* argv[]) {
|
|||||||
case OPT_MODE_REPACK:
|
case OPT_MODE_REPACK:
|
||||||
case OPT_MODE_VERIFY:
|
case OPT_MODE_VERIFY:
|
||||||
if (mode && (mode != i)) {
|
if (mode && (mode != i)) {
|
||||||
fprintf(stderr, "Only a single mode can be specified\n");
|
fprintf(stderr,
|
||||||
|
"Only one mode can be specified\n");
|
||||||
parse_error = 1;
|
parse_error = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -762,7 +780,9 @@ static int do_vbutil_kernel(int argc, char* argv[]) {
|
|||||||
else if (!strcasecmp(optarg, "mips"))
|
else if (!strcasecmp(optarg, "mips"))
|
||||||
arch = ARCH_MIPS;
|
arch = ARCH_MIPS;
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "Unknown architecture string: %s\n", optarg);
|
fprintf(stderr,
|
||||||
|
"Unknown architecture string: %s\n",
|
||||||
|
optarg);
|
||||||
parse_error = 1;
|
parse_error = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -838,7 +858,7 @@ static int do_vbutil_kernel(int argc, char* argv[]) {
|
|||||||
if (parse_error)
|
if (parse_error)
|
||||||
return PrintHelp(progname);
|
return PrintHelp(progname);
|
||||||
|
|
||||||
switch(mode) {
|
switch (mode) {
|
||||||
case OPT_MODE_PACK:
|
case OPT_MODE_PACK:
|
||||||
|
|
||||||
/* Required */
|
/* Required */
|
||||||
@@ -846,7 +866,7 @@ static int do_vbutil_kernel(int argc, char* argv[]) {
|
|||||||
if (!keyblock_file)
|
if (!keyblock_file)
|
||||||
Fatal("Missing required keyblock file.\n");
|
Fatal("Missing required keyblock file.\n");
|
||||||
|
|
||||||
g_keyblock = (VbKeyBlockHeader*)ReadFile(keyblock_file, 0);
|
g_keyblock = (VbKeyBlockHeader *) ReadFile(keyblock_file, 0);
|
||||||
if (!g_keyblock)
|
if (!g_keyblock)
|
||||||
Fatal("Error reading key block.\n");
|
Fatal("Error reading key block.\n");
|
||||||
|
|
||||||
@@ -861,21 +881,25 @@ static int do_vbutil_kernel(int argc, char* argv[]) {
|
|||||||
|
|
||||||
if (config_file) {
|
if (config_file) {
|
||||||
Debug("Reading %s\n", config_file);
|
Debug("Reading %s\n", config_file);
|
||||||
g_config_data = ReadConfigFile(config_file, &g_config_size);
|
g_config_data =
|
||||||
|
ReadConfigFile(config_file, &g_config_size);
|
||||||
if (!g_config_data)
|
if (!g_config_data)
|
||||||
Fatal("Error reading config file.\n");
|
Fatal("Error reading config file.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vmlinuz_file)
|
if (vmlinuz_file)
|
||||||
if (!ImportVmlinuzFile(vmlinuz_file, arch, kernel_body_load_address))
|
if (!ImportVmlinuzFile
|
||||||
|
(vmlinuz_file, arch, kernel_body_load_address))
|
||||||
Fatal("Error reading kernel file.\n");
|
Fatal("Error reading kernel file.\n");
|
||||||
|
|
||||||
if (bootloader_file) {
|
if (bootloader_file) {
|
||||||
Debug("Reading %s\n", bootloader_file);
|
Debug("Reading %s\n", bootloader_file);
|
||||||
g_bootloader_data = ReadFile(bootloader_file, &g_bootloader_size);
|
g_bootloader_data =
|
||||||
|
ReadFile(bootloader_file, &g_bootloader_size);
|
||||||
if (!g_bootloader_data)
|
if (!g_bootloader_data)
|
||||||
Fatal("Error reading bootloader file.\n");
|
Fatal("Error reading bootloader file.\n");
|
||||||
Debug(" bootloader file size=0x%" PRIx64 "\n", g_bootloader_size);
|
Debug(" bootloader file size=0x%" PRIx64 "\n",
|
||||||
|
g_bootloader_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do it */
|
/* Do it */
|
||||||
@@ -884,8 +908,7 @@ static int do_vbutil_kernel(int argc, char* argv[]) {
|
|||||||
&kernel_size);
|
&kernel_size);
|
||||||
|
|
||||||
return Pack(filename, kernel_blob, kernel_size,
|
return Pack(filename, kernel_blob, kernel_size,
|
||||||
version, kernel_body_load_address,
|
version, kernel_body_load_address, signpriv_key);
|
||||||
signpriv_key);
|
|
||||||
|
|
||||||
case OPT_MODE_REPACK:
|
case OPT_MODE_REPACK:
|
||||||
|
|
||||||
@@ -918,13 +941,15 @@ static int do_vbutil_kernel(int argc, char* argv[]) {
|
|||||||
version = g_preamble->kernel_version;
|
version = g_preamble->kernel_version;
|
||||||
|
|
||||||
if (!address_str)
|
if (!address_str)
|
||||||
kernel_body_load_address = g_preamble->body_load_address;
|
kernel_body_load_address =
|
||||||
|
g_preamble->body_load_address;
|
||||||
|
|
||||||
if (config_file) {
|
if (config_file) {
|
||||||
if (g_config_data)
|
if (g_config_data)
|
||||||
free(g_config_data);
|
free(g_config_data);
|
||||||
Debug("Reading %s\n", config_file);
|
Debug("Reading %s\n", config_file);
|
||||||
g_config_data = ReadConfigFile(config_file, &g_config_size);
|
g_config_data =
|
||||||
|
ReadConfigFile(config_file, &g_config_size);
|
||||||
if (!g_config_data)
|
if (!g_config_data)
|
||||||
Fatal("Error reading config file.\n");
|
Fatal("Error reading config file.\n");
|
||||||
}
|
}
|
||||||
@@ -932,7 +957,8 @@ static int do_vbutil_kernel(int argc, char* argv[]) {
|
|||||||
if (keyblock_file) {
|
if (keyblock_file) {
|
||||||
if (g_keyblock)
|
if (g_keyblock)
|
||||||
free(g_keyblock);
|
free(g_keyblock);
|
||||||
g_keyblock = (VbKeyBlockHeader*)ReadFile(keyblock_file, 0);
|
g_keyblock =
|
||||||
|
(VbKeyBlockHeader *) ReadFile(keyblock_file, 0);
|
||||||
if (!g_keyblock)
|
if (!g_keyblock)
|
||||||
Fatal("Error reading key block.\n");
|
Fatal("Error reading key block.\n");
|
||||||
}
|
}
|
||||||
@@ -943,9 +969,7 @@ static int do_vbutil_kernel(int argc, char* argv[]) {
|
|||||||
&kernel_size);
|
&kernel_size);
|
||||||
|
|
||||||
return Pack(filename, kernel_blob, kernel_size,
|
return Pack(filename, kernel_blob, kernel_size,
|
||||||
version, kernel_body_load_address,
|
version, kernel_body_load_address, signpriv_key);
|
||||||
signpriv_key);
|
|
||||||
|
|
||||||
|
|
||||||
case OPT_MODE_VERIFY:
|
case OPT_MODE_VERIFY:
|
||||||
|
|
||||||
@@ -965,7 +989,8 @@ static int do_vbutil_kernel(int argc, char* argv[]) {
|
|||||||
keyblock_file, min_version);
|
keyblock_file, min_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "You must specify a mode: --pack, --repack or --verify\n");
|
fprintf(stderr,
|
||||||
|
"You must specify a mode: --pack, --repack or --verify\n");
|
||||||
return PrintHelp(progname);
|
return PrintHelp(progname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
#include "util_misc.h"
|
#include "util_misc.h"
|
||||||
#include "vboot_common.h"
|
#include "vboot_common.h"
|
||||||
|
|
||||||
|
|
||||||
/* Command line options */
|
/* Command line options */
|
||||||
enum {
|
enum {
|
||||||
OPT_INKEY = 1000,
|
OPT_INKEY = 1000,
|
||||||
@@ -30,18 +29,18 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct option long_opts[] = {
|
static const struct option long_opts[] = {
|
||||||
{"key", 1, 0, OPT_INKEY },
|
{"key", 1, 0, OPT_INKEY},
|
||||||
{"version", 1, 0, OPT_KEY_VERSION },
|
{"version", 1, 0, OPT_KEY_VERSION},
|
||||||
{"algorithm", 1, 0, OPT_ALGORITHM },
|
{"algorithm", 1, 0, OPT_ALGORITHM},
|
||||||
{"pack", 1, 0, OPT_MODE_PACK },
|
{"pack", 1, 0, OPT_MODE_PACK},
|
||||||
{"unpack", 1, 0, OPT_MODE_UNPACK },
|
{"unpack", 1, 0, OPT_MODE_UNPACK},
|
||||||
{"copyto", 1, 0, OPT_COPYTO },
|
{"copyto", 1, 0, OPT_COPYTO},
|
||||||
{NULL, 0, 0, 0}
|
{NULL, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Print help and return error */
|
/* Print help and return error */
|
||||||
static int PrintHelp(char *progname) {
|
static int PrintHelp(char *progname)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@@ -56,8 +55,7 @@ static int PrintHelp(char *progname) {
|
|||||||
"(required for .keyb,\n"
|
"(required for .keyb,\n"
|
||||||
" ignored for .pem)\n"
|
" ignored for .pem)\n"
|
||||||
" --algorithm <number> "
|
" --algorithm <number> "
|
||||||
"Signing algorithm to use with key:\n",
|
"Signing algorithm to use with key:\n", progname);
|
||||||
progname);
|
|
||||||
|
|
||||||
for (i = 0; i < kNumAlgorithms; i++) {
|
for (i = 0; i < kNumAlgorithms; i++) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@@ -71,18 +69,17 @@ static int PrintHelp(char *progname) {
|
|||||||
"\n"
|
"\n"
|
||||||
" Optional parameters:\n"
|
" Optional parameters:\n"
|
||||||
" --copyto <file> "
|
" --copyto <file> "
|
||||||
"Write a copy of the key to this file.\n"
|
"Write a copy of the key to this file.\n" "\n", progname);
|
||||||
"\n",
|
|
||||||
progname);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pack a .keyb file into a .vbpubk, or a .pem into a .vbprivk */
|
/* Pack a .keyb file into a .vbpubk, or a .pem into a .vbprivk */
|
||||||
static int Pack(const char *infile, const char *outfile, uint64_t algorithm,
|
static int Pack(const char *infile, const char *outfile, uint64_t algorithm,
|
||||||
uint64_t version) {
|
uint64_t version)
|
||||||
VbPublicKey* pubkey;
|
{
|
||||||
VbPrivateKey* privkey;
|
VbPublicKey *pubkey;
|
||||||
|
VbPrivateKey *privkey;
|
||||||
|
|
||||||
if (!infile || !outfile) {
|
if (!infile || !outfile) {
|
||||||
fprintf(stderr, "vbutil_key: Must specify --in and --out\n");
|
fprintf(stderr, "vbutil_key: Must specify --in and --out\n");
|
||||||
@@ -111,11 +108,11 @@ static int Pack(const char *infile, const char *outfile, uint64_t algorithm,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Unpack a .vbpubk or .vbprivk */
|
/* Unpack a .vbpubk or .vbprivk */
|
||||||
static int Unpack(const char *infile, const char *outfile) {
|
static int Unpack(const char *infile, const char *outfile)
|
||||||
VbPublicKey* pubkey;
|
{
|
||||||
VbPrivateKey* privkey;
|
VbPublicKey *pubkey;
|
||||||
|
VbPrivateKey *privkey;
|
||||||
|
|
||||||
if (!infile) {
|
if (!infile) {
|
||||||
fprintf(stderr, "Need file to unpack\n");
|
fprintf(stderr, "Need file to unpack\n");
|
||||||
@@ -133,7 +130,8 @@ static int Unpack(const char *infile, const char *outfile) {
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
if (outfile) {
|
if (outfile) {
|
||||||
if (0 != PublicKeyWrite(outfile, pubkey)) {
|
if (0 != PublicKeyWrite(outfile, pubkey)) {
|
||||||
fprintf(stderr, "vbutil_key: Error writing key copy.\n");
|
fprintf(stderr,
|
||||||
|
"vbutil_key: Error writing key copy\n");
|
||||||
free(pubkey);
|
free(pubkey);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -144,12 +142,16 @@ static int Unpack(const char *infile, const char *outfile) {
|
|||||||
|
|
||||||
if ((privkey = PrivateKeyRead(infile))) {
|
if ((privkey = PrivateKeyRead(infile))) {
|
||||||
printf("Private Key file: %s\n", infile);
|
printf("Private Key file: %s\n", infile);
|
||||||
printf("Algorithm: %" PRIu64 " %s\n", privkey->algorithm,
|
printf("Algorithm: %" PRIu64 " %s\n",
|
||||||
(privkey->algorithm < kNumAlgorithms ?
|
privkey->algorithm,
|
||||||
algo_strings[privkey->algorithm] : "(invalid)"));
|
(privkey->algorithm <
|
||||||
|
kNumAlgorithms ? algo_strings[privkey->
|
||||||
|
algorithm] :
|
||||||
|
"(invalid)"));
|
||||||
if (outfile) {
|
if (outfile) {
|
||||||
if (0 != PrivateKeyWrite(outfile, privkey)) {
|
if (0 != PrivateKeyWrite(outfile, privkey)) {
|
||||||
fprintf(stderr, "vbutil_key: Error writing key copy.\n");
|
fprintf(stderr,
|
||||||
|
"vbutil_key: Error writing key copy\n");
|
||||||
free(privkey);
|
free(privkey);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -158,12 +160,13 @@ static int Unpack(const char *infile, const char *outfile) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
VbExError("Unable to parse either .vbpubk or vbprivk from %s\n", infile);
|
VbExError("Unable to parse either .vbpubk or vbprivk from %s\n",
|
||||||
|
infile);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_vbutil_key(int argc, char *argv[])
|
||||||
static int do_vbutil_key(int argc, char* argv[]) {
|
{
|
||||||
|
|
||||||
char *infile = NULL;
|
char *infile = NULL;
|
||||||
char *outfile = NULL;
|
char *outfile = NULL;
|
||||||
@@ -171,7 +174,7 @@ static int do_vbutil_key(int argc, char* argv[]) {
|
|||||||
int parse_error = 0;
|
int parse_error = 0;
|
||||||
uint64_t version = 1;
|
uint64_t version = 1;
|
||||||
uint64_t algorithm = kNumAlgorithms;
|
uint64_t algorithm = kNumAlgorithms;
|
||||||
char* e;
|
char *e;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
char *progname = strrchr(argv[0], '/');
|
char *progname = strrchr(argv[0], '/');
|
||||||
@@ -227,7 +230,7 @@ static int do_vbutil_key(int argc, char* argv[]) {
|
|||||||
if (parse_error)
|
if (parse_error)
|
||||||
return PrintHelp(progname);
|
return PrintHelp(progname);
|
||||||
|
|
||||||
switch(mode) {
|
switch (mode) {
|
||||||
case OPT_MODE_PACK:
|
case OPT_MODE_PACK:
|
||||||
return Pack(infile, outfile, algorithm, version);
|
return Pack(infile, outfile, algorithm, version);
|
||||||
case OPT_MODE_UNPACK:
|
case OPT_MODE_UNPACK:
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
#include "util_misc.h"
|
#include "util_misc.h"
|
||||||
#include "vboot_common.h"
|
#include "vboot_common.h"
|
||||||
|
|
||||||
|
|
||||||
/* Command line options */
|
/* Command line options */
|
||||||
enum {
|
enum {
|
||||||
OPT_MODE_PACK = 1000,
|
OPT_MODE_PACK = 1000,
|
||||||
@@ -32,22 +31,19 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct option long_opts[] = {
|
static const struct option long_opts[] = {
|
||||||
{"pack", 1, 0, OPT_MODE_PACK },
|
{"pack", 1, 0, OPT_MODE_PACK},
|
||||||
{"unpack", 1, 0, OPT_MODE_UNPACK },
|
{"unpack", 1, 0, OPT_MODE_UNPACK},
|
||||||
{"datapubkey", 1, 0, OPT_DATAPUBKEY },
|
{"datapubkey", 1, 0, OPT_DATAPUBKEY},
|
||||||
{"signpubkey", 1, 0, OPT_SIGNPUBKEY },
|
{"signpubkey", 1, 0, OPT_SIGNPUBKEY},
|
||||||
{"signprivate", 1, 0, OPT_SIGNPRIVATE },
|
{"signprivate", 1, 0, OPT_SIGNPRIVATE},
|
||||||
{"signprivate_pem", 1, 0, OPT_SIGNPRIVATE_PEM },
|
{"signprivate_pem", 1, 0, OPT_SIGNPRIVATE_PEM},
|
||||||
{"pem_algorithm", 1, 0, OPT_PEM_ALGORITHM },
|
{"pem_algorithm", 1, 0, OPT_PEM_ALGORITHM},
|
||||||
{"externalsigner", 1, 0, OPT_EXTERNAL_SIGNER },
|
{"externalsigner", 1, 0, OPT_EXTERNAL_SIGNER},
|
||||||
{"flags", 1, 0, OPT_FLAGS },
|
{"flags", 1, 0, OPT_FLAGS},
|
||||||
{NULL, 0, 0, 0}
|
{NULL, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char usage[] =
|
||||||
/* Print help and return error */
|
|
||||||
static int PrintHelp(char *progname) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"Verified boot key block utility\n"
|
"Verified boot key block utility\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Usage: %s <--pack|--unpack> <file> [OPTIONS]\n"
|
"Usage: %s <--pack|--unpack> <file> [OPTIONS]\n"
|
||||||
@@ -74,27 +70,33 @@ static int PrintHelp(char *progname) {
|
|||||||
" Signing public key in .vbpubk format. This is required to\n"
|
" Signing public key in .vbpubk format. This is required to\n"
|
||||||
" verify a signed keyblock.\n"
|
" verify a signed keyblock.\n"
|
||||||
" --datapubkey <file>"
|
" --datapubkey <file>"
|
||||||
" Write the data public key to this file.\n",
|
" Write the data public key to this file.\n";
|
||||||
progname);
|
|
||||||
|
/* Print help and return error */
|
||||||
|
static int PrintHelp(char *progname)
|
||||||
|
{
|
||||||
|
fprintf(stderr, usage, progname);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pack a .keyblock */
|
/* Pack a .keyblock */
|
||||||
static int Pack(const char* outfile, const char* datapubkey,
|
static int Pack(const char *outfile, const char *datapubkey,
|
||||||
const char* signprivate,
|
const char *signprivate,
|
||||||
const char* signprivate_pem, uint64_t pem_algorithm,
|
const char *signprivate_pem, uint64_t pem_algorithm,
|
||||||
uint64_t flags,
|
uint64_t flags, const char *external_signer)
|
||||||
const char* external_signer) {
|
{
|
||||||
VbPublicKey* data_key;
|
VbPublicKey *data_key;
|
||||||
VbPrivateKey* signing_key = NULL;
|
VbPrivateKey *signing_key = NULL;
|
||||||
VbKeyBlockHeader* block;
|
VbKeyBlockHeader *block;
|
||||||
|
|
||||||
if (!outfile) {
|
if (!outfile) {
|
||||||
fprintf(stderr, "vbutil_keyblock: Must specify output filename.\n");
|
fprintf(stderr,
|
||||||
|
"vbutil_keyblock: Must specify output filename.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (!datapubkey) {
|
if (!datapubkey) {
|
||||||
fprintf(stderr, "vbutil_keyblock: Must specify data public key.\n");
|
fprintf(stderr,
|
||||||
|
"vbutil_keyblock: Must specify data public key.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,20 +108,23 @@ static int Pack(const char* outfile, const char* datapubkey,
|
|||||||
|
|
||||||
if (signprivate_pem) {
|
if (signprivate_pem) {
|
||||||
if (pem_algorithm >= kNumAlgorithms) {
|
if (pem_algorithm >= kNumAlgorithms) {
|
||||||
fprintf(stderr, "vbutil_keyblock: Invalid --pem_algorithm %" PRIu64 "\n",
|
fprintf(stderr,
|
||||||
pem_algorithm);
|
"vbutil_keyblock: Invalid --pem_algorithm %"
|
||||||
|
PRIu64 "\n", pem_algorithm);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (external_signer) {
|
if (external_signer) {
|
||||||
/* External signing uses the PEM file directly. */
|
/* External signing uses the PEM file directly. */
|
||||||
block = KeyBlockCreate_external(data_key,
|
block = KeyBlockCreate_external(data_key,
|
||||||
signprivate_pem, pem_algorithm,
|
signprivate_pem,
|
||||||
flags,
|
pem_algorithm, flags,
|
||||||
external_signer);
|
external_signer);
|
||||||
} else {
|
} else {
|
||||||
signing_key = PrivateKeyReadPem(signprivate_pem, pem_algorithm);
|
signing_key =
|
||||||
|
PrivateKeyReadPem(signprivate_pem, pem_algorithm);
|
||||||
if (!signing_key) {
|
if (!signing_key) {
|
||||||
fprintf(stderr, "vbutil_keyblock: Error reading signing key.\n");
|
fprintf(stderr, "vbutil_keyblock:"
|
||||||
|
" Error reading signing key.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
block = KeyBlockCreate(data_key, signing_key, flags);
|
block = KeyBlockCreate(data_key, signing_key, flags);
|
||||||
@@ -128,7 +133,8 @@ static int Pack(const char* outfile, const char* datapubkey,
|
|||||||
if (signprivate) {
|
if (signprivate) {
|
||||||
signing_key = PrivateKeyRead(signprivate);
|
signing_key = PrivateKeyRead(signprivate);
|
||||||
if (!signing_key) {
|
if (!signing_key) {
|
||||||
fprintf(stderr, "vbutil_keyblock: Error reading signing key.\n");
|
fprintf(stderr, "vbutil_keyblock:"
|
||||||
|
" Error reading signing key.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,11 +153,12 @@ static int Pack(const char* outfile, const char* datapubkey,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Unpack(const char* infile, const char* datapubkey,
|
static int Unpack(const char *infile, const char *datapubkey,
|
||||||
const char* signpubkey) {
|
const char *signpubkey)
|
||||||
VbPublicKey* data_key;
|
{
|
||||||
VbPublicKey* sign_key = NULL;
|
VbPublicKey *data_key;
|
||||||
VbKeyBlockHeader* block;
|
VbPublicKey *sign_key = NULL;
|
||||||
|
VbKeyBlockHeader *block;
|
||||||
|
|
||||||
if (!infile) {
|
if (!infile) {
|
||||||
fprintf(stderr, "vbutil_keyblock: Must specify filename\n");
|
fprintf(stderr, "vbutil_keyblock: Must specify filename\n");
|
||||||
@@ -164,16 +171,19 @@ static int Unpack(const char* infile, const char* datapubkey,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the block is signed, then verify it with the signing public key, since
|
/* If the block is signed, then verify it with the signing public key,
|
||||||
KeyBlockRead() only verified the hash. */
|
* since KeyBlockRead() only verified the hash. */
|
||||||
if (block->key_block_signature.sig_size && signpubkey) {
|
if (block->key_block_signature.sig_size && signpubkey) {
|
||||||
sign_key = PublicKeyRead(signpubkey);
|
sign_key = PublicKeyRead(signpubkey);
|
||||||
if (!sign_key) {
|
if (!sign_key) {
|
||||||
fprintf(stderr, "vbutil_keyblock: Error reading signpubkey.\n");
|
fprintf(stderr,
|
||||||
|
"vbutil_keyblock: Error reading signpubkey.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (0 != KeyBlockVerify(block, block->key_block_size, sign_key, 0)) {
|
if (0 !=
|
||||||
fprintf(stderr, "vbutil_keyblock: Error verifying key block.\n");
|
KeyBlockVerify(block, block->key_block_size, sign_key, 0)) {
|
||||||
|
fprintf(stderr, "vbutil_keyblock:"
|
||||||
|
" Error verifying key block.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
free(sign_key);
|
free(sign_key);
|
||||||
@@ -203,8 +213,8 @@ static int Unpack(const char* infile, const char* datapubkey,
|
|||||||
|
|
||||||
if (datapubkey) {
|
if (datapubkey) {
|
||||||
if (0 != PublicKeyWrite(datapubkey, data_key)) {
|
if (0 != PublicKeyWrite(datapubkey, data_key)) {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "vbutil_keyblock:"
|
||||||
"vbutil_keyblock: unable to write public key\n");
|
" unable to write public key\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,21 +223,21 @@ static int Unpack(const char* infile, const char* datapubkey,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_vbutil_keyblock(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
|
||||||
static int do_vbutil_keyblock(int argc, char* argv[]) {
|
char *filename = NULL;
|
||||||
|
char *datapubkey = NULL;
|
||||||
char* filename = NULL;
|
char *signpubkey = NULL;
|
||||||
char* datapubkey = NULL;
|
char *signprivate = NULL;
|
||||||
char* signpubkey = NULL;
|
char *signprivate_pem = NULL;
|
||||||
char* signprivate = NULL;
|
char *external_signer = NULL;
|
||||||
char* signprivate_pem = NULL;
|
|
||||||
char* external_signer = NULL;
|
|
||||||
uint64_t flags = 0;
|
uint64_t flags = 0;
|
||||||
uint64_t pem_algorithm = 0;
|
uint64_t pem_algorithm = 0;
|
||||||
int is_pem_algorithm = 0;
|
int is_pem_algorithm = 0;
|
||||||
int mode = 0;
|
int mode = 0;
|
||||||
int parse_error = 0;
|
int parse_error = 0;
|
||||||
char* e;
|
char *e;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
char *progname = strrchr(argv[0], '/');
|
char *progname = strrchr(argv[0], '/');
|
||||||
@@ -292,18 +302,21 @@ static int do_vbutil_keyblock(int argc, char* argv[]) {
|
|||||||
|
|
||||||
/* Check if the right combination of options was provided. */
|
/* Check if the right combination of options was provided. */
|
||||||
if (signprivate && signprivate_pem) {
|
if (signprivate && signprivate_pem) {
|
||||||
fprintf(stderr, "Only one of --signprivate or --signprivate_pem must"
|
fprintf(stderr,
|
||||||
|
"Only one of --signprivate or --signprivate_pem must"
|
||||||
" be specified\n");
|
" be specified\n");
|
||||||
parse_error = 1;
|
parse_error = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signprivate_pem && !is_pem_algorithm) {
|
if (signprivate_pem && !is_pem_algorithm) {
|
||||||
fprintf(stderr, "--pem_algorithm must be used with --signprivate_pem\n");
|
fprintf(stderr, "--pem_algorithm must be used with"
|
||||||
|
" --signprivate_pem\n");
|
||||||
parse_error = 1;
|
parse_error = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (external_signer && !signprivate_pem) {
|
if (external_signer && !signprivate_pem) {
|
||||||
fprintf(stderr, "--externalsigner must be used with --signprivate_pem"
|
fprintf(stderr,
|
||||||
|
"--externalsigner must be used with --signprivate_pem"
|
||||||
"\n");
|
"\n");
|
||||||
parse_error = 1;
|
parse_error = 1;
|
||||||
}
|
}
|
||||||
@@ -311,12 +324,11 @@ static int do_vbutil_keyblock(int argc, char* argv[]) {
|
|||||||
if (parse_error)
|
if (parse_error)
|
||||||
return PrintHelp(progname);
|
return PrintHelp(progname);
|
||||||
|
|
||||||
switch(mode) {
|
switch (mode) {
|
||||||
case OPT_MODE_PACK:
|
case OPT_MODE_PACK:
|
||||||
return Pack(filename, datapubkey, signprivate,
|
return Pack(filename, datapubkey, signprivate,
|
||||||
signprivate_pem, pem_algorithm,
|
signprivate_pem, pem_algorithm,
|
||||||
flags,
|
flags, external_signer);
|
||||||
external_signer);
|
|
||||||
case OPT_MODE_UNPACK:
|
case OPT_MODE_UNPACK:
|
||||||
return Unpack(filename, datapubkey, signpubkey);
|
return Unpack(filename, datapubkey, signpubkey);
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -14,16 +14,17 @@
|
|||||||
#include "vboot_api.h"
|
#include "vboot_api.h"
|
||||||
#include "vboot_host.h"
|
#include "vboot_host.h"
|
||||||
|
|
||||||
static uint8_t* GetKernelConfig(uint8_t* blob, size_t blob_size,
|
static uint8_t *GetKernelConfig(uint8_t * blob, size_t blob_size,
|
||||||
uint64_t kernel_body_load_address) {
|
uint64_t kernel_body_load_address)
|
||||||
|
{
|
||||||
|
|
||||||
VbKeyBlockHeader* key_block;
|
VbKeyBlockHeader *key_block;
|
||||||
VbKernelPreambleHeader* preamble;
|
VbKernelPreambleHeader *preamble;
|
||||||
uint32_t now = 0;
|
uint32_t now = 0;
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
|
|
||||||
/* Skip the key block */
|
/* Skip the key block */
|
||||||
key_block = (VbKeyBlockHeader*)blob;
|
key_block = (VbKeyBlockHeader *) blob;
|
||||||
now += key_block->key_block_size;
|
now += key_block->key_block_size;
|
||||||
if (now + blob > blob + blob_size) {
|
if (now + blob > blob + blob_size) {
|
||||||
VbExError("key_block_size advances past the end of the blob\n");
|
VbExError("key_block_size advances past the end of the blob\n");
|
||||||
@@ -31,33 +32,36 @@ static uint8_t* GetKernelConfig(uint8_t* blob, size_t blob_size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Open up the preamble */
|
/* Open up the preamble */
|
||||||
preamble = (VbKernelPreambleHeader*)(blob + now);
|
preamble = (VbKernelPreambleHeader *) (blob + now);
|
||||||
now += preamble->preamble_size;
|
now += preamble->preamble_size;
|
||||||
if (now + blob > blob + blob_size) {
|
if (now + blob > blob + blob_size) {
|
||||||
VbExError("preamble_size advances past the end of the blob\n");
|
VbExError("preamble_size advances past the end of the blob\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read body_load_address from preamble if no kernel_body_load_address */
|
/* Read body_load_address from preamble if no
|
||||||
|
* kernel_body_load_address */
|
||||||
if (kernel_body_load_address == USE_PREAMBLE_LOAD_ADDR)
|
if (kernel_body_load_address == USE_PREAMBLE_LOAD_ADDR)
|
||||||
kernel_body_load_address = preamble->body_load_address;
|
kernel_body_load_address = preamble->body_load_address;
|
||||||
|
|
||||||
/* The x86 kernels have a pointer to the kernel commandline in the zeropage
|
/* The x86 kernels have a pointer to the kernel commandline in the
|
||||||
* table, but that's irrelevant for ARM. Both types keep the config blob in
|
* zeropage table, but that's irrelevant for ARM. Both types keep the
|
||||||
* the same place, so just go find it. */
|
* config blob in the same place, so just go find it. */
|
||||||
offset = preamble->bootloader_address -
|
offset = preamble->bootloader_address -
|
||||||
(kernel_body_load_address + CROS_PARAMS_SIZE +
|
(kernel_body_load_address + CROS_PARAMS_SIZE +
|
||||||
CROS_CONFIG_SIZE) + now;
|
CROS_CONFIG_SIZE) + now;
|
||||||
if (offset > blob_size) {
|
if (offset > blob_size) {
|
||||||
VbExError("params are outside of the memory blob: %x\n", offset);
|
VbExError("params are outside of the memory blob: %x\n",
|
||||||
|
offset);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return blob + offset;
|
return blob + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* MMapFile(const char* filename, size_t *size) {
|
static void *MMapFile(const char *filename, size_t * size)
|
||||||
FILE* f;
|
{
|
||||||
uint8_t* buf;
|
FILE *f;
|
||||||
|
uint8_t *buf;
|
||||||
long file_size = 0;
|
long file_size = 0;
|
||||||
|
|
||||||
f = fopen(filename, "rb");
|
f = fopen(filename, "rb");
|
||||||
@@ -88,10 +92,9 @@ static void* MMapFile(const char* filename, size_t *size) {
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *FindKernelConfig(const char *infile, uint64_t kernel_body_load_address)
|
char *FindKernelConfig(const char *infile, uint64_t kernel_body_load_address)
|
||||||
{
|
{
|
||||||
uint8_t* blob;
|
uint8_t *blob;
|
||||||
size_t blob_size;
|
size_t blob_size;
|
||||||
uint8_t *config = NULL;
|
uint8_t *config = NULL;
|
||||||
char *newstr = NULL;
|
char *newstr = NULL;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
static const char * const usage= "\n\
|
static const char *const usage = "\n\
|
||||||
Usage: " MYNAME " PROGRAM|COMMAND [args...]\n\
|
Usage: " MYNAME " PROGRAM|COMMAND [args...]\n\
|
||||||
\n\
|
\n\
|
||||||
This is the unified firmware utility, which will eventually replace\n\
|
This is the unified firmware utility, which will eventually replace\n\
|
||||||
@@ -45,7 +45,7 @@ In either case it will append some usage information to " LOGFILE "\n\
|
|||||||
|
|
||||||
static int do_help(int argc, char *argv[])
|
static int do_help(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
const struct futil_cmd_t * const *cmd;
|
const struct futil_cmd_t *const *cmd;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fputs(usage, stdout);
|
fputs(usage, stdout);
|
||||||
@@ -64,6 +64,7 @@ static int do_help(int argc, char *argv[])
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLARE_FUTIL_COMMAND(help, do_help,
|
DECLARE_FUTIL_COMMAND(help, do_help,
|
||||||
"Show a bit of help (you're looking at it)");
|
"Show a bit of help (you're looking at it)");
|
||||||
|
|
||||||
@@ -71,11 +72,11 @@ DECLARE_FUTIL_COMMAND(help, do_help,
|
|||||||
* These are built-in functions that we'd like to abandon completely someday.
|
* These are built-in functions that we'd like to abandon completely someday.
|
||||||
* TODO: If no one complains, get rid of them.
|
* TODO: If no one complains, get rid of them.
|
||||||
*/
|
*/
|
||||||
static const char * const dep_cmds[] = {
|
static const char *const dep_cmds[] = {
|
||||||
"dev_sign_file",
|
"dev_sign_file",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const dep_usage= "\n\
|
static const char *const dep_usage = "\n\
|
||||||
The program \"%s\" is deprecated and may go away soon.\n\
|
The program \"%s\" is deprecated and may go away soon.\n\
|
||||||
\n\
|
\n\
|
||||||
If you feel this is in error, please open a bug at\n\
|
If you feel this is in error, please open a bug at\n\
|
||||||
@@ -147,9 +148,9 @@ static void log_open(void)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
#ifdef FORCE_LOGGING_ON
|
#ifdef FORCE_LOGGING_ON
|
||||||
log_fd = open(LOGFILE, O_WRONLY|O_APPEND|O_CREAT, 0666);
|
log_fd = open(LOGFILE, O_WRONLY | O_APPEND | O_CREAT, 0666);
|
||||||
#else
|
#else
|
||||||
log_fd = open(LOGFILE, O_WRONLY|O_APPEND);
|
log_fd = open(LOGFILE, O_WRONLY | O_APPEND);
|
||||||
#endif
|
#endif
|
||||||
if (log_fd < 0) {
|
if (log_fd < 0) {
|
||||||
|
|
||||||
@@ -158,7 +159,7 @@ static void log_open(void)
|
|||||||
|
|
||||||
/* Permission problems should improve shortly ... */
|
/* Permission problems should improve shortly ... */
|
||||||
sleep(1);
|
sleep(1);
|
||||||
log_fd = open(LOGFILE, O_WRONLY|O_APPEND|O_CREAT, 0666);
|
log_fd = open(LOGFILE, O_WRONLY | O_APPEND | O_CREAT, 0666);
|
||||||
if (log_fd < 0) /* Nope, they didn't */
|
if (log_fd < 0) /* Nope, they didn't */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -209,7 +210,6 @@ static void log_args(int argc, char *argv[])
|
|||||||
log_close();
|
log_close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* Here we go */
|
/* Here we go */
|
||||||
|
|
||||||
@@ -220,7 +220,7 @@ int main(int argc, char *argv[], char *envp[])
|
|||||||
char buf[80];
|
char buf[80];
|
||||||
pid_t myproc;
|
pid_t myproc;
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
const struct futil_cmd_t * const *cmd;
|
const struct futil_cmd_t *const *cmd;
|
||||||
int i;
|
int i;
|
||||||
int via_symlink = 0;
|
int via_symlink = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,9 @@
|
|||||||
|
|
||||||
/* Here's a structure to define the commands that futility implements. */
|
/* Here's a structure to define the commands that futility implements. */
|
||||||
struct futil_cmd_t {
|
struct futil_cmd_t {
|
||||||
const char * const name;
|
const char *const name;
|
||||||
int (*const handler)(int argc, char **argv);
|
int (*const handler) (int argc, char **argv);
|
||||||
const char * const shorthelp;
|
const char *const shorthelp;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -33,7 +33,7 @@ struct futil_cmd_t {
|
|||||||
= &__cmd_##NAME
|
= &__cmd_##NAME
|
||||||
|
|
||||||
/* This is the list of pointers to all commands. */
|
/* This is the list of pointers to all commands. */
|
||||||
extern const struct futil_cmd_t * const futil_cmds[];
|
extern const struct futil_cmd_t *const futil_cmds[];
|
||||||
|
|
||||||
/* Size of an array */
|
/* Size of an array */
|
||||||
#ifndef ARRAY_SIZE
|
#ifndef ARRAY_SIZE
|
||||||
|
|||||||
@@ -1,29 +1,28 @@
|
|||||||
// Copyright 2010 The Chromium OS Authors. All rights reserved.
|
/* Copyright 2010 The Chromium OS Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
//
|
*
|
||||||
// Constants describing the kernel blob content.
|
* Constants describing the kernel blob content.
|
||||||
|
*/
|
||||||
#ifndef VBOOT_REFERENCE_KERNEL_BLOB_H_
|
#ifndef VBOOT_REFERENCE_KERNEL_BLOB_H_
|
||||||
#define VBOOT_REFERENCE_KERNEL_BLOB_H_
|
#define VBOOT_REFERENCE_KERNEL_BLOB_H_
|
||||||
|
|
||||||
|
/* Maximum kernel command-line size */
|
||||||
// Maximum kernel command-line size
|
|
||||||
#define CROS_CONFIG_SIZE 4096
|
#define CROS_CONFIG_SIZE 4096
|
||||||
|
|
||||||
// Size of the x86 zeropage table
|
/* Size of the x86 zeropage table */
|
||||||
#define CROS_PARAMS_SIZE 4096
|
#define CROS_PARAMS_SIZE 4096
|
||||||
|
|
||||||
// Alignment of various chunks within the kernel blob
|
/* Alignment of various chunks within the kernel blob */
|
||||||
#define CROS_ALIGN 4096
|
#define CROS_ALIGN 4096
|
||||||
|
|
||||||
// Sentinel RAM address indicating that no entry address is specified
|
/* Sentinel RAM address indicating that no entry address is specified */
|
||||||
#define CROS_NO_ENTRY_ADDR (~0)
|
#define CROS_NO_ENTRY_ADDR (~0)
|
||||||
|
|
||||||
// RAM address where the 32-bit kernel expects to be started
|
/* RAM address where the 32-bit kernel expects to be started */
|
||||||
#define CROS_32BIT_ENTRY_ADDR 0x100000
|
#define CROS_32BIT_ENTRY_ADDR 0x100000
|
||||||
|
|
||||||
// Simplified version of x86 kernel e820 memory map entries
|
/* Simplified version of x86 kernel e820 memory map entries */
|
||||||
#define E820_ENTRY_MAX 128
|
#define E820_ENTRY_MAX 128
|
||||||
#define E820_TYPE_RAM 1
|
#define E820_TYPE_RAM 1
|
||||||
#define E820_TYPE_RESERVED 2
|
#define E820_TYPE_RESERVED 2
|
||||||
@@ -32,34 +31,32 @@ struct linux_kernel_e820entry {
|
|||||||
uint64_t start_addr;
|
uint64_t start_addr;
|
||||||
uint64_t segment_size;
|
uint64_t segment_size;
|
||||||
uint32_t segment_type;
|
uint32_t segment_type;
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
// Simplified version of the x86 kernel zeropage table
|
|
||||||
struct linux_kernel_params
|
|
||||||
{
|
|
||||||
uint8_t pad0[0x1e8 - 0x0];
|
|
||||||
uint8_t n_e820_entry; // 1e8
|
|
||||||
uint8_t pad1[0x1f1 - 0x1e9];
|
|
||||||
uint8_t setup_sects; // 1f1
|
|
||||||
uint8_t pad2[0x1fe - 0x1f2];
|
|
||||||
uint16_t boot_flag; // 1fe
|
|
||||||
uint16_t jump; // 200
|
|
||||||
uint32_t header; // 202
|
|
||||||
uint16_t version; // 206
|
|
||||||
uint8_t pad3[0x210 - 0x208];
|
|
||||||
uint8_t type_of_loader; // 210
|
|
||||||
uint8_t pad4[0x218 - 0x211];
|
|
||||||
uint32_t ramdisk_image; // 218
|
|
||||||
uint32_t ramdisk_size; // 21c
|
|
||||||
uint8_t pad5[0x228 - 0x220];
|
|
||||||
uint32_t cmd_line_ptr; // 228
|
|
||||||
uint32_t ramdisk_max; // 22c
|
|
||||||
uint32_t kernel_alignment; // 230
|
|
||||||
uint8_t relocatable_kernel; // 234
|
|
||||||
uint8_t min_alignment; // 235
|
|
||||||
uint8_t pad6[0x2d0 - 0x236];
|
|
||||||
struct linux_kernel_e820entry e820_entries[E820_ENTRY_MAX]; // 2d0 - cd0
|
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
/* Simplified version of the x86 kernel zeropage table */
|
||||||
|
struct linux_kernel_params {
|
||||||
|
uint8_t pad0[0x1e8 - 0x0];
|
||||||
|
uint8_t n_e820_entry; /* 1e8 */
|
||||||
|
uint8_t pad1[0x1f1 - 0x1e9];
|
||||||
|
uint8_t setup_sects; /* 1f1 */
|
||||||
|
uint8_t pad2[0x1fe - 0x1f2];
|
||||||
|
uint16_t boot_flag; /* 1fe */
|
||||||
|
uint16_t jump; /* 200 */
|
||||||
|
uint32_t header; /* 202 */
|
||||||
|
uint16_t version; /* 206 */
|
||||||
|
uint8_t pad3[0x210 - 0x208];
|
||||||
|
uint8_t type_of_loader; /* 210 */
|
||||||
|
uint8_t pad4[0x218 - 0x211];
|
||||||
|
uint32_t ramdisk_image; /* 218 */
|
||||||
|
uint32_t ramdisk_size; /* 21c */
|
||||||
|
uint8_t pad5[0x228 - 0x220];
|
||||||
|
uint32_t cmd_line_ptr; /* 228 */
|
||||||
|
uint32_t ramdisk_max; /* 22c */
|
||||||
|
uint32_t kernel_alignment; /* 230 */
|
||||||
|
uint8_t relocatable_kernel; /* 234 */
|
||||||
|
uint8_t min_alignment; /* 235 */
|
||||||
|
uint8_t pad6[0x2d0 - 0x236];
|
||||||
|
struct linux_kernel_e820entry e820_entries[E820_ENTRY_MAX]; /* 2d0-cd0 */
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
#endif // VBOOT_REFERENCE_KERNEL_BLOB_H_
|
#endif /* VBOOT_REFERENCE_KERNEL_BLOB_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user