1// Copyright (c) 2012 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 <getopt.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <uuid/uuid.h>
10
11#include "cgpt.h"
12#include "vboot_host.h"
13
14extern const char* progname;
15
16static void Usage(void)
17{
18  printf("\nUsage: %s prioritize [OPTIONS] DRIVE\n\n"
19         "Reorder the priority of all active ChromeOS Kernel partitions.\n\n"
20         "Options:\n"
21         "  -D NUM       Size (in bytes) of the disk where partitions reside\n"
22         "                 default 0, meaning partitions and GPT structs are\n"
23         "                 both on DRIVE\n"
24         "  -P NUM       Highest priority to use in the new ordering. The\n"
25         "                 other partitions will be ranked in decreasing\n"
26         "                 priority while preserving their original order.\n"
27         "                 If necessary the lowest ranks will be coalesced.\n"
28         "                 No active kernels will be lowered to priority 0.\n"
29         "  -i NUM       Specify the partition to make the highest in the new\n"
30         "                 order.\n"
31         "  -f           Friends of the given partition (those with the same\n"
32         "                 starting priority) are also updated to the new\n"
33         "                 highest priority.\n"
34         "\n"
35         "With no options this will set the lowest active kernel to\n"
36         "priority 1 while maintaining the original order.\n"
37         "\n", progname);
38}
39
40int cmd_prioritize(int argc, char *argv[]) {
41  CgptPrioritizeParams params;
42  memset(&params, 0, sizeof(params));
43
44  int c;
45  int errorcnt = 0;
46  char *e = 0;
47
48  opterr = 0;                     // quiet, you
49  while ((c=getopt(argc, argv, ":hi:fP:D:")) != -1)
50  {
51    switch (c)
52    {
53    case 'D':
54      params.drive_size = strtoull(optarg, &e, 0);
55      if (!*optarg || (e && *e))
56      {
57        Error("invalid argument to -%c: \"%s\"\n", c, optarg);
58        errorcnt++;
59      }
60      break;
61    case 'i':
62      params.set_partition = (uint32_t)strtoul(optarg, &e, 0);
63      if (!*optarg || (e && *e))
64      {
65        Error("invalid argument to -%c: \"%s\"\n", c, optarg);
66        errorcnt++;
67      }
68      break;
69    case 'f':
70      params.set_friends = 1;
71      break;
72    case 'P':
73      params.max_priority = (int)strtol(optarg, &e, 0);
74      if (!*optarg || (e && *e))
75      {
76        Error("invalid argument to -%c: \"%s\"\n", c, optarg);
77        errorcnt++;
78      }
79      if (params.max_priority < 1 || params.max_priority > 15) {
80        Error("value for -%c must be between 1 and 15\n", c);
81        errorcnt++;
82      }
83      break;
84
85    case 'h':
86      Usage();
87      return CGPT_OK;
88    case '?':
89      Error("unrecognized option: -%c\n", optopt);
90      errorcnt++;
91      break;
92    case ':':
93      Error("missing argument to -%c\n", optopt);
94      errorcnt++;
95      break;
96    default:
97      errorcnt++;
98      break;
99    }
100  }
101  if (errorcnt)
102  {
103    Usage();
104    return CGPT_FAILED;
105  }
106
107  if (params.set_friends && !params.set_partition) {
108    Error("the -f option is only useful with the -i option\n");
109    Usage();
110    return CGPT_FAILED;
111  }
112
113  if (optind >= argc) {
114    Error("missing drive argument\n");
115    return CGPT_FAILED;
116  }
117
118  params.drive_name = argv[optind];
119
120  return CgptPrioritize(&params);
121}
122