blob: be30230fff6943eb186ed69eec2cc9c180a9bc25 [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 Ventureaa107a62018-12-12 15:16:25 -080028#include <iostream>
29#include <iterator>
Patrick Venture00887592018-12-11 10:57:06 -080030#include <memory>
Patrick Venturebf58cd62018-12-11 09:05:46 -080031#include <string>
Patrick Venturea6586362018-12-11 18:47:13 -080032#include <vector>
33
34#define IPMILPC "ipmilpc"
35#define IPMIBT "ipmibt"
36
37namespace
38{
39const std::vector<std::string> interfaceList = {IPMIBT, IPMILPC};
40}
Patrick Venturebf58cd62018-12-11 09:05:46 -080041
42void usage(const char* program)
43{
44 std::fprintf(stderr,
45 "Usage: %s -command <command> -interface <interface> -image "
Patrick Venturea6586362018-12-11 18:47:13 -080046 "<image file> -sig <signature file>\n",
Patrick Venturebf58cd62018-12-11 09:05:46 -080047 program);
Patrick Venturea6586362018-12-11 18:47:13 -080048
Patrick Ventureaa107a62018-12-12 15:16:25 -080049 std::copy(interfaceList.begin(), interfaceList.end(),
50 std::ostream_iterator<std::string>(std::cerr, ", "));
51 std::fprintf(stderr, "\n");
Patrick Venturebf58cd62018-12-11 09:05:46 -080052}
53
54bool checkCommand(const std::string& command)
55{
56 return (command == "update");
57}
58
59bool checkInterface(const std::string& interface)
60{
Patrick Venturea6586362018-12-11 18:47:13 -080061 auto intf =
62 std::find(interfaceList.begin(), interfaceList.end(), interface);
63 return (intf != interfaceList.end());
Patrick Venturebf58cd62018-12-11 09:05:46 -080064}
65
66int main(int argc, char* argv[])
67{
68 std::string command, interface, imagePath, signaturePath;
69
70 while (1)
71 {
72 // clang-format off
73 static struct option long_options[] = {
74 {"command", required_argument, 0, 'c'},
75 {"interface", required_argument, 0, 'i'},
76 {"image", required_argument, 0, 'm'},
77 {"sig", required_argument, 0, 's'},
78 {0, 0, 0, 0}
79 };
80 // clang-format on
81
82 int option_index = 0;
83 int c =
84 getopt_long(argc, argv, "c:i:m:s:", long_options, &option_index);
85 if (c == -1)
86 {
87 break;
88 }
89
90 switch (c)
91 {
92 case 'c':
93 command = std::string{optarg};
94 if (!checkCommand(command))
95 {
96 usage(argv[0]);
97 exit(EXIT_FAILURE);
98 }
99
100 break;
101 case 'i':
102 interface = std::string{optarg};
103 if (!checkInterface(interface))
104 {
105 usage(argv[0]);
106 exit(EXIT_FAILURE);
107 }
108 break;
109 case 'm':
110 imagePath = std::string{optarg};
111 break;
112 case 's':
113 signaturePath = std::string{optarg};
114 break;
115 default:
116 usage(argv[0]);
117 exit(EXIT_FAILURE);
118 }
119 }
120
121 /* They want to update the firmware. */
122 if (command == "update")
123 {
124 if (interface.empty() || imagePath.empty() || signaturePath.empty())
125 {
126 usage(argv[0]);
127 exit(EXIT_FAILURE);
128 }
129
Patrick Venturecf2d1b12018-12-11 18:22:36 -0800130 IpmiHandler ipmi;
131 BlobHandler blob(&ipmi);
Patrick Venture00887592018-12-11 10:57:06 -0800132
Patrick Venturea6586362018-12-11 18:47:13 -0800133 std::unique_ptr<DataInterface> handler;
134
135 /* Input has already been validated in this case. */
136 if (interface == IPMIBT)
137 {
138 handler = std::make_unique<BtDataHandler>(&blob);
139 }
140 else if (interface == IPMILPC)
141 {
142 handler = std::make_unique<LpcDataHandler>(&blob);
143 }
144
145 if (!handler)
146 {
147 /* TODO(venture): use a custom exception. */
148 std::fprintf(stderr, "Interface %s is unavailable\n",
149 interface.c_str());
150 exit(EXIT_FAILURE);
151 }
152
Patrick Venturebf58cd62018-12-11 09:05:46 -0800153 /* The parameters are all filled out. */
Patrick Venturea6586362018-12-11 18:47:13 -0800154 return updaterMain(&blob, handler.get(), imagePath, signaturePath);
Patrick Venturebf58cd62018-12-11 09:05:46 -0800155 }
156
157 return 0;
158}