blob: 536cde145859e242ffb172bf7cbc43db9c58194b [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 Venturea6586362018-12-11 18:47:13 -080017#include "bt.hpp"
Patrick Venture46bdadc2019-01-18 09:04:16 -080018#include "io.hpp"
Patrick Venturea6586362018-12-11 18:47:13 -080019#include "lpc.hpp"
Patrick Ventureb5bf0fc2019-05-03 14:33:49 -070020#include "p2a.hpp"
21#include "pci.hpp"
Patrick Venture2bc23fe2018-12-13 10:16:36 -080022#include "tool_errors.hpp"
Patrick Venturebf58cd62018-12-11 09:05:46 -080023#include "updater.hpp"
24
25/* Use CLI11 argument parser once in openbmc/meta-oe or whatever. */
26#include <getopt.h>
27
Patrick Venturea6586362018-12-11 18:47:13 -080028#include <algorithm>
Patrick Venturebf58cd62018-12-11 09:05:46 -080029#include <cstdio>
Patrick Venturee564d5b2019-05-14 12:30:06 -070030#include <exception>
Patrick Ventureaa107a62018-12-12 15:16:25 -080031#include <iostream>
Patrick Venture664c5bc2019-03-07 08:09:45 -080032#include <ipmiblob/blob_handler.hpp>
33#include <ipmiblob/ipmi_handler.hpp>
Patrick Ventureaa107a62018-12-12 15:16:25 -080034#include <iterator>
Patrick Venture00887592018-12-11 10:57:06 -080035#include <memory>
Patrick Venturebf58cd62018-12-11 09:05:46 -080036#include <string>
Patrick Venturea6586362018-12-11 18:47:13 -080037#include <vector>
38
39#define IPMILPC "ipmilpc"
Patrick Ventureb5bf0fc2019-05-03 14:33:49 -070040#define IPMIPCI "ipmipci"
Patrick Venturea6586362018-12-11 18:47:13 -080041#define IPMIBT "ipmibt"
42
43namespace
44{
Patrick Ventureb5bf0fc2019-05-03 14:33:49 -070045const std::vector<std::string> interfaceList = {IPMIBT, IPMILPC, IPMIPCI};
Patrick Venturea6586362018-12-11 18:47:13 -080046}
Patrick Venturebf58cd62018-12-11 09:05:46 -080047
48void usage(const char* program)
49{
Patrick Venture7ae5dde2018-12-14 10:03:35 -080050 std::fprintf(
51 stderr,
52 "Usage: %s --command <command> --interface <interface> --image "
53 "<image file> --sig <signature file>\n",
54 program);
Patrick Venturea6586362018-12-11 18:47:13 -080055
Patrick Venture7ae5dde2018-12-14 10:03:35 -080056 std::fprintf(stderr, "interfaces: ");
Patrick Ventureaa107a62018-12-12 15:16:25 -080057 std::copy(interfaceList.begin(), interfaceList.end(),
58 std::ostream_iterator<std::string>(std::cerr, ", "));
59 std::fprintf(stderr, "\n");
Patrick Venturebf58cd62018-12-11 09:05:46 -080060}
61
62bool checkCommand(const std::string& command)
63{
64 return (command == "update");
65}
66
67bool checkInterface(const std::string& interface)
68{
Patrick Venturea6586362018-12-11 18:47:13 -080069 auto intf =
70 std::find(interfaceList.begin(), interfaceList.end(), interface);
71 return (intf != interfaceList.end());
Patrick Venturebf58cd62018-12-11 09:05:46 -080072}
73
74int main(int argc, char* argv[])
75{
76 std::string command, interface, imagePath, signaturePath;
77
78 while (1)
79 {
80 // clang-format off
81 static struct option long_options[] = {
82 {"command", required_argument, 0, 'c'},
83 {"interface", required_argument, 0, 'i'},
84 {"image", required_argument, 0, 'm'},
85 {"sig", required_argument, 0, 's'},
86 {0, 0, 0, 0}
87 };
88 // clang-format on
89
90 int option_index = 0;
91 int c =
92 getopt_long(argc, argv, "c:i:m:s:", long_options, &option_index);
93 if (c == -1)
94 {
95 break;
96 }
97
98 switch (c)
99 {
100 case 'c':
101 command = std::string{optarg};
102 if (!checkCommand(command))
103 {
104 usage(argv[0]);
105 exit(EXIT_FAILURE);
106 }
107
108 break;
109 case 'i':
110 interface = std::string{optarg};
111 if (!checkInterface(interface))
112 {
113 usage(argv[0]);
114 exit(EXIT_FAILURE);
115 }
116 break;
117 case 'm':
118 imagePath = std::string{optarg};
119 break;
120 case 's':
121 signaturePath = std::string{optarg};
122 break;
123 default:
124 usage(argv[0]);
125 exit(EXIT_FAILURE);
126 }
127 }
128
Patrick Venture361bd5a2018-12-14 09:49:47 -0800129 if (command.empty())
130 {
131 usage(argv[0]);
132 exit(EXIT_FAILURE);
133 }
134
Patrick Venturebf58cd62018-12-11 09:05:46 -0800135 /* They want to update the firmware. */
136 if (command == "update")
137 {
138 if (interface.empty() || imagePath.empty() || signaturePath.empty())
139 {
140 usage(argv[0]);
141 exit(EXIT_FAILURE);
142 }
143
Patrick Venture866d4482019-05-13 09:26:52 -0700144 auto ipmi = ipmiblob::IpmiHandler::CreateIpmiHandler();
145 ipmiblob::BlobHandler blob(std::move(ipmi));
Patrick Venture46bdadc2019-01-18 09:04:16 -0800146 host_tool::DevMemDevice devmem;
Patrick Ventureb5bf0fc2019-05-03 14:33:49 -0700147 host_tool::PciUtilImpl pci;
Patrick Venture00887592018-12-11 10:57:06 -0800148
Patrick Venture9b534f02018-12-13 16:10:02 -0800149 std::unique_ptr<host_tool::DataInterface> handler;
Patrick Venturea6586362018-12-11 18:47:13 -0800150
151 /* Input has already been validated in this case. */
152 if (interface == IPMIBT)
153 {
Patrick Venture9b534f02018-12-13 16:10:02 -0800154 handler = std::make_unique<host_tool::BtDataHandler>(&blob);
Patrick Venturea6586362018-12-11 18:47:13 -0800155 }
156 else if (interface == IPMILPC)
157 {
Patrick Venture46bdadc2019-01-18 09:04:16 -0800158 handler =
159 std::make_unique<host_tool::LpcDataHandler>(&blob, &devmem);
Patrick Venturea6586362018-12-11 18:47:13 -0800160 }
Patrick Ventureb5bf0fc2019-05-03 14:33:49 -0700161 else if (interface == IPMIPCI)
162 {
163 handler = std::make_unique<host_tool::P2aDataHandler>(
164 &blob, &devmem, &pci);
165 }
Patrick Venturea6586362018-12-11 18:47:13 -0800166
167 if (!handler)
168 {
169 /* TODO(venture): use a custom exception. */
170 std::fprintf(stderr, "Interface %s is unavailable\n",
171 interface.c_str());
172 exit(EXIT_FAILURE);
173 }
174
Patrick Venturebf58cd62018-12-11 09:05:46 -0800175 /* The parameters are all filled out. */
Patrick Venture2bc23fe2018-12-13 10:16:36 -0800176 try
177 {
Patrick Venture55646de2019-05-16 10:06:26 -0700178 host_tool::UpdateHandler updater(&blob, handler.get());
179 host_tool::updaterMain(&updater, imagePath, signaturePath);
Patrick Venture2bc23fe2018-12-13 10:16:36 -0800180 }
Patrick Venture9b534f02018-12-13 16:10:02 -0800181 catch (const host_tool::ToolException& e)
Patrick Venture2bc23fe2018-12-13 10:16:36 -0800182 {
183 std::fprintf(stderr, "Exception received: %s\n", e.what());
184 return -1;
185 }
Patrick Venturee564d5b2019-05-14 12:30:06 -0700186 catch (const std::exception& e)
187 {
188 std::fprintf(stderr, "Unexpected exception received: %s\n",
189 e.what());
190 return -1;
191 }
Patrick Venturebf58cd62018-12-11 09:05:46 -0800192 }
193
194 return 0;
195}