blob: eafa1622c542f0ea5afab104df7de6e00358d75f [file] [log] [blame]
Patrick Venturebf58cd62018-12-11 09:05:46 -08001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Patrick Venture00887592018-12-11 10:57:06 -080017#include "blob_handler.hpp"
Patrick Venturea6586362018-12-11 18:47:13 -080018#include "bt.hpp"
Patrick Venturecf2d1b12018-12-11 18:22:36 -080019#include "ipmi_handler.hpp"
Patrick Venturea6586362018-12-11 18:47:13 -080020#include "lpc.hpp"
Patrick Venture2bc23fe2018-12-13 10:16:36 -080021#include "tool_errors.hpp"
Patrick Venturebf58cd62018-12-11 09:05:46 -080022#include "updater.hpp"
23
24/* Use CLI11 argument parser once in openbmc/meta-oe or whatever. */
25#include <getopt.h>
26
Patrick Venturea6586362018-12-11 18:47:13 -080027#include <algorithm>
Patrick Venturebf58cd62018-12-11 09:05:46 -080028#include <cstdio>
Patrick Ventureaa107a62018-12-12 15:16:25 -080029#include <iostream>
30#include <iterator>
Patrick Venture00887592018-12-11 10:57:06 -080031#include <memory>
Patrick Venturebf58cd62018-12-11 09:05:46 -080032#include <string>
Patrick Venturea6586362018-12-11 18:47:13 -080033#include <vector>
34
35#define IPMILPC "ipmilpc"
36#define IPMIBT "ipmibt"
37
38namespace
39{
40const std::vector<std::string> interfaceList = {IPMIBT, IPMILPC};
41}
Patrick Venturebf58cd62018-12-11 09:05:46 -080042
43void usage(const char* program)
44{
45 std::fprintf(stderr,
46 "Usage: %s -command <command> -interface <interface> -image "
Patrick Venturea6586362018-12-11 18:47:13 -080047 "<image file> -sig <signature file>\n",
Patrick Venturebf58cd62018-12-11 09:05:46 -080048 program);
Patrick Venturea6586362018-12-11 18:47:13 -080049
Patrick Ventureaa107a62018-12-12 15:16:25 -080050 std::copy(interfaceList.begin(), interfaceList.end(),
51 std::ostream_iterator<std::string>(std::cerr, ", "));
52 std::fprintf(stderr, "\n");
Patrick Venturebf58cd62018-12-11 09:05:46 -080053}
54
55bool checkCommand(const std::string& command)
56{
57 return (command == "update");
58}
59
60bool checkInterface(const std::string& interface)
61{
Patrick Venturea6586362018-12-11 18:47:13 -080062 auto intf =
63 std::find(interfaceList.begin(), interfaceList.end(), interface);
64 return (intf != interfaceList.end());
Patrick Venturebf58cd62018-12-11 09:05:46 -080065}
66
67int main(int argc, char* argv[])
68{
69 std::string command, interface, imagePath, signaturePath;
70
71 while (1)
72 {
73 // clang-format off
74 static struct option long_options[] = {
75 {"command", required_argument, 0, 'c'},
76 {"interface", required_argument, 0, 'i'},
77 {"image", required_argument, 0, 'm'},
78 {"sig", required_argument, 0, 's'},
79 {0, 0, 0, 0}
80 };
81 // clang-format on
82
83 int option_index = 0;
84 int c =
85 getopt_long(argc, argv, "c:i:m:s:", long_options, &option_index);
86 if (c == -1)
87 {
88 break;
89 }
90
91 switch (c)
92 {
93 case 'c':
94 command = std::string{optarg};
95 if (!checkCommand(command))
96 {
97 usage(argv[0]);
98 exit(EXIT_FAILURE);
99 }
100
101 break;
102 case 'i':
103 interface = std::string{optarg};
104 if (!checkInterface(interface))
105 {
106 usage(argv[0]);
107 exit(EXIT_FAILURE);
108 }
109 break;
110 case 'm':
111 imagePath = std::string{optarg};
112 break;
113 case 's':
114 signaturePath = std::string{optarg};
115 break;
116 default:
117 usage(argv[0]);
118 exit(EXIT_FAILURE);
119 }
120 }
121
Patrick Venture361bd5a2018-12-14 09:49:47 -0800122 if (command.empty())
123 {
124 usage(argv[0]);
125 exit(EXIT_FAILURE);
126 }
127
Patrick Venturebf58cd62018-12-11 09:05:46 -0800128 /* They want to update the firmware. */
129 if (command == "update")
130 {
131 if (interface.empty() || imagePath.empty() || signaturePath.empty())
132 {
133 usage(argv[0]);
134 exit(EXIT_FAILURE);
135 }
136
Patrick Venturecf2d1b12018-12-11 18:22:36 -0800137 IpmiHandler ipmi;
138 BlobHandler blob(&ipmi);
Patrick Venture00887592018-12-11 10:57:06 -0800139
Patrick Venturea6586362018-12-11 18:47:13 -0800140 std::unique_ptr<DataInterface> handler;
141
142 /* Input has already been validated in this case. */
143 if (interface == IPMIBT)
144 {
145 handler = std::make_unique<BtDataHandler>(&blob);
146 }
147 else if (interface == IPMILPC)
148 {
149 handler = std::make_unique<LpcDataHandler>(&blob);
150 }
151
152 if (!handler)
153 {
154 /* TODO(venture): use a custom exception. */
155 std::fprintf(stderr, "Interface %s is unavailable\n",
156 interface.c_str());
157 exit(EXIT_FAILURE);
158 }
159
Patrick Venturebf58cd62018-12-11 09:05:46 -0800160 /* The parameters are all filled out. */
Patrick Venture2bc23fe2018-12-13 10:16:36 -0800161 try
162 {
163 updaterMain(&blob, handler.get(), imagePath, signaturePath);
164 }
165 catch (const ToolException& e)
166 {
167 std::fprintf(stderr, "Exception received: %s\n", e.what());
168 return -1;
169 }
Patrick Venturebf58cd62018-12-11 09:05:46 -0800170 }
171
172 return 0;
173}