1 // Copyright 2017 The Fuchsia 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 <dirent.h>
6 #include <fcntl.h>
7 #include <stdbool.h>
8 #include <stddef.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12 
13 #include <utility>
14 
15 #include "pave-lib.h"
16 #include "pave-logging.h"
17 
18 namespace {
19 
20 using paver::Arch;
21 using paver::Command;
22 using paver::Flags;
23 
PrintUsage()24 void PrintUsage() {
25     ERROR("install-disk-image <command> [options...]\n");
26     ERROR("Commands:\n");
27     ERROR("  install-bootloader : Install a BOOTLOADER partition to the device\n");
28     ERROR("  install-efi        : Install an EFI partition to the device\n");
29     ERROR("  install-kernc      : Install a KERN-C CrOS partition to the device\n");
30     ERROR("  install-zircona    : Install a ZIRCON-A partition to the device\n");
31     ERROR("  install-zirconb    : Install a ZIRCON-B partition to the device\n");
32     ERROR("  install-zirconr    : Install a ZIRCON-R partition to the device\n");
33     ERROR("  install-vbmetaa    : Install a VBMETA-A partition to the device\n");
34     ERROR("  install-vbmetab    : Install a VBMETA-B partition to the device\n");
35     ERROR("  install-fvm        : Install a sparse FVM to the device\n");
36     ERROR("  install-data-file  : Install a file to DATA (--path required)\n");
37     ERROR("  wipe               : Clean up the install disk\n");
38     ERROR("Options:\n");
39     ERROR("  --file <file>: Read from FILE instead of stdin\n");
40     ERROR("  --force: Install partition even if inappropriate for the device\n");
41     ERROR("  --path <path>: Install DATA file to path\n");
42 }
43 
ParseFlags(int argc,char ** argv,Flags * flags)44 bool ParseFlags(int argc, char** argv, Flags* flags) {
45 #define SHIFT_ARGS \
46     do {           \
47         argc--;    \
48         argv++;    \
49     } while (0)
50 
51     // Parse command.
52     if (argc < 2) {
53         ERROR("install-disk-image needs a command\n");
54         return false;
55     }
56     SHIFT_ARGS;
57 
58     if (!strcmp(argv[0], "install-bootloader")) {
59         flags->cmd = Command::kInstallBootloader;
60     } else if (!strcmp(argv[0], "install-efi")) {
61         flags->cmd = Command::kInstallEfi;
62     } else if (!strcmp(argv[0], "install-kernc")) {
63         flags->cmd = Command::kInstallKernc;
64     } else if (!strcmp(argv[0], "install-zircona")) {
65         flags->cmd = Command::kInstallZirconA;
66     } else if (!strcmp(argv[0], "install-zirconb")) {
67         flags->cmd = Command::kInstallZirconB;
68     } else if (!strcmp(argv[0], "install-zirconr")) {
69         flags->cmd = Command::kInstallZirconR;
70     } else if (!strcmp(argv[0], "install-vbmetaa")) {
71         flags->cmd = Command::kInstallVbMetaA;
72     } else if (!strcmp(argv[0], "install-vbmetab")) {
73         flags->cmd = Command::kInstallVbMetaB;
74     } else if (!strcmp(argv[0], "install-data-file")) {
75         flags->cmd = Command::kInstallDataFile;
76     } else if (!strcmp(argv[0], "install-fvm")) {
77         flags->cmd = Command::kInstallFvm;
78     } else if (!strcmp(argv[0], "wipe")) {
79         flags->cmd = Command::kWipe;
80     } else {
81         ERROR("Invalid command: %s\n", argv[0]);
82         return false;
83     }
84     SHIFT_ARGS;
85 
86     // Parse options.
87     flags->force = false;
88 #if defined(__x86_64__)
89     flags->arch = Arch::X64;
90 #elif defined(__aarch64__)
91     flags->arch = Arch::ARM64;
92 #endif
93     flags->payload_fd.reset(STDIN_FILENO);
94     while (argc > 0) {
95         if (!strcmp(argv[0], "--file")) {
96             SHIFT_ARGS;
97             if (argc < 1) {
98                 ERROR("'--file' argument requires a file\n");
99                 return false;
100             }
101             flags->payload_fd.reset(open(argv[0], O_RDONLY));
102             if (!flags->payload_fd) {
103                 ERROR("Couldn't open supplied file\n");
104                 return false;
105             }
106         } else if (!strcmp(argv[0], "--path")) {
107             SHIFT_ARGS;
108             if (argc < 1) {
109                 ERROR("'--path' argument requires a path\n");
110                 return false;
111             }
112             flags->path = argv[0];
113         } else if (!strcmp(argv[0], "--force")) {
114             flags->force = true;
115         } else {
116             return false;
117         }
118         SHIFT_ARGS;
119     }
120 
121     if (flags->cmd == Command::kInstallDataFile && flags->path == nullptr) {
122         ERROR("install-data-file requires --path\n");
123         return false;
124     }
125 
126     return true;
127 #undef SHIFT_ARGS
128 }
129 
130 } // namespace
131 
main(int argc,char ** argv)132 int main(int argc, char** argv) {
133     Flags flags;
134     if (!(ParseFlags(argc, argv, &flags))) {
135         PrintUsage();
136         return -1;
137     }
138     return paver::RealMain(std::move(flags)) == ZX_OK ? 0 : 1;
139 }
140