| OLD | NEW |
| 1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 * Use of this source code is governed by a BSD-style license that can be | 2 * Use of this source code is governed by a BSD-style license that can be |
| 3 * found in the LICENSE file. | 3 * found in the LICENSE file. |
| 4 * | 4 * |
| 5 * Update GPT attribute bits. | 5 * Update GPT attribute bits. |
| 6 */ | 6 */ |
| 7 #include <getopt.h> | 7 #include <getopt.h> |
| 8 #include <stdio.h> | 8 #include <stdio.h> |
| 9 #include <stdlib.h> | 9 #include <stdlib.h> |
| 10 #include "cgpt.h" | 10 #include "cgpt.h" |
| 11 #include "cgptlib_internal.h" | 11 #include "cgptlib_internal.h" |
| 12 #include "cgpt_tofix.h" | 12 #include "cgpt_tofix.h" |
| 13 #include "utility.h" | 13 #include "utility.h" |
| 14 | 14 |
| 15 static struct number_range | 15 static struct number_range range_1_0 = {1, 0}; |
| 16 range_1_0 = {1, 0}, | 16 static struct number_range range_15_0 = {15, 0}; |
| 17 range_15_0 = {15, 0}; | 17 static struct number_range range_16_1 = {16, 1}; |
| 18 | 18 |
| 19 /* Integers to store parsed argument. */ | 19 /* Integers to store parsed argument. */ |
| 20 static int help, partition, bad, successful, tries, priority; | 20 static int help, partition, successful, tries, priority; |
| 21 | 21 |
| 22 /* The structure for getopt_long(). When you add/delete any line, please refine | 22 /* The structure for getopt_long(). When you add/delete any line, please refine |
| 23 * attribute_comments[] and third parameter of getopt_long() too. */ | 23 * attribute_comments[] and third parameter of getopt_long() too. */ |
| 24 static struct option attribute_options[] = { | 24 static struct option attribute_options[] = { |
| 25 {.name = "help", .has_arg = no_argument, .flag = 0, .val = 'h'}, | 25 {.name = "help", .has_arg = no_argument, .flag = 0, .val = 'h'}, |
| 26 {.name = "partition", .has_arg = required_argument, .flag = 0, .val = 'i'}, | 26 {.name = "partition", .has_arg = required_argument, .flag = 0, .val = 'i'}, |
| 27 {.name = "bad", .has_arg = required_argument, .flag = 0, .val = 'b'}, | |
| 28 {.name = "successful", .has_arg = required_argument, .flag = 0, .val = 's'}, | 27 {.name = "successful", .has_arg = required_argument, .flag = 0, .val = 's'}, |
| 29 {.name = "tries", .has_arg = required_argument, .flag = 0, .val = 't'}, | 28 {.name = "tries", .has_arg = required_argument, .flag = 0, .val = 't'}, |
| 30 {.name = "priority", .has_arg = required_argument, .flag = 0, .val = 'p'}, | 29 {.name = "priority", .has_arg = required_argument, .flag = 0, .val = 'p'}, |
| 31 { /* last element, which should be zero. */ } | 30 { /* last element, which should be zero. */ } |
| 32 }; | 31 }; |
| 33 | 32 |
| 34 /* Extra information than struct option, please update this structure if you | 33 /* Extra information than struct option, please update this structure if you |
| 35 * add/remove any line in attribute_options[]. */ | 34 * add/remove any line in attribute_options[]. */ |
| 36 static struct option_details attribute_options_details[] = { | 35 static struct option_details attribute_options_details[] = { |
| 37 /* help */ | 36 /* help */ |
| 38 { .comment = "print this help", | 37 { .comment = "print this help", |
| 39 .validator = AssignTrue, | 38 .validator = AssignTrue, |
| 40 .valid_range = 0, | 39 .valid_range = 0, |
| 41 .parsed = &help}, | 40 .parsed = &help}, |
| 42 /* partition */ | 41 /* partition */ |
| 43 { .comment = "partition number " | 42 { .comment = "partition number " |
| 44 "(defualt: first ChromeOS kernel)", | 43 "(default: first ChromeOS kernel)", |
| 45 .validator = InNumberRange, | 44 .validator = InNumberRange, |
| 46 .valid_range = &range_15_0, | 45 .valid_range = &range_16_1, |
| 47 .parsed = &partition}, | 46 .parsed = &partition}, |
| 48 /* bad */ | |
| 49 { .comment = "mark partition bad", | |
| 50 .validator = InNumberRange, | |
| 51 .valid_range = &range_1_0, | |
| 52 .parsed = &bad}, | |
| 53 /* successful */ | 47 /* successful */ |
| 54 { .comment = "mark partition successful", | 48 { .comment = "mark partition successful", |
| 55 .validator = InNumberRange, | 49 .validator = InNumberRange, |
| 56 .valid_range = &range_1_0, | 50 .valid_range = &range_1_0, |
| 57 .parsed = &successful}, | 51 .parsed = &successful}, |
| 58 /* tries */ | 52 /* tries */ |
| 59 { .comment = "tries", | 53 { .comment = "tries", |
| 60 .validator = InNumberRange, | 54 .validator = InNumberRange, |
| 61 .valid_range = &range_15_0, | 55 .valid_range = &range_15_0, |
| 62 .parsed = &tries}, | 56 .parsed = &tries}, |
| 63 /* priority */ | 57 /* priority */ |
| 64 { .comment = "priority to boot", | 58 { .comment = "priority to boot", |
| 65 .validator = InNumberRange, | 59 .validator = InNumberRange, |
| 66 .valid_range = &range_15_0, | 60 .valid_range = &range_15_0, |
| 67 .parsed = &priority}, | 61 .parsed = &priority}, |
| 68 { /* last element, which should be zero. */ } | 62 { /* last element, which should be zero. */ } |
| 69 }; | 63 }; |
| 70 | 64 |
| 71 void AttributeHelp() { | 65 void AttributeHelp() { |
| 72 printf("\nUsage: %s attribute [OPTIONS] device_name\n\n", progname); | 66 printf("\nUsage: %s attribute [OPTIONS] device_name\n\n", progname); |
| 73 ShowOptions(attribute_options, attribute_options_details, | 67 ShowOptions(attribute_options, attribute_options_details, |
| 74 ARRAY_COUNT(attribute_options)); | 68 ARRAY_COUNT(attribute_options)); |
| 75 printf("\n* Attribute command only applies on ChromeOS kernel entry.\n\n"); | |
| 76 } | 69 } |
| 77 | 70 |
| 78 /* Parses all options (and validates them), then opens the drive and sets | 71 /* Parses all options (and validates them), then opens the drive and sets |
| 79 * corresponding bits in GPT entry. */ | 72 * corresponding bits in GPT entry. */ |
| 80 int CgptAttribute(int argc, char *argv[]) { | 73 int CgptAttribute(int argc, char *argv[]) { |
| 81 struct drive drive; | 74 struct drive drive; |
| 75 GptEntry *entry; |
| 82 | 76 |
| 83 /* I know this is NOT the perfect place to put code to make options[] and | 77 /* I know this is NOT the perfect place to put code to make options[] and |
| 84 * details[] are synced. But this is the best place we have right now since C | 78 * details[] are synced. But this is the best place we have right now since C |
| 85 * preprocessor doesn't know sizeof() for #if directive. */ | 79 * preprocessor doesn't know sizeof() for #if directive. */ |
| 86 assert(ARRAY_COUNT(attribute_options) == | 80 assert(ARRAY_COUNT(attribute_options) == |
| 87 ARRAY_COUNT(attribute_options_details)); | 81 ARRAY_COUNT(attribute_options_details)); |
| 88 | 82 |
| 89 help = partition = bad = successful = tries = priority = NOT_INITED; | 83 help = partition = successful = tries = priority = NOT_INITED; |
| 90 | 84 |
| 91 if (CGPT_OK != HandleOptions(argc, argv, | 85 if (CGPT_OK != HandleOptions(argc, argv, |
| 92 "hi:b:s:t:p:", | 86 "hi:b:s:t:p:", |
| 93 ARRAY_COUNT(attribute_options), | 87 ARRAY_COUNT(attribute_options), |
| 94 attribute_options, | 88 attribute_options, |
| 95 attribute_options_details)) | 89 attribute_options_details)) |
| 96 return CGPT_FAILED; | 90 return CGPT_FAILED; |
| 97 if (help != NOT_INITED) { | 91 if (help != NOT_INITED) { |
| 98 AttributeHelp(); | 92 AttributeHelp(); |
| 99 return CGPT_FAILED; | 93 return CGPT_FAILED; |
| 100 } | 94 } |
| 101 | 95 |
| 102 if (CGPT_OK != OpenDriveInLastArgument(argc, argv, &drive)) | 96 if (CGPT_OK != OpenDriveInLastArgument(argc, argv, &drive)) |
| 103 return CGPT_FAILED; | 97 return CGPT_FAILED; |
| 104 | 98 |
| 105 if (CheckValid(&drive) != CGPT_OK) return CGPT_FAILED; | 99 if (CheckValid(&drive) != CGPT_OK) return CGPT_FAILED; |
| 106 | 100 |
| 107 /* partition is not specified, search for the first Chromeos kernel. */ | 101 /* partition is not specified, search for the first Chromeos kernel. */ |
| 108 if (partition == NOT_INITED) { | 102 if (partition == NOT_INITED) { |
| 109 int i; | 103 int i; |
| 110 for (i = 0; i < GetNumberOfEntries(&drive.gpt); ++i) { | 104 for (i = 0; i < GetNumberOfEntries(&drive.gpt); ++i) { |
| 111 static Guid chromeos_kernel = GPT_ENT_TYPE_CHROMEOS_KERNEL; | |
| 112 GptEntry *entry; | |
| 113 entry = GetEntry(&drive.gpt, PRIMARY, i); | 105 entry = GetEntry(&drive.gpt, PRIMARY, i); |
| 114 if (!Memcmp(&chromeos_kernel, &entry->type, sizeof(Guid))) { | 106 if (!Memcmp(&guid_chromeos_kernel, &entry->type, sizeof(Guid))) { |
| 115 partition = i; | 107 partition = i+1; |
| 116 break; | 108 break; |
| 117 } | 109 } |
| 118 } | 110 } |
| 119 if (partition == NOT_INITED) { | 111 if (partition == NOT_INITED) { |
| 120 printf("[ERROR] No ChromeOS kernel is found. " | 112 printf("[ERROR] No ChromeOS kernel partition found. " |
| 121 "Please use --partition to specify.\n"); | 113 "Please use --partition to specify.\n"); |
| 122 return CGPT_FAILED; | 114 return CGPT_FAILED; |
| 123 } else { | 115 } else { |
| 124 debug("No --partition is specified. " | 116 debug("No --partition is specified. " |
| 125 "Found the first ChromeOS kernel at index [%d].\n", | 117 "Found the first ChromeOS kernel in partition [%d].\n", |
| 126 partition); | 118 partition); |
| 127 } | 119 } |
| 128 } | 120 } |
| 121 int index = partition - 1; |
| 129 | 122 |
| 130 if (successful != NOT_INITED) | 123 if (successful != NOT_INITED) |
| 131 SetSuccessful(&drive.gpt, PRIMARY, partition, successful); | 124 SetSuccessful(&drive.gpt, PRIMARY, index, successful); |
| 132 if (tries != NOT_INITED) | 125 if (tries != NOT_INITED) |
| 133 SetTries(&drive.gpt, PRIMARY, partition, tries); | 126 SetTries(&drive.gpt, PRIMARY, index, tries); |
| 134 if (priority != NOT_INITED) | 127 if (priority != NOT_INITED) |
| 135 SetPriority(&drive.gpt, PRIMARY, partition, priority); | 128 SetPriority(&drive.gpt, PRIMARY, index, priority); |
| 129 |
| 130 /* Display state */ |
| 131 entry = GetEntry(&drive.gpt, PRIMARY, index); |
| 132 EntryDetails(entry, index, NOT_INITED); |
| 136 | 133 |
| 137 /* Claims primary is good, then secondary will be overwritten. */ | 134 /* Claims primary is good, then secondary will be overwritten. */ |
| 138 /* TODO: rspangler broke this during cgptlib refactoring; need to | 135 /* TODO: rspangler broke this during cgptlib refactoring; need to |
| 139 * update this to match new internal APIs. */ | 136 * update this to match new internal APIs. */ |
| 140 RepairEntries(&drive.gpt, MASK_PRIMARY); | 137 RepairEntries(&drive.gpt, MASK_PRIMARY); |
| 141 RepairHeader(&drive.gpt, MASK_PRIMARY); | 138 RepairHeader(&drive.gpt, MASK_PRIMARY); |
| 142 | 139 |
| 143 /* Forces headers and entries are modified so that CRC32 will be re-calculated | 140 /* Forces headers and entries are modified so that CRC32 will be re-calculated |
| 144 * and headers and entries will be updated to drive. */ | 141 * and headers and entries will be updated to drive. */ |
| 145 drive.gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 | | 142 drive.gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 | |
| 146 GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2); | 143 GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2); |
| 147 UpdateCrc(&drive.gpt); | 144 UpdateCrc(&drive.gpt); |
| 148 DriveClose(&drive); | 145 DriveClose(&drive); |
| 149 | 146 |
| 150 return CGPT_OK; | 147 return CGPT_OK; |
| 151 } | 148 } |
| OLD | NEW |