Enable attributes to display and set properly.

Review URL: http://codereview.chromium.org/2614002
This commit is contained in:
Bill Richardson
2010-06-04 12:26:42 -07:00
parent af5ae8e21b
commit 77d26e5190
8 changed files with 102 additions and 79 deletions

View File

@@ -142,6 +142,7 @@ void UTF16ToUTF8(const uint16_t *utf16, uint8_t *utf8)
utf8[s8idx++] = 0x80 | (utfchar & 0x3f); utf8[s8idx++] = 0x80 | (utfchar & 0x3f);
} }
} }
utf8[s8idx++] = 0;
} }
/* Convert UTF8 string to UTF16. Rewritten from gpt utility. /* Convert UTF8 string to UTF16. Rewritten from gpt utility.
@@ -209,10 +210,11 @@ struct {
char *description; char *description;
} supported_types[] = { } supported_types[] = {
{GPT_ENT_TYPE_UNUSED, "unused", "Unused partition"}, {GPT_ENT_TYPE_UNUSED, "unused", "Unused partition"},
{GPT_ENT_TYPE_EFI, "efi", "EFI partition"}, {GPT_ENT_TYPE_EFI, "efi", "EFI System Partition"},
{GPT_ENT_TYPE_CHROMEOS_KERNEL, "croskern", "ChromeOS kernel"}, {GPT_ENT_TYPE_CHROMEOS_KERNEL, "croskern", "ChromeOS kernel"},
{GPT_ENT_TYPE_CHROMEOS_ROOTFS, "crosroot", "ChromeOS rootfs"}, {GPT_ENT_TYPE_CHROMEOS_ROOTFS, "crosroot", "ChromeOS rootfs"},
{GPT_ENT_TYPE_CHROMEOS_RESERVED, "crosresv", "ChromeOS reserved"}, {GPT_ENT_TYPE_CHROMEOS_RESERVED, "crosresv", "ChromeOS reserved"},
{GPT_ENT_TYPE_LINUX_DATA, "data", "Linux data"},
}; };
/* Resolves human-readable GPT type. /* Resolves human-readable GPT type.
@@ -444,7 +446,6 @@ int main(int argc, char *argv[]) {
int i; int i;
progname = argv[0]; progname = argv[0];
printf("Copyright (c) 2010 The Chromium OS Authors. All rights reserved.\n");
cmd = argv[optind++]; cmd = argv[optind++];
for (i = 0; i < sizeof(cmds)/sizeof(cmds[0]); ++i) { for (i = 0; i < sizeof(cmds)/sizeof(cmds[0]); ++i) {
if (cmd && !strcmp(cmds[i].name, cmd)) if (cmd && !strcmp(cmds[i].name, cmd))

View File

@@ -120,6 +120,7 @@ void UTF8ToUTF16(const uint8_t *utf8, uint16_t *utf16);
int ResolveType(const Guid *type, char *buf); int ResolveType(const Guid *type, char *buf);
int SupportedType(const char *name, Guid *type); int SupportedType(const char *name, Guid *type);
void PrintTypes(void); void PrintTypes(void);
void EntryDetails(GptEntry *entry, int index, int raw);
/* Describes the drive storing the GPT. */ /* Describes the drive storing the GPT. */
struct drive { struct drive {

View File

@@ -242,8 +242,7 @@ int CgptAdm(int argc, char *argv[]) {
} }
if (command == DELETE) { if (command == DELETE) {
Guid unused = GPT_ENT_TYPE_UNUSED; Memcpy(&entry->type, &guid_unused, sizeof(Guid));
Memcpy(&entry->type, &unused, sizeof(Guid));
} }
if (dirty) { if (dirty) {

View File

@@ -12,19 +12,18 @@
#include "cgpt_tofix.h" #include "cgpt_tofix.h"
#include "utility.h" #include "utility.h"
static struct number_range static struct number_range range_1_0 = {1, 0};
range_1_0 = {1, 0}, static struct number_range range_15_0 = {15, 0};
range_15_0 = {15, 0}; static struct number_range range_16_1 = {16, 1};
/* Integers to store parsed argument. */ /* Integers to store parsed argument. */
static int help, partition, bad, successful, tries, priority; static int help, partition, successful, tries, priority;
/* The structure for getopt_long(). When you add/delete any line, please refine /* The structure for getopt_long(). When you add/delete any line, please refine
* attribute_comments[] and third parameter of getopt_long() too. */ * attribute_comments[] and third parameter of getopt_long() too. */
static struct option attribute_options[] = { static struct option attribute_options[] = {
{.name = "help", .has_arg = no_argument, .flag = 0, .val = 'h'}, {.name = "help", .has_arg = no_argument, .flag = 0, .val = 'h'},
{.name = "partition", .has_arg = required_argument, .flag = 0, .val = 'i'}, {.name = "partition", .has_arg = required_argument, .flag = 0, .val = 'i'},
{.name = "bad", .has_arg = required_argument, .flag = 0, .val = 'b'},
{.name = "successful", .has_arg = required_argument, .flag = 0, .val = 's'}, {.name = "successful", .has_arg = required_argument, .flag = 0, .val = 's'},
{.name = "tries", .has_arg = required_argument, .flag = 0, .val = 't'}, {.name = "tries", .has_arg = required_argument, .flag = 0, .val = 't'},
{.name = "priority", .has_arg = required_argument, .flag = 0, .val = 'p'}, {.name = "priority", .has_arg = required_argument, .flag = 0, .val = 'p'},
@@ -41,15 +40,10 @@ static struct option_details attribute_options_details[] = {
.parsed = &help}, .parsed = &help},
/* partition */ /* partition */
{ .comment = "partition number " { .comment = "partition number "
"(defualt: first ChromeOS kernel)", "(default: first ChromeOS kernel)",
.validator = InNumberRange, .validator = InNumberRange,
.valid_range = &range_15_0, .valid_range = &range_16_1,
.parsed = &partition}, .parsed = &partition},
/* bad */
{ .comment = "mark partition bad",
.validator = InNumberRange,
.valid_range = &range_1_0,
.parsed = &bad},
/* successful */ /* successful */
{ .comment = "mark partition successful", { .comment = "mark partition successful",
.validator = InNumberRange, .validator = InNumberRange,
@@ -72,13 +66,13 @@ void AttributeHelp() {
printf("\nUsage: %s attribute [OPTIONS] device_name\n\n", progname); printf("\nUsage: %s attribute [OPTIONS] device_name\n\n", progname);
ShowOptions(attribute_options, attribute_options_details, ShowOptions(attribute_options, attribute_options_details,
ARRAY_COUNT(attribute_options)); ARRAY_COUNT(attribute_options));
printf("\n* Attribute command only applies on ChromeOS kernel entry.\n\n");
} }
/* Parses all options (and validates them), then opens the drive and sets /* Parses all options (and validates them), then opens the drive and sets
* corresponding bits in GPT entry. */ * corresponding bits in GPT entry. */
int CgptAttribute(int argc, char *argv[]) { int CgptAttribute(int argc, char *argv[]) {
struct drive drive; struct drive drive;
GptEntry *entry;
/* I know this is NOT the perfect place to put code to make options[] and /* I know this is NOT the perfect place to put code to make options[] and
* details[] are synced. But this is the best place we have right now since C * details[] are synced. But this is the best place we have right now since C
@@ -86,7 +80,7 @@ int CgptAttribute(int argc, char *argv[]) {
assert(ARRAY_COUNT(attribute_options) == assert(ARRAY_COUNT(attribute_options) ==
ARRAY_COUNT(attribute_options_details)); ARRAY_COUNT(attribute_options_details));
help = partition = bad = successful = tries = priority = NOT_INITED; help = partition = successful = tries = priority = NOT_INITED;
if (CGPT_OK != HandleOptions(argc, argv, if (CGPT_OK != HandleOptions(argc, argv,
"hi:b:s:t:p:", "hi:b:s:t:p:",
@@ -108,31 +102,34 @@ int CgptAttribute(int argc, char *argv[]) {
if (partition == NOT_INITED) { if (partition == NOT_INITED) {
int i; int i;
for (i = 0; i < GetNumberOfEntries(&drive.gpt); ++i) { for (i = 0; i < GetNumberOfEntries(&drive.gpt); ++i) {
static Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
GptEntry *entry;
entry = GetEntry(&drive.gpt, PRIMARY, i); entry = GetEntry(&drive.gpt, PRIMARY, i);
if (!Memcmp(&chromeos_kernel, &entry->type, sizeof(Guid))) { if (!Memcmp(&guid_chromeos_kernel, &entry->type, sizeof(Guid))) {
partition = i; partition = i+1;
break; break;
} }
} }
if (partition == NOT_INITED) { if (partition == NOT_INITED) {
printf("[ERROR] No ChromeOS kernel is found. " printf("[ERROR] No ChromeOS kernel partition found. "
"Please use --partition to specify.\n"); "Please use --partition to specify.\n");
return CGPT_FAILED; return CGPT_FAILED;
} else { } else {
debug("No --partition is specified. " debug("No --partition is specified. "
"Found the first ChromeOS kernel at index [%d].\n", "Found the first ChromeOS kernel in partition [%d].\n",
partition); partition);
} }
} }
int index = partition - 1;
if (successful != NOT_INITED) if (successful != NOT_INITED)
SetSuccessful(&drive.gpt, PRIMARY, partition, successful); SetSuccessful(&drive.gpt, PRIMARY, index, successful);
if (tries != NOT_INITED) if (tries != NOT_INITED)
SetTries(&drive.gpt, PRIMARY, partition, tries); SetTries(&drive.gpt, PRIMARY, index, tries);
if (priority != NOT_INITED) if (priority != NOT_INITED)
SetPriority(&drive.gpt, PRIMARY, partition, priority); SetPriority(&drive.gpt, PRIMARY, index, priority);
/* Display state */
entry = GetEntry(&drive.gpt, PRIMARY, index);
EntryDetails(entry, index, NOT_INITED);
/* Claims primary is good, then secondary will be overwritten. */ /* Claims primary is good, then secondary will be overwritten. */
/* TODO: rspangler broke this during cgptlib refactoring; need to /* TODO: rspangler broke this during cgptlib refactoring; need to

View File

@@ -88,11 +88,11 @@ static void RawDump(const uint8_t *memory, const int size,
#define PARTITION_FMT "%10d%10d%8d %s\n" #define PARTITION_FMT "%10d%10d%8d %s\n"
#define PARTITION_MORE "%10s%10s%8s %s%s\n", "", "", "" #define PARTITION_MORE "%10s%10s%8s %s%s\n", "", "", ""
static void HeaderDetails(GptHeader *header, const char *indent) { static void HeaderDetails(GptHeader *header, const char *indent, int raw) {
int i; int i;
printf("%sSig: ", indent); printf("%sSig: ", indent);
if (number == NOT_INITED) { if (raw == NOT_INITED) {
printf("["); printf("[");
for (i = 0; i < sizeof(header->signature); ++i) for (i = 0; i < sizeof(header->signature); ++i)
printf("%c", header->signature[i]); printf("%c", header->signature[i]);
@@ -123,52 +123,66 @@ static void HeaderDetails(GptHeader *header, const char *indent) {
printf("%sEntries CRC: 0x%08x\n", indent, header->entries_crc32); printf("%sEntries CRC: 0x%08x\n", indent, header->entries_crc32);
} }
void EntriesDetails(GptData *gpt, const int secondary) { void EntryDetails(GptEntry *entry, int index, int raw) {
char contents[256];
if (raw == NOT_INITED) {
uint8_t label[sizeof(entry->name) * 3 / 2];
char type[GUID_STRLEN], unique[GUID_STRLEN];;
UTF16ToUTF8(entry->name, label);
snprintf(contents, sizeof(contents), "Label: \"%s\"", label);
printf(PARTITION_FMT, (int)entry->starting_lba,
(int)(entry->ending_lba - entry->starting_lba + 1),
index+1, contents);
if (CGPT_OK == ResolveType(&entry->type, type)) {
printf(PARTITION_MORE, "Type: ", type);
} else {
GuidToStr(&entry->type, type);
printf(PARTITION_MORE, "Type: ", type);
}
GuidToStr(&entry->unique, unique);
printf(PARTITION_MORE, "UUID: ", unique);
if (!Memcmp(&guid_chromeos_kernel, &entry->type, sizeof(Guid))) {
int tries = (entry->attributes & CGPT_ATTRIBUTE_TRIES_MASK) >>
CGPT_ATTRIBUTE_TRIES_OFFSET;
int successful = (entry->attributes & CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >>
CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
int priority = (entry->attributes & CGPT_ATTRIBUTE_PRIORITY_MASK) >>
CGPT_ATTRIBUTE_PRIORITY_OFFSET;
snprintf(contents, sizeof(contents),
"priority=%d tries=%d successful=%d",
priority, tries, successful);
printf(PARTITION_MORE, "Attr: ", contents);
}
} else {
char label[BUFFER_SIZE(sizeof(entry->name))];
char type[GUID_STRLEN], unique[GUID_STRLEN];
RawDump((void*)entry->name, sizeof(entry->name), label, 2);
snprintf(contents, sizeof(contents), "Label: %s", label);
printf(PARTITION_FMT, (int)entry->starting_lba,
(int)(entry->ending_lba - entry->starting_lba + 1),
index+1, contents);
GuidToStr(&entry->type, type);
printf(PARTITION_MORE, "Type: ", type);
GuidToStr(&entry->unique, unique);
printf(PARTITION_MORE, "UUID: ", unique);
snprintf(contents, sizeof(contents), "[%016lx]", entry->attributes);
printf(PARTITION_MORE, "Attr: ", contents);
}
}
void EntriesDetails(GptData *gpt, const int secondary, int raw) {
int i; int i;
for (i = 0; i < GetNumberOfEntries(gpt); ++i) { for (i = 0; i < GetNumberOfEntries(gpt); ++i) {
static Guid unused = GPT_ENT_TYPE_UNUSED;
char contents[256];
GptEntry *entry; GptEntry *entry;
entry = GetEntry(gpt, secondary, i); entry = GetEntry(gpt, secondary, i);
if (!Memcmp(&unused, &entry->type, sizeof(unused))) continue; if (!Memcmp(&guid_unused, &entry->type, sizeof(Guid))) continue;
if (number == NOT_INITED) { EntryDetails(entry, i, raw);
uint8_t label[sizeof(entry->name) * 3 / 2];
char type[GUID_STRLEN], unique[GUID_STRLEN];;
UTF16ToUTF8(entry->name, label);
snprintf(contents, sizeof(contents), "Label: \"%s\"", label);
printf(PARTITION_FMT, (int)entry->starting_lba,
(int)(entry->ending_lba - entry->starting_lba + 1),
i, contents);
if (CGPT_OK == ResolveType(&entry->type, type)) {
printf(PARTITION_MORE, "Type: ", type);
} else {
GuidToStr(&entry->type, type);
printf(PARTITION_MORE, "Type: ", type);
}
GuidToStr(&entry->unique, unique);
printf(PARTITION_MORE, "UUID: ", unique);
} else {
char label[BUFFER_SIZE(sizeof(entry->name))];
char type[GUID_STRLEN], unique[GUID_STRLEN],
attributes[BUFFER_SIZE(sizeof(uint64_t))];
RawDump((void*)entry->name, sizeof(entry->name), label, 2);
snprintf(contents, sizeof(contents), "Label: %s", label);
printf(PARTITION_FMT, (int)entry->starting_lba,
(int)(entry->ending_lba - entry->starting_lba + 1),
i, contents);
GuidToStr(&entry->type, type);
printf(PARTITION_MORE, "Type: ", type);
GuidToStr(&entry->unique, unique);
printf(PARTITION_MORE, "UUID: ", unique);
RawDump((uint8_t*)&entry->attributes, 8, attributes, 4);
printf(PARTITION_MORE, "Attr: ", attributes);
}
} }
} }
@@ -216,7 +230,7 @@ int CgptShow(int argc, char *argv[]) {
if (CGPT_OK != OpenDriveInLastArgument(argc, argv, &drive)) if (CGPT_OK != OpenDriveInLastArgument(argc, argv, &drive))
return CGPT_FAILED; return CGPT_FAILED;
printf(TITLE_FMT, "start", "size", "index", "contents"); printf(TITLE_FMT, "start", "size", "part", "contents");
printf(GPT_FMT, 0, GPT_PMBR_SECTOR, "", "PMBR"); printf(GPT_FMT, 0, GPT_PMBR_SECTOR, "", "PMBR");
if (drive.gpt.valid_headers & MASK_PRIMARY) { if (drive.gpt.valid_headers & MASK_PRIMARY) {
@@ -228,7 +242,7 @@ int CgptShow(int argc, char *argv[]) {
snprintf(indent, sizeof(indent), GPT_MORE); snprintf(indent, sizeof(indent), GPT_MORE);
header = (GptHeader*)drive.gpt.primary_header; header = (GptHeader*)drive.gpt.primary_header;
HeaderDetails(header, indent); HeaderDetails(header, indent, number);
} }
} else { } else {
printf(GPT_FMT, (int)GPT_PMBR_SECTOR, printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
@@ -241,7 +255,7 @@ int CgptShow(int argc, char *argv[]) {
"Pri GPT table"); "Pri GPT table");
if (drive.gpt.valid_entries & MASK_PRIMARY) if (drive.gpt.valid_entries & MASK_PRIMARY)
EntriesDetails(&drive.gpt, PRIMARY); EntriesDetails(&drive.gpt, PRIMARY, number);
printf(GPT_FMT, (int)(drive.gpt.drive_sectors - GPT_HEADER_SECTOR - printf(GPT_FMT, (int)(drive.gpt.drive_sectors - GPT_HEADER_SECTOR -
GPT_ENTRIES_SECTORS), GPT_ENTRIES_SECTORS),
@@ -256,7 +270,7 @@ int CgptShow(int argc, char *argv[]) {
(!(drive.gpt.valid_entries & MASK_PRIMARY) || (!(drive.gpt.valid_entries & MASK_PRIMARY) ||
Memcmp(drive.gpt.primary_entries, drive.gpt.secondary_entries, Memcmp(drive.gpt.primary_entries, drive.gpt.secondary_entries,
TOTAL_ENTRIES_SIZE))) { TOTAL_ENTRIES_SIZE))) {
EntriesDetails(&drive.gpt, SECONDARY); EntriesDetails(&drive.gpt, SECONDARY, number);
} }
if (drive.gpt.valid_headers & MASK_SECONDARY) if (drive.gpt.valid_headers & MASK_SECONDARY)
@@ -279,7 +293,7 @@ int CgptShow(int argc, char *argv[]) {
snprintf(indent, sizeof(indent), GPT_MORE); snprintf(indent, sizeof(indent), GPT_MORE);
header = (GptHeader*)drive.gpt.secondary_header; header = (GptHeader*)drive.gpt.secondary_header;
HeaderDetails(header, indent); HeaderDetails(header, indent, number);
} }
} }

View File

@@ -9,6 +9,10 @@
#include "gpt.h" #include "gpt.h"
#include "utility.h" #include "utility.h"
/* global types to compare against */
const Guid guid_unused = GPT_ENT_TYPE_UNUSED;
const Guid guid_chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL;
int GptInit(GptData *gpt) { int GptInit(GptData *gpt) {
int retval; int retval;

View File

@@ -18,14 +18,15 @@
/* Bit definitions and masks for GPT attributes. /* Bit definitions and masks for GPT attributes.
* *
* 63 -- do not automounting * 63-61 -- (reserved)
* 62 -- hidden
* 60 -- read-only * 60 -- read-only
* : * 59-57 -- (reserved)
* 56 -- success * 56 -- success
* 55,52 -- tries * 55-52 -- tries
* 51,48 -- priority * 51-48 -- priority
* 0 -- system partition * 47-2 -- UEFI: reserved for future use
* 1 -- UEFI: partition is not mapped
* 0 -- UEFI: partition is required
*/ */
#define CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET 56 #define CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET 56
#define CGPT_ATTRIBUTE_MAX_SUCCESSFUL (1ULL) #define CGPT_ATTRIBUTE_MAX_SUCCESSFUL (1ULL)

View File

@@ -34,6 +34,8 @@
{{{0x3cb8e202,0x3b7e,0x47dd,0x8a,0x3c,{0x7f,0xf2,0xa1,0x3c,0xfc,0xec}}}} {{{0x3cb8e202,0x3b7e,0x47dd,0x8a,0x3c,{0x7f,0xf2,0xa1,0x3c,0xfc,0xec}}}}
#define GPT_ENT_TYPE_CHROMEOS_RESERVED \ #define GPT_ENT_TYPE_CHROMEOS_RESERVED \
{{{0x2e0a753d,0x9e48,0x43b0,0x83,0x37,{0xb1,0x51,0x92,0xcb,0x1b,0x5e}}}} {{{0x2e0a753d,0x9e48,0x43b0,0x83,0x37,{0xb1,0x51,0x92,0xcb,0x1b,0x5e}}}}
#define GPT_ENT_TYPE_LINUX_DATA \
{{{0xebd0a0a2,0xb9e5,0x4433,0x87,0xc0,{0x68,0xb6,0xb7,0x26,0x99,0xc7}}}}
#define UUID_NODE_LEN 6 #define UUID_NODE_LEN 6
@@ -56,6 +58,10 @@ typedef struct {
} u; } u;
} __attribute__((packed)) Guid; } __attribute__((packed)) Guid;
/* Some constant values */
extern const Guid guid_unused;
extern const Guid guid_chromeos_kernel;
/* GPT header defines how many partitions exist on a drive and sectors managed. /* GPT header defines how many partitions exist on a drive and sectors managed.
* For every drive device, there are 2 headers, primary and secondary. * For every drive device, there are 2 headers, primary and secondary.
* Most of fields are duplicated except my_lba and entries_lba. * Most of fields are duplicated except my_lba and entries_lba.