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 |