Commit 68965c48 authored by Sophie Brun's avatar Sophie Brun

New upstream version 0~R63-10032.B

parent 237d850b
......@@ -46,9 +46,7 @@ VBSF_SRCS = \
firmware/lib/cryptolib/sha512.c \
firmware/lib/cryptolib/sha_utility.c \
firmware/lib/stateful_util.c \
firmware/lib/vboot_api_firmware.c \
firmware/lib/vboot_common.c \
firmware/lib/vboot_firmware.c \
firmware/lib/region-fw.c \
# Additional firmware library sources needed by VbSelectAndLoadKernel() call
......
This diff is collapsed.
BDB library and utilities
Boot Descriptor Block (BDB) library and utilities
Building:
---------
......
......@@ -149,6 +149,9 @@ void EntryDetails(GptEntry *entry, uint32_t index, int raw);
uint32_t GetNumberOfEntries(const struct drive *drive);
GptEntry *GetEntry(GptData *gpt, int secondary, uint32_t entry_index);
void SetLegacyBoot(struct drive *drive, int secondary, uint32_t entry_index,
int legacy_boot);
int GetLegacyBoot(struct drive *drive, int secondary, uint32_t entry_index);
void SetPriority(struct drive *drive, int secondary, uint32_t entry_index,
int priority);
int GetPriority(struct drive *drive, int secondary, uint32_t entry_index);
......@@ -187,6 +190,8 @@ void Error(const char *format, ...);
void Warning(const char *format, ...);
// Command functions.
int check_int_parse(char option, const char *buf);
int check_int_limit(char option, int val, int low, int high);
int cmd_show(int argc, char *argv[]);
int cmd_repair(int argc, char *argv[]);
int cmd_create(int argc, char *argv[]);
......
......@@ -4,8 +4,6 @@
#include <string.h>
#define _STUB_IMPLEMENTATION_
#include "cgpt.h"
#include "cgpt_params.h"
#include "cgptlib_internal.h"
......@@ -55,6 +53,10 @@ static const char* DumpCgptAddParams(const CgptAddParams *params) {
snprintf(tmp, sizeof(tmp), "-P %d ", params->priority);
StrnAppend(buf, tmp, sizeof(buf));
}
if (params->set_legacy_boot) {
snprintf(tmp, sizeof(tmp), "-B %d ", params->legacy_boot);
StrnAppend(buf, tmp, sizeof(buf));
}
if (params->set_raw) {
snprintf(tmp, sizeof(tmp), "-A 0x%x ", params->raw_value);
StrnAppend(buf, tmp, sizeof(buf));
......@@ -109,6 +111,8 @@ static int SetEntryAttributes(struct drive *drive,
SetTries(drive, PRIMARY, index, params->tries);
if (params->set_priority)
SetPriority(drive, PRIMARY, index, params->priority);
if (params->set_legacy_boot)
SetLegacyBoot(drive, PRIMARY, index, params->legacy_boot);
}
// New partitions must specify type, begin, and size.
......@@ -134,10 +138,8 @@ static int CgptCheckAddValidity(struct drive *drive) {
return -1;
}
if (((drive->gpt.valid_headers & MASK_BOTH) != MASK_BOTH) ||
((drive->gpt.valid_entries & MASK_BOTH) != MASK_BOTH)) {
Error("one of the GPT header/entries is invalid.\n"
"please run 'cgpt repair' before adding anything.\n");
if (CGPT_OK != CheckValid(drive)) {
Error("please run 'cgpt repair' before adding anything.\n");
return -1;
}
......
......@@ -51,6 +51,22 @@ void Warning(const char *format, ...) {
va_end(ap);
}
int check_int_parse(char option, const char *buf) {
if (!*optarg || (buf && *buf)) {
Error("invalid argument to -%c: \"%s\"\n", option, optarg);
return 1;
}
return 0;
}
int check_int_limit(char option, int val, int low, int high) {
if (val < low || val > high) {
Error("value for -%c must be between %d and %d", option, low, high);
return 1;
}
return 0;
}
int CheckValid(const struct drive *drive) {
if ((drive->gpt.valid_headers != MASK_BOTH) ||
(drive->gpt.valid_entries != MASK_BOTH)) {
......@@ -747,6 +763,20 @@ GptEntry *GetEntry(GptData *gpt, int secondary, uint32_t entry_index) {
return (GptEntry*)(&entries[stride * entry_index]);
}
void SetLegacyBoot(struct drive *drive, int secondary, uint32_t entry_index,
int legacy_boot) {
require(legacy_boot >= 0 && legacy_boot <= CGPT_ATTRIBUTE_MAX_LEGACY_BOOT);
GptEntry *entry;
entry = GetEntry(&drive->gpt, secondary, entry_index);
SetEntryLegacyBoot(entry, legacy_boot);
}
int GetLegacyBoot(struct drive *drive, int secondary, uint32_t entry_index) {
GptEntry *entry;
entry = GetEntry(&drive->gpt, secondary, entry_index);
return GetEntryLegacyBoot(entry);
}
void SetPriority(struct drive *drive, int secondary, uint32_t entry_index,
int priority) {
require(priority >= 0 && priority <= CGPT_ATTRIBUTE_MAX_PRIORITY);
......
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <ctype.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
......@@ -74,7 +75,14 @@ static int match_content(CgptFindParams *params, struct drive *drive,
static void showmatch(CgptFindParams *params, char *filename,
int partnum, GptEntry *entry) {
char * format = "%s%d\n";
if (strncmp("/dev/mmcblk", filename, 11) == 0)
/*
* Follow convention from disk_name() in kernel block/partition-generic.c
* code:
* If the last digit of the device name is a number, add a 'p' between the
* device name and the partition number.
*/
if (isdigit(filename[strlen(filename) - 1]))
format = "%sp%d\n";
if (params->numeric) {
......@@ -169,6 +177,7 @@ static int do_search(CgptFindParams *params, char *fileName) {
#define PROC_PARTITIONS "/proc/partitions"
#define DEV_DIR "/dev"
#define SYS_BLOCK_DIR "/sys/block"
#define MAX_PARTITION_NAME_LEN 128
static const char *devdirs[] = { "/dev", "/devices", "/devfs", 0 };
......@@ -211,7 +220,8 @@ static char *is_wholedev(const char *basename) {
// returns true if any matches were found, false otherwise.
static int scan_real_devs(CgptFindParams *params) {
int found = 0;
char partname[128]; // max size for /proc/partition lines?
char partname[MAX_PARTITION_NAME_LEN];
char partname_prev[MAX_PARTITION_NAME_LEN];
FILE *fp;
char *pathname;
......@@ -223,6 +233,7 @@ static int scan_real_devs(CgptFindParams *params) {
size_t line_length = 0;
char *line = NULL;
partname_prev[0] = '\0';
while (getline(&line, &line_length, fp) != -1) {
int ma, mi;
long long unsigned int sz;
......@@ -230,11 +241,19 @@ static int scan_real_devs(CgptFindParams *params) {
if (sscanf(line, " %d %d %llu %127[^\n ]", &ma, &mi, &sz, partname) != 4)
continue;
if ((pathname = is_wholedev(partname))) {
if (do_search(params, pathname)) {
found++;
/* Only check devices that have partitions under them.
* We can tell by checking that an entry like "sda" is immediately
* followed by one like "sda0". */
if (!strncmp(partname_prev, partname, strlen(partname_prev)) &&
strlen(partname_prev)) {
if ((pathname = is_wholedev(partname_prev))) {
if (do_search(params, pathname)) {
found++;
}
}
}
strcpy(partname_prev, partname);
}
fclose(fp);
......
......@@ -77,6 +77,7 @@ int ForkExecL(const char *cwd, const char *cmd, ...) {
const char **argv = calloc(argc + 1, sizeof(char *));
if (argv == NULL) {
errno = ENOMEM;
va_end(ap);
return -1;
}
argv[0] = cmd;
......@@ -211,7 +212,8 @@ int ReadNorFlash(char *temp_dir_template) {
ret++;
int fd_flags = fcntl(1, F_GETFD);
// Close stdout on exec so that flashrom does not muck up cgpt's output.
fcntl(1, F_SETFD, FD_CLOEXEC);
if (0 != fcntl(1, F_SETFD, FD_CLOEXEC))
Warning("Can't stop flashrom from mucking up our output\n");
if (ForkExecL(temp_dir_template, FLASHROM_PATH, "-i", "RW_GPT:rw_gpt", "-r",
NULL) != 0) {
Error("Cannot exec flashrom to read from RW_GPT section.\n");
......@@ -220,7 +222,9 @@ int ReadNorFlash(char *temp_dir_template) {
ret = 0;
}
fcntl(1, F_SETFD, fd_flags);
// Restore stdout flags
if (0 != fcntl(1, F_SETFD, fd_flags))
Warning("Can't restore stdout flags\n");
return ret;
}
......@@ -236,7 +240,8 @@ int WriteNorFlash(const char *dir) {
int nr_fails = 0;
int fd_flags = fcntl(1, F_GETFD);
// Close stdout on exec so that flashrom does not muck up cgpt's output.
fcntl(1, F_SETFD, FD_CLOEXEC);
if (0 != fcntl(1, F_SETFD, FD_CLOEXEC))
Warning("Can't stop flashrom from mucking up our output\n");
if (ForkExecL(dir, FLASHROM_PATH, "-i", "RW_GPT_PRIMARY:rw_gpt_1",
"-w", "--fast-verify", NULL) != 0) {
Warning("Cannot write the 1st half of rw_gpt back with flashrom.\n");
......@@ -247,7 +252,8 @@ int WriteNorFlash(const char *dir) {
Warning("Cannot write the 2nd half of rw_gpt back with flashrom.\n");
nr_fails++;
}
fcntl(1, F_SETFD, fd_flags);
if (0 != fcntl(1, F_SETFD, fd_flags))
Warning("Can't restore stdout flags\n");
switch (nr_fails) {
case 0: ret = 0; break;
case 1: Warning("It might still be okay.\n"); break;
......
......@@ -116,6 +116,11 @@ int CgptPrioritize(CgptPrioritizeParams *params) {
return CGPT_FAILED;
}
if (CGPT_OK != CheckValid(&drive)) {
Error("please run 'cgpt repair' before reordering the priority.\n");
return CGPT_OK;
}
max_part = GetNumberOfEntries(&drive);
if (params->set_partition) {
......
......@@ -44,9 +44,9 @@ static void RawDump(const uint8_t *memory, const int size,
/* Output formatters */
#define TITLE_FMT "%12s%12s%8s %s\n"
#define GPT_FMT "%12d%12d%8s %s\n"
#define GPT_FMT "%12"PRId64"%12"PRId64"%8s %s\n"
#define GPT_MORE "%12s%12s%8s ", "", "", ""
#define PARTITION_FMT "%12d%12d%8d %s\n"
#define PARTITION_FMT "%12"PRId64"%12"PRId64"%8d %s\n"
#define PARTITION_MORE "%12s%12s%8s %s%s\n", "", "", ""
void PrintSignature(const char *indent, const char *sig, size_t n, int raw) {
......@@ -100,13 +100,14 @@ void EntryDetails(GptEntry *entry, uint32_t index, int raw) {
char contents[256]; // scratch buffer for formatting output
uint8_t label[GPT_PARTNAME_LEN];
char type[GUID_STRLEN], unique[GUID_STRLEN];
int clen;
UTF16ToUTF8(entry->name, sizeof(entry->name) / sizeof(entry->name[0]),
label, sizeof(label));
require(snprintf(contents, sizeof(contents),
"Label: \"%s\"", label) < sizeof(contents));
printf(PARTITION_FMT, (int)entry->starting_lba,
(int)(entry->ending_lba - entry->starting_lba + 1),
printf(PARTITION_FMT, (uint64_t)entry->starting_lba,
(uint64_t)(entry->ending_lba - entry->starting_lba + 1),
index+1, contents);
if (!raw && CGPT_OK == ResolveType(&entry->type, type)) {
......@@ -118,6 +119,7 @@ void EntryDetails(GptEntry *entry, uint32_t index, int raw) {
GuidToStr(&entry->unique, unique, GUID_STRLEN);
printf(PARTITION_MORE, "UUID: ", unique);
clen = 0;
if (!raw) {
if (GuidEqual(&guid_chromeos_kernel, &entry->type)) {
int tries = (entry->attrs.fields.gpt_att &
......@@ -129,16 +131,35 @@ void EntryDetails(GptEntry *entry, uint32_t index, int raw) {
int priority = (entry->attrs.fields.gpt_att &
CGPT_ATTRIBUTE_PRIORITY_MASK) >>
CGPT_ATTRIBUTE_PRIORITY_OFFSET;
require(snprintf(contents, sizeof(contents),
"priority=%d tries=%d successful=%d",
priority, tries, successful) < sizeof(contents));
printf(PARTITION_MORE, "Attr: ", contents);
clen = snprintf(contents, sizeof(contents),
"priority=%d tries=%d successful=%d ",
priority, tries, successful);
}
if (entry->attrs.fields.system) {
clen += snprintf(contents + clen, sizeof(contents) - clen,
"system=%d ", entry->attrs.fields.system);
require(clen < sizeof(contents));
}
if (entry->attrs.fields.efi_ignore) {
clen += snprintf(contents + clen, sizeof(contents) - clen,
"efi_ignore=%d ", entry->attrs.fields.efi_ignore);
require(clen < sizeof(contents));
}
if (entry->attrs.fields.legacy_boot) {
clen += snprintf(contents + clen, sizeof(contents) - clen,
"legacy_boot=%d ", entry->attrs.fields.legacy_boot);
require(clen < sizeof(contents));
}
} else {
require(snprintf(contents, sizeof(contents),
"[%x]", entry->attrs.fields.gpt_att) < sizeof(contents));
printf(PARTITION_MORE, "Attr: ", contents);
clen = snprintf(contents, sizeof(contents),
"[%x]", entry->attrs.fields.gpt_att);
}
require(clen < sizeof(contents));
if (clen)
printf(PARTITION_MORE, "Attr: ", contents);
}
void EntriesDetails(struct drive *drive, const int secondary, int raw) {
......@@ -209,6 +230,9 @@ static int GptShow(struct drive *drive, CgptShowParams *params) {
case 'P':
printf("%d\n", GetPriority(drive, ANY_VALID, index));
break;
case 'B':
printf("%d\n", GetLegacyBoot(drive, ANY_VALID, index));
break;
case 'A':
printf("0x%x\n", entry->attrs.fields.gpt_att);
break;
......@@ -233,8 +257,8 @@ static int GptShow(struct drive *drive, CgptShowParams *params) {
} else {
GuidToStr(&entry->type, type, GUID_STRLEN);
}
printf(PARTITION_FMT, (int)entry->starting_lba,
(int)(entry->ending_lba - entry->starting_lba + 1),
printf(PARTITION_FMT, (uint64_t)entry->starting_lba,
(uint64_t)(entry->ending_lba - entry->starting_lba + 1),
i+1, type);
}
} else { // show all partitions
......@@ -248,18 +272,18 @@ static int GptShow(struct drive *drive, CgptShowParams *params) {
printf(TITLE_FMT, "start", "size", "part", "contents");
char buf[256]; // buffer for formatted PMBR content
PMBRToStr(&drive->pmbr, buf, sizeof(buf)); // will exit if buf is too small
printf(GPT_FMT, 0, GPT_PMBR_SECTORS, "", buf);
printf(GPT_FMT, (uint64_t)0, (uint64_t)GPT_PMBR_SECTORS, "", buf);
if (drive->gpt.ignored & MASK_PRIMARY) {
printf(GPT_FMT, (int)GPT_PMBR_SECTORS,
(int)GPT_HEADER_SECTORS, "IGNORED", "Pri GPT header");
printf(GPT_FMT, (uint64_t)GPT_PMBR_SECTORS,
(uint64_t)GPT_HEADER_SECTORS, "IGNORED", "Pri GPT header");
} else {
if (drive->gpt.valid_headers & MASK_PRIMARY) {
printf(GPT_FMT, (int)GPT_PMBR_SECTORS,
(int)GPT_HEADER_SECTORS, "", "Pri GPT header");
printf(GPT_FMT, (uint64_t)GPT_PMBR_SECTORS,
(uint64_t)GPT_HEADER_SECTORS, "", "Pri GPT header");
} else {
printf(GPT_FMT, (int)GPT_PMBR_SECTORS,
(int)GPT_HEADER_SECTORS, "INVALID", "Pri GPT header");
printf(GPT_FMT, (uint64_t)GPT_PMBR_SECTORS,
(uint64_t)GPT_HEADER_SECTORS, "INVALID", "Pri GPT header");
}
if (params->debug ||
......@@ -274,8 +298,8 @@ static int GptShow(struct drive *drive, CgptShowParams *params) {
}
GptHeader* primary_header = (GptHeader*)drive->gpt.primary_header;
printf(GPT_FMT, (int)primary_header->entries_lba,
(int)CalculateEntriesSectors(primary_header),
printf(GPT_FMT, (uint64_t)primary_header->entries_lba,
(uint64_t)CalculateEntriesSectors(primary_header),
drive->gpt.valid_entries & MASK_PRIMARY ? "" : "INVALID",
"Pri GPT table");
......@@ -286,12 +310,13 @@ static int GptShow(struct drive *drive, CgptShowParams *params) {
/****************************** Secondary *************************/
if (drive->gpt.ignored & MASK_SECONDARY) {
printf(GPT_FMT, (int)(drive->gpt.gpt_drive_sectors - GPT_HEADER_SECTORS),
(int)GPT_HEADER_SECTORS, "IGNORED", "Sec GPT header");
printf(GPT_FMT,
(uint64_t)(drive->gpt.gpt_drive_sectors - GPT_HEADER_SECTORS),
(uint64_t)GPT_HEADER_SECTORS, "IGNORED", "Sec GPT header");
} else {
GptHeader* secondary_header = (GptHeader*)drive->gpt.secondary_header;
printf(GPT_FMT, (int)secondary_header->entries_lba,
(int)CalculateEntriesSectors(secondary_header),
printf(GPT_FMT, (uint64_t)secondary_header->entries_lba,
(uint64_t)CalculateEntriesSectors(secondary_header),
drive->gpt.valid_entries & MASK_SECONDARY ? "" : "INVALID",
"Sec GPT table");
/* We show secondary table details if any of following is true.
......@@ -310,11 +335,12 @@ static int GptShow(struct drive *drive, CgptShowParams *params) {
}
if (drive->gpt.valid_headers & MASK_SECONDARY) {
printf(GPT_FMT, (int)(drive->gpt.gpt_drive_sectors - GPT_HEADER_SECTORS),
(int)GPT_HEADER_SECTORS, "", "Sec GPT header");
printf(GPT_FMT,
(uint64_t)(drive->gpt.gpt_drive_sectors - GPT_HEADER_SECTORS),
(uint64_t)GPT_HEADER_SECTORS, "", "Sec GPT header");
} else {
printf(GPT_FMT, (int)GPT_PMBR_SECTORS,
(int)GPT_HEADER_SECTORS, "INVALID", "Sec GPT header");
printf(GPT_FMT, (uint64_t)GPT_PMBR_SECTORS,
(uint64_t)GPT_HEADER_SECTORS, "INVALID", "Sec GPT header");
}
/* We show secondary header if any of following is true:
* 1. in debug mode.
......
......@@ -22,9 +22,13 @@
#include <sys/types.h>
#include <unistd.h>
#include "2sysincludes.h"
#include "2common.h"
#include "2sha.h"
#include "cgpt.h"
#include "cgpt_nor.h"
#include "cryptolib.h"
#include "file_keys.h"
// Check if cmdline |argv| has "-D". "-D" signifies that GPT structs are stored
// off device, and hence we should not wrap around cgpt.
......@@ -67,8 +71,8 @@ static const char *find_mtd_device(int argc, const char *const argv[]) {
static int wrap_cgpt(int argc,
const char *const argv[],
const char *mtd_device) {
uint8_t *original_hash = NULL;
uint8_t *modified_hash = NULL;
uint8_t original_hash[VB2_SHA1_DIGEST_SIZE];
uint8_t modified_hash[VB2_SHA1_DIGEST_SIZE];
int ret = 0;
// Create a temp dir to work in.
......@@ -81,7 +85,11 @@ static int wrap_cgpt(int argc,
if (snprintf(rw_gpt_path, sizeof(rw_gpt_path), "%s/rw_gpt", temp_dir) < 0) {
goto cleanup;
}
original_hash = DigestFile(rw_gpt_path, SHA1_DIGEST_ALGORITHM);
if (VB2_SUCCESS != DigestFile(rw_gpt_path, VB2_HASH_SHA1,
original_hash, sizeof(original_hash))) {
Error("Cannot compute original GPT digest.\n");
goto cleanup;
}
// Obtain the MTD size.
ret++;
......@@ -126,9 +134,9 @@ static int wrap_cgpt(int argc,
// Write back "rw_gpt" to NOR flash in two chunks.
ret++;
modified_hash = DigestFile(rw_gpt_path, SHA1_DIGEST_ALGORITHM);
if (original_hash != NULL && modified_hash != NULL) {
if (memcmp(original_hash, modified_hash, SHA1_DIGEST_SIZE) != 0) {
if (VB2_SUCCESS == DigestFile(rw_gpt_path, VB2_HASH_SHA1,
modified_hash, sizeof(modified_hash))) {
if (memcmp(original_hash, modified_hash, VB2_SHA1_DIGEST_SIZE) != 0) {
ret = WriteNorFlash(temp_dir);
} else {
ret = 0;
......@@ -136,8 +144,6 @@ static int wrap_cgpt(int argc,
}
cleanup:
free(original_hash);
free(modified_hash);
RemoveDir(temp_dir);
return ret;
}
......@@ -146,11 +152,14 @@ int main(int argc, const char *argv[]) {
char resolved_cgpt[PATH_MAX];
pid_t pid = getpid();
char exe_link[40];
int retval = 0;
if (argc < 1) {
return -1;
}
const char *orig_argv0 = argv[0];
snprintf(exe_link, sizeof(exe_link), "/proc/%d/exe", pid);
memset(resolved_cgpt, 0, sizeof(resolved_cgpt));
if (readlink(exe_link, resolved_cgpt, sizeof(resolved_cgpt) - 1) == -1) {
......@@ -163,18 +172,25 @@ int main(int argc, const char *argv[]) {
if (argc > 2 && !has_dash_D(argc, argv)) {
const char *mtd_device = find_mtd_device(argc, argv);
if (mtd_device) {
return wrap_cgpt(argc, argv, mtd_device);
retval = wrap_cgpt(argc, argv, mtd_device);
goto cleanup;
}
}
// Forward to cgpt as-is. Real cgpt has been renamed cgpt.bin.
char *real_cgpt;
if (asprintf(&real_cgpt, "%s.bin", argv[0]) == -1) {
return -1;
retval = -1;
goto cleanup;
}
argv[0] = real_cgpt;
if (execv(argv[0], (char * const *)argv) == -1) {
err(-2, "execv(%s) failed", real_cgpt);
}
return -2;
free(real_cgpt);
retval = -2;
cleanup:
argv[0] = orig_argv0;
return retval;
}
......@@ -27,7 +27,8 @@ static void Usage(void)
" -S NUM set Successful flag (0|1)\n"
" -T NUM set Tries flag (0-15)\n"
" -P NUM set Priority flag (0-15)\n"
" -A NUM set raw 64-bit attribute value\n"
" -B NUM set Legacy Boot flag (0|1)\n"
" -A NUM set raw 16-bit attribute value (bits 48-63)\n"
"\n"
"Use the -i option to modify an existing partition.\n"
"The -b, -s, and -t options must be given for new partitions.\n"
......@@ -45,43 +46,27 @@ int cmd_add(int argc, char *argv[]) {
char *e = 0;
opterr = 0; // quiet, you
while ((c=getopt(argc, argv, ":hi:b:s:t:u:l:S:T:P:A:D:")) != -1)
while ((c=getopt(argc, argv, ":hi:b:s:t:u:l:S:T:P:B:A:D:")) != -1)
{
switch (c)
{
case 'D':
params.drive_size = strtoull(optarg, &e, 0);
if (!*optarg || (e && *e))
{
Error("invalid argument to -%c: \"%s\"\n", c, optarg);
errorcnt++;
}
errorcnt += check_int_parse(c, e);
break;
case 'i':
params.partition = (uint32_t)strtoul(optarg, &e, 0);
if (!*optarg || (e && *e))
{
Error("invalid argument to -%c: \"%s\"\n", c, optarg);