blob: 218eebe9a18df0229c80f19f2f09242ca0185134 [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 Venturebf58cd62018-12-11 09:05:46 -080021#include "updater.hpp"
22
23/* Use CLI11 argument parser once in openbmc/meta-oe or whatever. */
24#include <getopt.h>
25
Patrick Venturea6586362018-12-11 18:47:13 -080026#include <algorithm>
Patrick Venturebf58cd62018-12-11 09:05:46 -080027#include <cstdio>
Patrick Venture00887592018-12-11 10:57:06 -080028#include <memory>
Patrick Venturea6586362018-12-11 18:47:13 -080029#include <sstream>
Patrick Venturebf58cd62018-12-11 09:05:46 -080030#include <string>
Patrick Venturea6586362018-12-11 18:47:13 -080031#include <vector>
32
33#define IPMILPC "ipmilpc"
34#define IPMIBT "ipmibt"
35
36namespace
37{
38const std::vector<std::string> interfaceList = {IPMIBT, IPMILPC};
39}
Patrick Venturebf58cd62018-12-11 09:05:46 -080040
41void usage(const char* program)
42{
Patrick Venturea6586362018-12-11 18:47:13 -080043 std::ostringstream intfs;
44
45 /* can use std::accumulate(), also probably loads of better ways
46 */
47 for (const auto& intf : interfaceList)
48 {
49 intfs << intf << ", ";
50 }
51
Patrick Venturebf58cd62018-12-11 09:05:46 -080052 std::fprintf(stderr,
53 "Usage: %s -command <command> -interface <interface> -image "
Patrick Venturea6586362018-12-11 18:47:13 -080054 "<image file> -sig <signature file>\n",
Patrick Venturebf58cd62018-12-11 09:05:46 -080055 program);
Patrick Venturea6586362018-12-11 18:47:13 -080056
57 std::fprintf(stderr, "interfaces: %s", intfs.str().c_str());
Patrick Venturebf58cd62018-12-11 09:05:46 -080058}
59
60bool checkCommand(const std::string& command)
61{
62 return (command == "update");
63}
64
65bool checkInterface(const std::string& interface)
66{
Patrick Venturea6586362018-12-11 18:47:13 -080067 auto intf =
68 std::find(interfaceList.begin(), interfaceList.end(), interface);
69 return (intf != interfaceList.end());
Patrick Venturebf58cd62018-12-11 09:05:46 -080070}
71
72int main(int argc, char* argv[])
73{
74 std::string command, interface, imagePath, signaturePath;
75
76 while (1)
77 {
78 // clang-format off
79 static struct option long_options[] = {
80 {"command", required_argument, 0, 'c'},
81 {"interface", required_argument, 0, 'i'},
82 {"image", required_argument, 0, 'm'},
83 {"sig", required_argument, 0, 's'},
84 {0, 0, 0, 0}
85 };
86 // clang-format on
87
88 int option_index = 0;
89 int c =
90 getopt_long(argc, argv, "c:i:m:s:", long_options, &option_index);
91 if (c == -1)
92 {
93 break;
94 }
95
96 switch (c)
97 {
98 case 'c':
99 command = std::string{optarg};
100 if (!checkCommand(command))
101 {
102 usage(argv[0]);
103 exit(EXIT_FAILURE);
104 }
105
106 break;
107 case 'i':
108 interface = std::string{optarg};
109 if (!checkInterface(interface))
110 {
111 usage(argv[0]);
112 exit(EXIT_FAILURE);
113 }
114 break;
115 case 'm':
116 imagePath = std::string{optarg};
117 break;
118 case 's':
119 signaturePath = std::string{optarg};
120 break;
121 default:
122 usage(argv[0]);
123 exit(EXIT_FAILURE);
124 }
125 }
126
127 /* They want to update the firmware. */
128 if (command == "update")
129 {
130 if (interface.empty() || imagePath.empty() || signaturePath.empty())
131 {
132 usage(argv[0]);
133 exit(EXIT_FAILURE);
134 }
135
Patrick Venturecf2d1b12018-12-11 18:22:36 -0800136 IpmiHandler ipmi;
137 BlobHandler blob(&ipmi);
Patrick Venture00887592018-12-11 10:57:06 -0800138
Patrick Venturea6586362018-12-11 18:47:13 -0800139 std::unique_ptr<DataInterface> handler;
140
141 /* Input has already been validated in this case. */
142 if (interface == IPMIBT)
143 {
144 handler = std::make_unique<BtDataHandler>(&blob);
145 }
146 else if (interface == IPMILPC)
147 {
148 handler = std::make_unique<LpcDataHandler>(&blob);
149 }
150
151 if (!handler)
152 {
153 /* TODO(venture): use a custom exception. */
154 std::fprintf(stderr, "Interface %s is unavailable\n",
155 interface.c_str());
156 exit(EXIT_FAILURE);
157 }
158
Patrick Venturebf58cd62018-12-11 09:05:46 -0800159 /* The parameters are all filled out. */
Patrick Venturea6586362018-12-11 18:47:13 -0800160 return updaterMain(&blob, handler.get(), imagePath, signaturePath);
Patrick Venturebf58cd62018-12-11 09:05:46 -0800161 }
162
163 return 0;
164}