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