summaryrefslogtreecommitdiff
path: root/cgpt/cmd_prioritize.c
diff options
context:
space:
mode:
Diffstat (limited to 'cgpt/cmd_prioritize.c')
-rw-r--r--cgpt/cmd_prioritize.c230
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(&params, 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(&params);
}