blob: b85f62bc77b138b4dcff6139643bc82c2298804d [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
122 /* They want to update the firmware. */
123 if (command == "update")
124 {
125 if (interface.empty() || imagePath.empty() || signaturePath.empty())
126 {
127 usage(argv[0]);
128 exit(EXIT_FAILURE);
129 }
130
Patrick Venturecf2d1b12018-12-11 18:22:36 -0800131 IpmiHandler ipmi;
132 BlobHandler blob(&ipmi);
Patrick Venture00887592018-12-11 10:57:06 -0800133
Patrick Venturea6586362018-12-11 18:47:13 -0800134 std::unique_ptr<DataInterface> handler;
135
136 /* Input has already been validated in this case. */
137 if (interface == IPMIBT)
138 {
139 handler = std::make_unique<BtDataHandler>(&blob);
140 }
141 else if (interface == IPMILPC)
142 {
143 handler = std::make_unique<LpcDataHandler>(&blob);
144 }
145
146 if (!handler)
147 {
148 /* TODO(venture): use a custom exception. */
149 std::fprintf(stderr, "Interface %s is unavailable\n",
150 interface.c_str());
151 exit(EXIT_FAILURE);
152 }
153
Patrick Venturebf58cd62018-12-11 09:05:46 -0800154 /* The parameters are all filled out. */
Patrick Venture2bc23fe2018-12-13 10:16:36 -0800155 try
156 {
157 updaterMain(&blob, handler.get(), imagePath, signaturePath);
158 }
159 catch (const ToolException& e)
160 {
161 std::fprintf(stderr, "Exception received: %s\n", e.what());
162 return -1;
163 }
Patrick Venturebf58cd62018-12-11 09:05:46 -0800164 }
165
166 return 0;
167}