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

Side by Side Diff: cgpt/cmd_prioritize.c

Issue 5352005: Add 'prioritize' command to cgpt tool. (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/vboot_reference.git@master
Patch Set: Created 10 years 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 | Annotate | Revision Log
« no previous file with comments | « cgpt/cmd_find.c ('k') | cgpt/cmd_show.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 #include "cgpt.h"
6
7 #include <getopt.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <uuid/uuid.h>
12
13 #include "cgptlib_internal.h"
14
15 static void Usage(void)
16 {
17 printf("\nUsage: %s prioritize [OPTIONS] DRIVE\n\n"
18 "Reorder the priority of all active ChromeOS Kernel partitions.\n\n"
19 "Options:\n"
20 " -P NUM Highest priority to use in the new ordering. The\n"
21 " other partitions will be ranked in decreasing\n"
22 " priority while preserving their original order.\n"
23 " If necessary the lowest ranks will be coalesced.\n"
24 " No active kernels will be lowered to priority 0.\n"
25 " -i NUM Specify the partition to make the highest in the new\n"
26 " order.\n"
27 " -f Friends of the given partition (those with the same\n"
28 " starting priority) are also updated to the new\n"
29 " highest priority.\n"
30 "\n"
31 "With no options this will set the lowest active kernel to\n"
32 "priority 1 while maintaining the original order.\n"
33 "\n", progname);
34 }
35
36 //////////////////////////////////////////////////////////////////////////////
37 // I want a sorted list of priority groups, where each element in the list
38 // contains an unordered list of GPT partition numbers. This is a stupid
39 // implementation, but our needs are simple and don't justify the time or space
40 // it would take to write a "better" one.
41 #define MAX_GROUPS 17 // 0-15, plus one "higher"
42
43 typedef struct {
44 int priority; // priority of this group
45 int num_parts; // number of partitions in this group
46 uint32_t *part; // array of partitions in this group
47 } group_t;
48
49 typedef struct {
50 int max_parts; // max number of partitions in any group
51 int num_groups; // number of non-empty groups
52 group_t group[MAX_GROUPS]; // array of groups
53 } group_list_t;
54
55
56 static group_list_t *NewGroupList(int max_p) {
57 int i;
58 group_list_t *gl = (group_list_t *)malloc(sizeof(group_list_t));
59 require(gl);
60 gl->max_parts = max_p;
61 gl->num_groups = 0;
62 // reserve space for the maximum number of partitions in every group
63 for (i=0; i<MAX_GROUPS; i++) {
64 gl->group[i].priority = -1;
65 gl->group[i].num_parts = 0;
66 gl->group[i].part = (uint32_t *)malloc(sizeof(uint32_t) * max_p);
67 require(gl->group[i].part);
68 }
69
70 return gl;
71 }
72
73 static void FreeGroups(group_list_t *gl) {
74 int i;
75 for (i=0; i<MAX_GROUPS; i++)
76 free(gl->group[i].part);
77 free(gl);
78 }
79
80 static void AddToGroup(group_list_t *gl, int priority, int partition) {
81 int i;
82 // See if I've already got a group with this priority
83 for (i=0; i<gl->num_groups; i++)
84 if (gl->group[i].priority == priority)
85 break;
86 if (i == gl->num_groups) {
87 // no, add a group
88 require(i < MAX_GROUPS);
89 gl->num_groups++;
90 gl->group[i].priority = priority;
91 }
92 // add the partition to it
93 int j = gl->group[i].num_parts;
94 gl->group[i].part[j] = partition;
95 gl->group[i].num_parts++;
96 }
97
98 static void ChangeGroup(group_list_t *gl, int old_priority, int new_priority) {
99 int i;
100 for (i=0; i<gl->num_groups; i++)
101 if (gl->group[i].priority == old_priority) {
102 gl->group[i].priority = new_priority;
103 break;
104 }
105 }
106
107 static void SortGroups(group_list_t *gl) {
108 int i, j;
109 group_t tmp;
110
111 // straight insertion sort is fast enough
112 for (i=1; i<gl->num_groups; i++) {
113 tmp = gl->group[i];
114 for (j=i; j && (gl->group[j-1].priority < tmp.priority); j--)
115 gl->group[j] = gl->group[j-1];
116 gl->group[j] = tmp;
117 }
118 }
119
120
121 //////////////////////////////////////////////////////////////////////////////
122
123 int cmd_prioritize(int argc, char *argv[]) {
124 struct drive drive;
125 uint32_t set_partition = 0;
126 int set_friends = 0;
127 int max_priority = 0;
128 int priority;
129 int orig_priority = 0;
130 int gpt_retval;
131 GptEntry *entry;
132 uint32_t index;
133 uint32_t max_part;
134 int num_kernels;
135 int i,j;
136 group_list_t *groups;
137
138 int c;
139 int errorcnt = 0;
140 char *e = 0;
141
142 opterr = 0; // quiet, you
143 while ((c=getopt(argc, argv, ":hi:fP:")) != -1)
144 {
145 switch (c)
146 {
147 case 'i':
148 set_partition = (uint32_t)strtoul(optarg, &e, 0);
149 if (!*optarg || (e && *e))
150 {
151 Error("invalid argument to -%c: \"%s\"\n", c, optarg);
152 errorcnt++;
153 }
154 break;
155 case 'f':
156 set_friends = 1;
157 break;
158 case 'P':
159 max_priority = (int)strtol(optarg, &e, 0);
160 if (!*optarg || (e && *e))
161 {
162 Error("invalid argument to -%c: \"%s\"\n", c, optarg);
163 errorcnt++;
164 }
165 if (max_priority < 1 || max_priority > 15) {
166 Error("value for -%c must be between 1 and 15\n", c);
167 errorcnt++;
168 }
169 break;
170
171 case 'h':
172 Usage();
173 return CGPT_OK;
174 case '?':
175 Error("unrecognized option: -%c\n", optopt);
176 errorcnt++;
177 break;
178 case ':':
179 Error("missing argument to -%c\n", optopt);
180 errorcnt++;
181 break;
182 default:
183 errorcnt++;
184 break;
185 }
186 }
187 if (errorcnt)
188 {
189 Usage();
190 return CGPT_FAILED;
191 }
192
193 if (set_friends && !set_partition) {
194 Error("the -f option is only useful with the -i option\n");
195 Usage();
196 return CGPT_FAILED;
197 }
198
199 if (optind >= argc) {
200 Error("missing drive argument\n");
201 return CGPT_FAILED;
202 }
203
204 if (CGPT_OK != DriveOpen(argv[optind], &drive))
205 return CGPT_FAILED;
206
207 if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
208 Error("GptSanityCheck() returned %d: %s\n",
209 gpt_retval, GptError(gpt_retval));
210 return CGPT_FAILED;
211 }
212
213 max_part = GetNumberOfEntries(&drive.gpt);
214
215 if (set_partition) {
216 if (set_partition < 1 || set_partition > max_part) {
217 Error("invalid partition number: %d (must be between 1 and %d\n",
218 set_partition, max_part);
219 goto bad;
220 }
221 index = set_partition - 1;
222 // it must be a kernel
223 entry = GetEntry(&drive.gpt, PRIMARY, index);
224 if (!GuidEqual(&entry->type, &guid_chromeos_kernel)) {
225 Error("partition %d is not a ChromeOS kernel\n", set_partition);
226 goto bad;
227 }
228 }
229
230 // How many kernel partitions do I have?
231 num_kernels = 0;
232 for (i = 0; i < max_part; i++) {
233 entry = GetEntry(&drive.gpt, PRIMARY, i);
234 if (GuidEqual(&entry->type, &guid_chromeos_kernel))
235 num_kernels++;
236 }
237
238 if (!num_kernels)
239 // nothing to do, so don't
240 goto good;
241
242 // Determine the current priority groups
243 groups = NewGroupList(num_kernels);
244 for (i = 0; i < max_part; i++) {
245 entry = GetEntry(&drive.gpt, PRIMARY, i);
246 if (!GuidEqual(&entry->type, &guid_chromeos_kernel))
247 continue;
248
249 priority = GetPriority(&drive.gpt, PRIMARY, i);
250
251 // Is this partition special?
252 if (set_partition && (i+1 == set_partition)) {
253 orig_priority = priority; // remember the original priority
254 if (set_friends)
255 AddToGroup(groups, priority, i); // we'll move them all later
256 else
257 AddToGroup(groups, 99, i); // move only this one
258 } else {
259 AddToGroup(groups, priority, i); // just remember
260 }
261 }
262
263 // If we're including friends, then change the original group priority
264 if (set_partition && set_friends) {
265 ChangeGroup(groups, orig_priority, 99);
266 }
267
268 // Sorting gives the new order. Now we just need to reassign the
269 // priorities.
270 SortGroups(groups);
271
272 // We'll never lower anything to zero, so if the last group is priority zero
273 // we can ignore it.
274 i = groups->num_groups;
275 if (groups->group[i-1].priority == 0)
276 groups->num_groups--;
277
278 // Where do we start?
279 if (max_priority)
280 priority = max_priority;
281 else
282 priority = groups->num_groups > 15 ? 15 : groups->num_groups;
283
284 // Figure out what the new values should be
285 for (i=0; i<groups->num_groups; i++) {
286 groups->group[i].priority = priority;
287 if (priority > 1)
288 priority--;
289 }
290
291 // Now apply the ranking to the GPT
292 for (i=0; i<groups->num_groups; i++)
293 for (j=0; j<groups->group[i].num_parts; j++)
294 SetPriority(&drive.gpt, PRIMARY,
295 groups->group[i].part[j], groups->group[i].priority);
296
297 FreeGroups(groups);
298
299
300 // Write it all out
301 good:
302 RepairEntries(&drive.gpt, MASK_PRIMARY);
303 RepairHeader(&drive.gpt, MASK_PRIMARY);
304
305 drive.gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 |
306 GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2);
307 UpdateCrc(&drive.gpt);
308
309 return DriveClose(&drive, 1);
310
311 bad:
312 (void) DriveClose(&drive, 0);
313 return CGPT_FAILED;
314 }
OLDNEW
« no previous file with comments | « cgpt/cmd_find.c ('k') | cgpt/cmd_show.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698