diff options
Diffstat (limited to 'cgpt/cmd_prioritize.c')
-rw-r--r-- | cgpt/cmd_prioritize.c | 230 |
1 files changed, 13 insertions, 217 deletions
diff --git a/cgpt/cmd_prioritize.c b/cgpt/cmd_prioritize.c index 3f345689..cb655f28 100644 --- a/cgpt/cmd_prioritize.c +++ b/cgpt/cmd_prioritize.c @@ -1,16 +1,14 @@ -// Copyright (c) 2010 The Chromium OS Authors. All rights reserved. +// Copyright (c) 2012 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cgpt.h" - #include <getopt.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <uuid/uuid.h> -#include "cgptlib_internal.h" +#include "cgpt_params.h" static void Usage(void) { @@ -33,107 +31,12 @@ static void Usage(void) "\n", progname); } -////////////////////////////////////////////////////////////////////////////// -// I want a sorted list of priority groups, where each element in the list -// contains an unordered list of GPT partition numbers. This is a stupid -// implementation, but our needs are simple and don't justify the time or space -// it would take to write a "better" one. -#define MAX_GROUPS 17 // 0-15, plus one "higher" - -typedef struct { - int priority; // priority of this group - int num_parts; // number of partitions in this group - uint32_t *part; // array of partitions in this group -} group_t; - -typedef struct { - int max_parts; // max number of partitions in any group - int num_groups; // number of non-empty groups - group_t group[MAX_GROUPS]; // array of groups -} group_list_t; - - -static group_list_t *NewGroupList(int max_p) { - int i; - group_list_t *gl = (group_list_t *)malloc(sizeof(group_list_t)); - require(gl); - gl->max_parts = max_p; - gl->num_groups = 0; - // reserve space for the maximum number of partitions in every group - for (i=0; i<MAX_GROUPS; i++) { - gl->group[i].priority = -1; - gl->group[i].num_parts = 0; - gl->group[i].part = (uint32_t *)malloc(sizeof(uint32_t) * max_p); - require(gl->group[i].part); - } - - return gl; -} - -static void FreeGroups(group_list_t *gl) { - int i; - for (i=0; i<MAX_GROUPS; i++) - free(gl->group[i].part); - free(gl); -} - -static void AddToGroup(group_list_t *gl, int priority, int partition) { - int i; - // See if I've already got a group with this priority - for (i=0; i<gl->num_groups; i++) - if (gl->group[i].priority == priority) - break; - if (i == gl->num_groups) { - // no, add a group - require(i < MAX_GROUPS); - gl->num_groups++; - gl->group[i].priority = priority; - } - // add the partition to it - int j = gl->group[i].num_parts; - gl->group[i].part[j] = partition; - gl->group[i].num_parts++; -} - -static void ChangeGroup(group_list_t *gl, int old_priority, int new_priority) { - int i; - for (i=0; i<gl->num_groups; i++) - if (gl->group[i].priority == old_priority) { - gl->group[i].priority = new_priority; - break; - } -} - -static void SortGroups(group_list_t *gl) { - int i, j; - group_t tmp; - - // straight insertion sort is fast enough - for (i=1; i<gl->num_groups; i++) { - tmp = gl->group[i]; - for (j=i; j && (gl->group[j-1].priority < tmp.priority); j--) - gl->group[j] = gl->group[j-1]; - gl->group[j] = tmp; - } -} - - -////////////////////////////////////////////////////////////////////////////// - int cmd_prioritize(int argc, char *argv[]) { struct drive drive; - uint32_t set_partition = 0; - int set_friends = 0; - int max_priority = 0; - int priority; - int orig_priority = 0; - int gpt_retval; - GptEntry *entry; - uint32_t index; - uint32_t max_part; - int num_kernels; - int i,j; - group_list_t *groups; + + CgptPrioritizeParams params; + memset(¶ms, 0, sizeof(params)); + int c; int errorcnt = 0; @@ -145,7 +48,7 @@ int cmd_prioritize(int argc, char *argv[]) { switch (c) { case 'i': - set_partition = (uint32_t)strtoul(optarg, &e, 0); + params.set_partition = (uint32_t)strtoul(optarg, &e, 0); if (!*optarg || (e && *e)) { Error("invalid argument to -%c: \"%s\"\n", c, optarg); @@ -153,16 +56,16 @@ int cmd_prioritize(int argc, char *argv[]) { } break; case 'f': - set_friends = 1; + params.set_friends = 1; break; case 'P': - max_priority = (int)strtol(optarg, &e, 0); + params.max_priority = (int)strtol(optarg, &e, 0); if (!*optarg || (e && *e)) { Error("invalid argument to -%c: \"%s\"\n", c, optarg); errorcnt++; } - if (max_priority < 1 || max_priority > 15) { + if (params.max_priority < 1 || params.max_priority > 15) { Error("value for -%c must be between 1 and 15\n", c); errorcnt++; } @@ -190,7 +93,7 @@ int cmd_prioritize(int argc, char *argv[]) { return CGPT_FAILED; } - if (set_friends && !set_partition) { + if (params.set_friends && !params.set_partition) { Error("the -f option is only useful with the -i option\n"); Usage(); return CGPT_FAILED; @@ -201,114 +104,7 @@ int cmd_prioritize(int argc, char *argv[]) { return CGPT_FAILED; } - if (CGPT_OK != DriveOpen(argv[optind], &drive)) - return CGPT_FAILED; - - if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) { - Error("GptSanityCheck() returned %d: %s\n", - gpt_retval, GptError(gpt_retval)); - return CGPT_FAILED; - } - - max_part = GetNumberOfEntries(&drive.gpt); - - if (set_partition) { - if (set_partition < 1 || set_partition > max_part) { - Error("invalid partition number: %d (must be between 1 and %d\n", - set_partition, max_part); - goto bad; - } - index = set_partition - 1; - // it must be a kernel - entry = GetEntry(&drive.gpt, PRIMARY, index); - if (!GuidEqual(&entry->type, &guid_chromeos_kernel)) { - Error("partition %d is not a ChromeOS kernel\n", set_partition); - goto bad; - } - } - - // How many kernel partitions do I have? - num_kernels = 0; - for (i = 0; i < max_part; i++) { - entry = GetEntry(&drive.gpt, PRIMARY, i); - if (GuidEqual(&entry->type, &guid_chromeos_kernel)) - num_kernels++; - } - - if (!num_kernels) - // nothing to do, so don't - goto good; - - // Determine the current priority groups - groups = NewGroupList(num_kernels); - for (i = 0; i < max_part; i++) { - entry = GetEntry(&drive.gpt, PRIMARY, i); - if (!GuidEqual(&entry->type, &guid_chromeos_kernel)) - continue; - - priority = GetPriority(&drive.gpt, PRIMARY, i); - - // Is this partition special? - if (set_partition && (i+1 == set_partition)) { - orig_priority = priority; // remember the original priority - if (set_friends) - AddToGroup(groups, priority, i); // we'll move them all later - else - AddToGroup(groups, 99, i); // move only this one - } else { - AddToGroup(groups, priority, i); // just remember - } - } - - // If we're including friends, then change the original group priority - if (set_partition && set_friends) { - ChangeGroup(groups, orig_priority, 99); - } - - // Sorting gives the new order. Now we just need to reassign the - // priorities. - SortGroups(groups); - - // We'll never lower anything to zero, so if the last group is priority zero - // we can ignore it. - i = groups->num_groups; - if (groups->group[i-1].priority == 0) - groups->num_groups--; - - // Where do we start? - if (max_priority) - priority = max_priority; - else - priority = groups->num_groups > 15 ? 15 : groups->num_groups; - - // Figure out what the new values should be - for (i=0; i<groups->num_groups; i++) { - groups->group[i].priority = priority; - if (priority > 1) - priority--; - } - - // Now apply the ranking to the GPT - for (i=0; i<groups->num_groups; i++) - for (j=0; j<groups->group[i].num_parts; j++) - SetPriority(&drive.gpt, PRIMARY, - groups->group[i].part[j], groups->group[i].priority); - - FreeGroups(groups); - - - // Write it all out -good: - RepairEntries(&drive.gpt, MASK_PRIMARY); - RepairHeader(&drive.gpt, MASK_PRIMARY); - - drive.gpt.modified |= (GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1 | - GPT_MODIFIED_HEADER2 | GPT_MODIFIED_ENTRIES2); - UpdateCrc(&drive.gpt); - - return DriveClose(&drive, 1); + params.driveName = argv[optind]; -bad: - (void) DriveClose(&drive, 0); - return CGPT_FAILED; + return cgpt_prioritize(¶ms); } |