blob: 547d50e01aa947f7642bd4ede231971b69702dc0 [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{
Patrick Venture7ae5dde2018-12-14 10:03:35 -080045 std::fprintf(
46 stderr,
47 "Usage: %s --command <command> --interface <interface> --image "
48 "<image file> --sig <signature file>\n",
49 program);
Patrick Venturea6586362018-12-11 18:47:13 -080050
Patrick Venture7ae5dde2018-12-14 10:03:35 -080051 std::fprintf(stderr, "interfaces: ");
Patrick Ventureaa107a62018-12-12 15:16:25 -080052 std::copy(interfaceList.begin(), interfaceList.end(),
53 std::ostream_iterator<std::string>(std::cerr, ", "));
54 std::fprintf(stderr, "\n");
Patrick Venturebf58cd62018-12-11 09:05:46 -080055}
56
57bool checkCommand(const std::string& command)
58{
59 return (command == "update");
60}
61
62bool checkInterface(const std::string& interface)
63{
Patrick Venturea6586362018-12-11 18:47:13 -080064 auto intf =
65 std::find(interfaceList.begin(), interfaceList.end(), interface);
66 return (intf != interfaceList.end());
Patrick Venturebf58cd62018-12-11 09:05:46 -080067}
68
69int main(int argc, char* argv[])
70{
71 std::string command, interface, imagePath, signaturePath;
72
73 while (1)
74 {
75 // clang-format off
76 static struct option long_options[] = {
77 {"command", required_argument, 0, 'c'},
78 {"interface", required_argument, 0, 'i'},
79 {"image", required_argument, 0, 'm'},
80 {"sig", required_argument, 0, 's'},
81 {0, 0, 0, 0}
82 };
83 // clang-format on
84
85 int option_index = 0;
86 int c =
87 getopt_long(argc, argv, "c:i:m:s:", long_options, &option_index);
88 if (c == -1)
89 {
90 break;
91 }
92
93 switch (c)
94 {
95 case 'c':
96 command = std::string{optarg};
97 if (!checkCommand(command))
98 {
99 usage(argv[0]);
100 exit(EXIT_FAILURE);
101 }
102
103 break;
104 case 'i':
105 interface = std::string{optarg};
106 if (!checkInterface(interface))
107 {
108 usage(argv[0]);
109 exit(EXIT_FAILURE);
110 }
111 break;
112 case 'm':
113 imagePath = std::string{optarg};
114 break;
115 case 's':
116 signaturePath = std::string{optarg};
117 break;
118 default:
119 usage(argv[0]);
120 exit(EXIT_FAILURE);
121 }
122 }
123
Patrick Venture361bd5a2018-12-14 09:49:47 -0800124 if (command.empty())
125 {
126 usage(argv[0]);
127 exit(EXIT_FAILURE);
128 }
129
Patrick Venturebf58cd62018-12-11 09:05:46 -0800130 /* They want to update the firmware. */
131 if (command == "update")
132 {
133 if (interface.empty() || imagePath.empty() || signaturePath.empty())
134 {
135 usage(argv[0]);
136 exit(EXIT_FAILURE);
137 }
138
Patrick Venture9b534f02018-12-13 16:10:02 -0800139 host_tool::IpmiHandler ipmi;
140 host_tool::BlobHandler blob(&ipmi);
Patrick Venture00887592018-12-11 10:57:06 -0800141
Patrick Venture9b534f02018-12-13 16:10:02 -0800142 std::unique_ptr<host_tool::DataInterface> handler;
Patrick Venturea6586362018-12-11 18:47:13 -0800143
144 /* Input has already been validated in this case. */
145 if (interface == IPMIBT)
146 {
Patrick Venture9b534f02018-12-13 16:10:02 -0800147 handler = std::make_unique<host_tool::BtDataHandler>(&blob);
Patrick Venturea6586362018-12-11 18:47:13 -0800148 }
149 else if (interface == IPMILPC)
150 {
Patrick Venture9b534f02018-12-13 16:10:02 -0800151 handler = std::make_unique<host_tool::LpcDataHandler>(&blob);
Patrick Venturea6586362018-12-11 18:47:13 -0800152 }
153
154 if (!handler)
155 {
156 /* TODO(venture): use a custom exception. */
157 std::fprintf(stderr, "Interface %s is unavailable\n",
158 interface.c_str());
159 exit(EXIT_FAILURE);
160 }
161
Patrick Venturebf58cd62018-12-11 09:05:46 -0800162 /* The parameters are all filled out. */
Patrick Venture2bc23fe2018-12-13 10:16:36 -0800163 try
164 {
Patrick Venture9b534f02018-12-13 16:10:02 -0800165 host_tool::updaterMain(&blob, handler.get(), imagePath,
166 signaturePath);
Patrick Venture2bc23fe2018-12-13 10:16:36 -0800167 }
Patrick Venture9b534f02018-12-13 16:10:02 -0800168 catch (const host_tool::ToolException& e)
Patrick Venture2bc23fe2018-12-13 10:16:36 -0800169 {
170 std::fprintf(stderr, "Exception received: %s\n", e.what());
171 return -1;
172 }
Patrick Venturebf58cd62018-12-11 09:05:46 -0800173 }
174
175 return 0;
176}