blob: e01640af7876e069fb78de92e7a5276e29e7c784 [file] [log] [blame]
Julian Hall351a0722023-01-12 11:58:42 +00001/*
2 * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <cstdio>
8#include <cstdlib>
9#include <cstring>
10#include <string>
11#include <sstream>
12#include <sys/stat.h>
13#include <common/uuid/uuid.h>
14#include <service/fwu/app/fwu_app.h>
15#include "cmd_update_image.h"
16#include "cmd_print_image_dir.h"
17#include "cmd_print_metadata_v1.h"
18#include "cmd_print_metadata_v2.h"
19
20static bool option_selected(
21 const char *option_switch,
22 int argc, char *argv[]);
23
24static std::string parse_string_option(
25 const char *option_switch,
26 int argc, char *argv[],
27 const char *default_val);
28
29static int parse_numeric_option(
30 const char *option_switch,
31 int argc, char *argv[],
32 int default_val);
33
34static bool file_exists(
35 const std::string &filename);
36
37static void print_usage(void);
38static void print_help(void);
39
40
41int main(int argc, char *argv[])
42{
43 fwu_app app;
44 std::string disk_img_filename;
45 std::string update_img_filename;
46 std::string img_type_uuid;
47
48 /* Check for help */
49 if (option_selected("-h", argc, argv) ||
50 option_selected("-help", argc, argv) ||
51 option_selected("--help", argc, argv)) {
52
53 print_help();
54 return 0;
55 }
56
57 /* Handle mandatory disk image filename. Must be first argument */
58 if (argc > 1)
59 disk_img_filename = std::string(argv[1]);
60 else {
61
62 printf("Error: missing disk-filename argument\n");
63 print_usage();
64 return -1;
65 }
66
67 /* Check if disk image file exists */
68 if (!file_exists(disk_img_filename)) {
69
70 printf("Error: %s does not exist\n", disk_img_filename.c_str());
71 return -1;
72 }
73
74 /* Create fwu configuration based on the input disk image */
75 int status = app.configure(disk_img_filename.c_str());
76
77 if (status) {
78
79 printf("Error: failed to configure with status: %d\n", status);
80 return -1;
81 }
82
83 /* Attempt to derive boot info from metadata. Assume bootloader booted from the
84 * active index. This can be overridden via command-line parameter.
85 */
86 unsigned int boot_index;
87 unsigned int metadata_version;
88
89 status = app.get_boot_info(boot_index, metadata_version);
90
91 if (status) {
92
93 printf("No recognised metadata, assume default boot index and version\n");
94
95 boot_index = 0;
96 metadata_version = 2;
97 }
98
99 /* Allow for command-line overrides */
100 boot_index = parse_numeric_option("-boot-index", argc, argv, boot_index);
101 metadata_version = parse_numeric_option("-meta-ver", argc, argv, metadata_version);
102
103 /* Options for printing fwu info */
104 bool is_print_img_dir = option_selected("-dir", argc, argv);
105 bool is_print_metadata = option_selected("-meta", argc, argv);
106
107 /* Parse input image related parameters*/
108 update_img_filename = parse_string_option("-img", argc, argv, "");
109 img_type_uuid = parse_string_option("-img-type", argc, argv, "");
110
111 /* Check if image file exists (if one was specified) */
112 if (!update_img_filename.empty() && !file_exists(update_img_filename)) {
113
114 printf("Error: %s does not exist\n", update_img_filename.c_str());
115 return -1;
116 }
117
118 /* Check if img type canonical uuid is well formed */
119 if (!img_type_uuid.empty() && !uuid_is_valid(img_type_uuid.c_str())) {
120
121 printf("Error: image type uuid invalid\n");
122 return -1;
123 }
124
125 /* Initialise the update_agent. Missing or corrupt metadata will get repaired
126 */
127 status = app.init_update_agent(boot_index, metadata_version);
128
129 if (!status) {
130
131 printf("Update agent started: boot index: %d metadata ver: %d\n",
132 boot_index, metadata_version);
133
134 if (is_print_img_dir)
135 cmd_print_image_dir(app);
136
137 if (is_print_metadata) {
138
139 if (metadata_version == 1)
140 cmd_print_metadata_v1(app);
141 else if (metadata_version == 2)
142 cmd_print_metadata_v2(app);
143 else
144 printf("Unsupported metadata version\n");
145
146 }
147
148 if (!update_img_filename.empty() && !img_type_uuid.empty()) {
149
150 status = cmd_update_image(app, img_type_uuid, update_img_filename);
151
152 } else if (!update_img_filename.empty() || !img_type_uuid.empty()) {
153
154 printf("Error: both image filename and uuid arguments are needed\n");
155 return -1;
156 }
157 }
158
159 if (!status)
160 printf("OK\n");
161 else
162 printf("Error status: %d\n", status);
163
164 return status;
165}
166
167static bool option_selected(
168 const char *option_switch,
169 int argc, char *argv[])
170{
171 bool is_selected = false;
172
173 for (int i = 1; (i < argc) && !is_selected; ++i) {
174
175 is_selected = (strcmp(argv[i], option_switch) == 0);
176 }
177
178 return is_selected;
179}
180
181static std::string parse_string_option(
182 const char *option_switch,
183 int argc, char *argv[],
184 const char *default_val)
185{
186 std::string option = std::string(default_val);
187
188 for (int i = 1; i + 1 < argc; ++i) {
189
190 if (strcmp(argv[i], option_switch) == 0) {
191
192 option = std::string(argv[i + 1]);
193 break;
194 }
195 }
196
197 return option;
198}
199
200static int parse_numeric_option(
201 const char *option_switch,
202 int argc, char *argv[],
203 int default_val)
204{
205 int option = default_val;
206
207 for (int i = 1; i + 1 < argc; ++i) {
208
209 if (strcmp(argv[i], option_switch) == 0) {
210
211 std::istringstream iss(argv[i + 1]);
212 int val;
213
214 iss >> val;
215
216 if (!iss.fail())
217 option = val;
218
219 break;
220 }
221 }
222
223 return option;
224}
225
226static bool file_exists(const std::string &filename)
227{
228 struct stat stat_buf;
229
230 return stat(filename.c_str(), &stat_buf) == 0;
231}
232
233static void print_usage(void)
234{
235 printf("Usage: fwu disk-filename [-dir -meta] [-boot-index number -meta-ver number] "
236 "[-img filename -img-type uuid]\n");
237}
238
239static void print_help(void)
240{
241 print_usage();
242
243 printf("\n");
244 printf("\tdisk-filename\tDisk image file to update\n");
245 printf("\t-dir\t\tPrint image directory\n");
246 printf("\t-meta\t\tPrint FWU metadata\n");
247 printf("\t-boot-index\tOverride default boot index [0..n]\n");
248 printf("\t-meta-ver\tSpecify FWU metadata to use\n");
249 printf("\t-img\t\tFile containing image update\n");
250 printf("\t-img-type\tCanonical UUID of image to update\n");
251}
252