Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Side by Side Diff: utility/cgpt/cgpt_tofix.c

Issue 2719008: Nearly complete rewrite of cgpt tool. (Closed) Base URL: ssh://git@chromiumos-git//vboot_reference.git
Patch Set: Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « utility/cgpt/cgpt_tofix.h ('k') | vboot_firmware/lib/cgptlib/cgptlib_internal.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 * found in the LICENSE file.
4 *
5 * Functions to fix, after cgptlib cleanup.
6 */
7 #include <getopt.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include "cgpt.h"
11 #include "cgptlib_internal.h"
12 #include "cgpt_tofix.h"
13 #include "crc32.h"
14 #include "utility.h"
15
16 const char *GptError(int errno) {
17 const char *error_string[] = {
18 /* GPT_SUCCESS */ "Success",
19 /* GPT_ERROR_NO_VALID_KERNEL */ "No valid kernel entry",
20 /* GPT_ERROR_INVALID_HEADERS */ "Both primary and secondary headers are "
21 "invalid.",
22 /* GPT_ERROR_INVALID_ENTRIES */ "Both primary and secondary entries are "
23 "invalid.",
24 /* GPT_ERROR_INVALID_SECTOR_SIZE */ "Invalid sector size",
25 /* GPT_ERROR_INVALID_SECTOR_NUMBER */ "Invalid sector number",
26 /* GPT_ERROR_INVALID_UPDATE_TYPE */ "Invalid update type",
27 };
28 return error_string[errno];
29 }
30
31
32 /* Update CRC value if necessary. */
33 void UpdateCrc(GptData *gpt) {
34 GptHeader *primary_header, *secondary_header;
35
36 primary_header = (GptHeader*)gpt->primary_header;
37 secondary_header = (GptHeader*)gpt->secondary_header;
38
39 if (gpt->modified & GPT_MODIFIED_ENTRIES1) {
40 primary_header->entries_crc32 =
41 Crc32(gpt->primary_entries, TOTAL_ENTRIES_SIZE);
42 }
43 if (gpt->modified & GPT_MODIFIED_ENTRIES2) {
44 secondary_header->entries_crc32 =
45 Crc32(gpt->secondary_entries, TOTAL_ENTRIES_SIZE);
46 }
47 if (gpt->modified & GPT_MODIFIED_HEADER1) {
48 primary_header->header_crc32 = 0;
49 primary_header->header_crc32 = Crc32(
50 (const uint8_t *)primary_header, primary_header->size);
51 }
52 if (gpt->modified & GPT_MODIFIED_HEADER2) {
53 secondary_header->header_crc32 = 0;
54 secondary_header->header_crc32 = Crc32(
55 (const uint8_t *)secondary_header, secondary_header->size);
56 }
57 }
58
59 /* Helper function to get a pointer to the partition entry.
60 * 'secondary' is either PRIMARY or SECONDARY.
61 * 'entry_index' is the partition index: [0, number_of_entries).
62 */
63 GptEntry *GetEntry(GptData *gpt, int secondary, int entry_index) {
64 uint8_t *entries;
65
66 if (secondary == PRIMARY) {
67 entries = gpt->primary_entries;
68 } else {
69 entries = gpt->secondary_entries;
70 }
71
72 return (GptEntry*)(&entries[GetNumberOfEntries(gpt) * entry_index]);
73 }
74
75 /* The following functions are helpers to access attributes bit more easily.
76 * 'secondary' is either PRIMARY or SECONDARY.
77 * 'entry_index' is the partition index: [0, number_of_entries).
78 *
79 * Get*() return the exact value (shifted and masked).
80 */
81 void SetPriority(GptData *gpt, int secondary, int entry_index, int priority) {
82 GptEntry *entry;
83 entry = GetEntry(gpt, secondary, entry_index);
84
85 assert(priority >= 0 && priority <= CGPT_ATTRIBUTE_MAX_PRIORITY);
86 entry->attributes &= ~CGPT_ATTRIBUTE_PRIORITY_MASK;
87 entry->attributes |= (uint64_t)priority << CGPT_ATTRIBUTE_PRIORITY_OFFSET;
88 }
89
90 int GetPriority(GptData *gpt, int secondary, int entry_index) {
91 GptEntry *entry;
92 entry = GetEntry(gpt, secondary, entry_index);
93 return (entry->attributes & CGPT_ATTRIBUTE_PRIORITY_MASK) >>
94 CGPT_ATTRIBUTE_PRIORITY_OFFSET;
95 }
96
97 void SetBad(GptData *gpt, int secondary, int entry_index, int bad) {
98 GptEntry *entry;
99 entry = GetEntry(gpt, secondary, entry_index);
100
101 // There is no bad attribute
102 assert(0);
103 }
104
105 int GetBad(GptData *gpt, int secondary, int entry_index) {
106 GptEntry *entry;
107 entry = GetEntry(gpt, secondary, entry_index);
108
109 // There is no bad attribute
110 assert(0);
111 return 0;
112 }
113
114 void SetTries(GptData *gpt, int secondary, int entry_index, int tries) {
115 GptEntry *entry;
116 entry = GetEntry(gpt, secondary, entry_index);
117
118 assert(tries >= 0 && tries <= CGPT_ATTRIBUTE_MAX_TRIES);
119 entry->attributes &= ~CGPT_ATTRIBUTE_TRIES_MASK;
120 entry->attributes |= (uint64_t)tries << CGPT_ATTRIBUTE_TRIES_OFFSET;
121 }
122
123 int GetTries(GptData *gpt, int secondary, int entry_index) {
124 GptEntry *entry;
125 entry = GetEntry(gpt, secondary, entry_index);
126 return (entry->attributes & CGPT_ATTRIBUTE_TRIES_MASK) >>
127 CGPT_ATTRIBUTE_TRIES_OFFSET;
128 }
129
130 void SetSuccessful(GptData *gpt, int secondary, int entry_index, int success) {
131 GptEntry *entry;
132 entry = GetEntry(gpt, secondary, entry_index);
133
134 assert(success >= 0 && success <= CGPT_ATTRIBUTE_MAX_SUCCESSFUL);
135 entry->attributes &= ~CGPT_ATTRIBUTE_SUCCESSFUL_MASK;
136 entry->attributes |= (uint64_t)success << CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
137 }
138
139 int GetSuccessful(GptData *gpt, int secondary, int entry_index) {
140 GptEntry *entry;
141 entry = GetEntry(gpt, secondary, entry_index);
142 return (entry->attributes & CGPT_ATTRIBUTE_SUCCESSFUL_MASK) >>
143 CGPT_ATTRIBUTE_SUCCESSFUL_OFFSET;
144 }
145
146 uint32_t GetNumberOfEntries(const GptData *gpt) {
147 GptHeader *header = 0;
148 if (gpt->valid_headers & MASK_PRIMARY)
149 header = (GptHeader*)gpt->primary_header;
150 else if (gpt->valid_headers & MASK_SECONDARY)
151 header = (GptHeader*)gpt->secondary_header;
152 else
153 assert(0);
154 return header->number_of_entries;
155 }
156
157 /* Two headers are NOT bitwise identical. For example, my_lba pointers to header
158 * itself so that my_lba in primary and secondary is definitely different.
159 * Only the following fields should be identical.
160 *
161 * first_usable_lba
162 * last_usable_lba
163 * number_of_entries
164 * size_of_entry
165 * disk_uuid
166 *
167 * If any of above field are not matched, overwrite secondary with primary since
168 * we always trust primary.
169 * If any one of header is invalid, copy from another. */
170 int IsSynonymous(const GptHeader* a, const GptHeader* b) {
171 if ((a->first_usable_lba == b->first_usable_lba) &&
172 (a->last_usable_lba == b->last_usable_lba) &&
173 (a->number_of_entries == b->number_of_entries) &&
174 (a->size_of_entry == b->size_of_entry) &&
175 (!Memcmp(&a->disk_uuid, &b->disk_uuid, sizeof(Guid))))
176 return 1;
177 return 0;
178 }
179
180 /* Primary entries and secondary entries should be bitwise identical.
181 * If two entries tables are valid, compare them. If not the same,
182 * overwrites secondary with primary (primary always has higher priority),
183 * and marks secondary as modified.
184 * If only one is valid, overwrites invalid one.
185 * If all are invalid, does nothing.
186 * This function returns bit masks for GptData.modified field.
187 * Note that CRC is NOT re-computed in this function.
188 */
189 uint8_t RepairEntries(GptData *gpt, const uint32_t valid_entries) {
190 if (valid_entries == MASK_BOTH) {
191 if (Memcmp(gpt->primary_entries, gpt->secondary_entries,
192 TOTAL_ENTRIES_SIZE)) {
193 Memcpy(gpt->secondary_entries, gpt->primary_entries, TOTAL_ENTRIES_SIZE);
194 return GPT_MODIFIED_ENTRIES2;
195 }
196 } else if (valid_entries == MASK_PRIMARY) {
197 Memcpy(gpt->secondary_entries, gpt->primary_entries, TOTAL_ENTRIES_SIZE);
198 return GPT_MODIFIED_ENTRIES2;
199 } else if (valid_entries == MASK_SECONDARY) {
200 Memcpy(gpt->primary_entries, gpt->secondary_entries, TOTAL_ENTRIES_SIZE);
201 return GPT_MODIFIED_ENTRIES1;
202 }
203
204 return 0;
205 }
206
207 /* The above five fields are shared between primary and secondary headers.
208 * We can recover one header from another through copying those fields. */
209 void CopySynonymousParts(GptHeader* target, const GptHeader* source) {
210 target->first_usable_lba = source->first_usable_lba;
211 target->last_usable_lba = source->last_usable_lba;
212 target->number_of_entries = source->number_of_entries;
213 target->size_of_entry = source->size_of_entry;
214 Memcpy(&target->disk_uuid, &source->disk_uuid, sizeof(Guid));
215 }
216
217 /* This function repairs primary and secondary headers if possible.
218 * If both headers are valid (CRC32 is correct) but
219 * a) indicate inconsistent usable LBA ranges,
220 * b) inconsistent partition entry size and number,
221 * c) inconsistent disk_uuid,
222 * we will use the primary header to overwrite secondary header.
223 * If primary is invalid (CRC32 is wrong), then we repair it from secondary.
224 * If secondary is invalid (CRC32 is wrong), then we repair it from primary.
225 * This function returns the bitmasks for modified header.
226 * Note that CRC value is NOT re-computed in this function. UpdateCrc() will
227 * do it later.
228 */
229 uint8_t RepairHeader(GptData *gpt, const uint32_t valid_headers) {
230 GptHeader *primary_header, *secondary_header;
231
232 primary_header = (GptHeader*)gpt->primary_header;
233 secondary_header = (GptHeader*)gpt->secondary_header;
234
235 if (valid_headers == MASK_BOTH) {
236 if (!IsSynonymous(primary_header, secondary_header)) {
237 CopySynonymousParts(secondary_header, primary_header);
238 return GPT_MODIFIED_HEADER2;
239 }
240 } else if (valid_headers == MASK_PRIMARY) {
241 Memcpy(secondary_header, primary_header, primary_header->size);
242 secondary_header->my_lba = gpt->drive_sectors - 1; /* the last sector */
243 secondary_header->entries_lba = secondary_header->my_lba -
244 GPT_ENTRIES_SECTORS;
245 return GPT_MODIFIED_HEADER2;
246 } else if (valid_headers == MASK_SECONDARY) {
247 Memcpy(primary_header, secondary_header, secondary_header->size);
248 primary_header->my_lba = GPT_PMBR_SECTOR; /* the second sector on drive */
249 primary_header->entries_lba = primary_header->my_lba + GPT_HEADER_SECTOR;
250 return GPT_MODIFIED_HEADER1;
251 }
252
253 return 0;
254 }
255
256 /* TODO: HORRIBLY broken non-implemented functions. These will be
257 * fixed as part of a second stage of refactoring to use the new
258 * cgptlib_internal functions. */
259 uint32_t CheckOverlappedPartition(GptData *gpt) {
260 return 1;
261 }
262
263 uint32_t CheckValidEntries(GptData *gpt) {
264 return 1;
265 }
266
267 int NonZeroGuid(const Guid *guid) {
268 return 1;
269 }
OLDNEW
« no previous file with comments | « utility/cgpt/cgpt_tofix.h ('k') | vboot_firmware/lib/cgptlib/cgptlib_internal.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698