blob: ada34bb8836df7c3561f34d2f61f342b28cf7b73 [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 Venture46bdadc2019-01-18 09:04:16 -080019#include "io.hpp"
Patrick Venturecf2d1b12018-12-11 18:22:36 -080020#include "ipmi_handler.hpp"
Patrick Venturea6586362018-12-11 18:47:13 -080021#include "lpc.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 Ventureaa107a62018-12-12 15:16:25 -080030#include <iostream>
31#include <iterator>
Patrick Venture00887592018-12-11 10:57:06 -080032#include <memory>
Patrick Venturebf58cd62018-12-11 09:05:46 -080033#include <string>
Patrick Venturea6586362018-12-11 18:47:13 -080034#include <vector>
35
36#define IPMILPC "ipmilpc"
37#define IPMIBT "ipmibt"
38
39namespace
40{
41const std::vector<std::string> interfaceList = {IPMIBT, IPMILPC};
42}
Patrick Venturebf58cd62018-12-11 09:05:46 -080043
44void usage(const char* program)
45{
Patrick Venture7ae5dde2018-12-14 10:03:35 -080046 std::fprintf(
47 stderr,
48 "Usage: %s --command <command> --interface <interface> --image "
49 "<image file> --sig <signature file>\n",
50 program);
Patrick Venturea6586362018-12-11 18:47:13 -080051
Patrick Venture7ae5dde2018-12-14 10:03:35 -080052 std::fprintf(stderr, "interfaces: ");
Patrick Ventureaa107a62018-12-12 15:16:25 -080053 std::copy(interfaceList.begin(), interfaceList.end(),
54 std::ostream_iterator<std::string>(std::cerr, ", "));
55 std::fprintf(stderr, "\n");
Patrick Venturebf58cd62018-12-11 09:05:46 -080056}
57
58bool checkCommand(const std::string& command)
59{
60 return (command == "update");
61}
62
63bool checkInterface(const std::string& interface)
64{
Patrick Venturea6586362018-12-11 18:47:13 -080065 auto intf =
66 std::find(interfaceList.begin(), interfaceList.end(), interface);
67 return (intf != interfaceList.end());
Patrick Venturebf58cd62018-12-11 09:05:46 -080068}
69
70int main(int argc, char* argv[])
71{
72 std::string command, interface, imagePath, signaturePath;
73
74 while (1)
75 {
76 // clang-format off
77 static struct option long_options[] = {
78 {"command", required_argument, 0, 'c'},
79 {"interface", required_argument, 0, 'i'},
80 {"image", required_argument, 0, 'm'},
81 {"sig", required_argument, 0, 's'},
82 {0, 0, 0, 0}
83 };
84 // clang-format on
85
86 int option_index = 0;
87 int c =
88 getopt_long(argc, argv, "c:i:m:s:", long_options, &option_index);
89 if (c == -1)
90 {
91 break;
92 }
93
94 switch (c)
95 {
96 case 'c':
97 command = std::string{optarg};
98 if (!checkCommand(command))
99 {
100 usage(argv[0]);
101 exit(EXIT_FAILURE);
102 }
103
104 break;
105 case 'i':
106 interface = std::string{optarg};
107 if (!checkInterface(interface))
108 {
109 usage(argv[0]);
110 exit(EXIT_FAILURE);
111 }
112 break;
113 case 'm':
114 imagePath = std::string{optarg};
115 break;
116 case 's':
117 signaturePath = std::string{optarg};
118 break;
119 default:
120 usage(argv[0]);
121 exit(EXIT_FAILURE);
122 }
123 }
124
Patrick Venture361bd5a2018-12-14 09:49:47 -0800125 if (command.empty())
126 {
127 usage(argv[0]);
128 exit(EXIT_FAILURE);
129 }
130
Patrick Venturebf58cd62018-12-11 09:05:46 -0800131 /* They want to update the firmware. */
132 if (command == "update")
133 {
134 if (interface.empty() || imagePath.empty() || signaturePath.empty())
135 {
136 usage(argv[0]);
137 exit(EXIT_FAILURE);
138 }
139
Patrick Venture9b534f02018-12-13 16:10:02 -0800140 host_tool::IpmiHandler ipmi;
141 host_tool::BlobHandler blob(&ipmi);
Patrick Venture46bdadc2019-01-18 09:04:16 -0800142 host_tool::DevMemDevice devmem;
Patrick Venture00887592018-12-11 10:57:06 -0800143
Patrick Venture9b534f02018-12-13 16:10:02 -0800144 std::unique_ptr<host_tool::DataInterface> handler;
Patrick Venturea6586362018-12-11 18:47:13 -0800145
146 /* Input has already been validated in this case. */
147 if (interface == IPMIBT)
148 {
Patrick Venture9b534f02018-12-13 16:10:02 -0800149 handler = std::make_unique<host_tool::BtDataHandler>(&blob);
Patrick Venturea6586362018-12-11 18:47:13 -0800150 }
151 else if (interface == IPMILPC)
152 {
Patrick Venture46bdadc2019-01-18 09:04:16 -0800153 handler =
154 std::make_unique<host_tool::LpcDataHandler>(&blob, &devmem);
Patrick Venturea6586362018-12-11 18:47:13 -0800155 }
156
157 if (!handler)
158 {
159 /* TODO(venture): use a custom exception. */
160 std::fprintf(stderr, "Interface %s is unavailable\n",
161 interface.c_str());
162 exit(EXIT_FAILURE);
163 }
164
Patrick Venturebf58cd62018-12-11 09:05:46 -0800165 /* The parameters are all filled out. */
Patrick Venture2bc23fe2018-12-13 10:16:36 -0800166 try
167 {
Patrick Venture9b534f02018-12-13 16:10:02 -0800168 host_tool::updaterMain(&blob, handler.get(), imagePath,
169 signaturePath);
Patrick Venture2bc23fe2018-12-13 10:16:36 -0800170 }
Patrick Venture9b534f02018-12-13 16:10:02 -0800171 catch (const host_tool::ToolException& e)
Patrick Venture2bc23fe2018-12-13 10:16:36 -0800172 {
173 std::fprintf(stderr, "Exception received: %s\n", e.what());
174 return -1;
175 }
Patrick Venturebf58cd62018-12-11 09:05:46 -0800176 }
177
178 return 0;
179}