1 /* 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 17 #include "blob_handler.hpp" 18 #include "bt.hpp" 19 #include "ipmi_handler.hpp" 20 #include "lpc.hpp" 21 #include "tool_errors.hpp" 22 #include "updater.hpp" 23 24 /* Use CLI11 argument parser once in openbmc/meta-oe or whatever. */ 25 #include <getopt.h> 26 27 #include <algorithm> 28 #include <cstdio> 29 #include <iostream> 30 #include <iterator> 31 #include <memory> 32 #include <string> 33 #include <vector> 34 35 #define IPMILPC "ipmilpc" 36 #define IPMIBT "ipmibt" 37 38 namespace 39 { 40 const std::vector<std::string> interfaceList = {IPMIBT, IPMILPC}; 41 } 42 43 void usage(const char* program) 44 { 45 std::fprintf( 46 stderr, 47 "Usage: %s --command <command> --interface <interface> --image " 48 "<image file> --sig <signature file>\n", 49 program); 50 51 std::fprintf(stderr, "interfaces: "); 52 std::copy(interfaceList.begin(), interfaceList.end(), 53 std::ostream_iterator<std::string>(std::cerr, ", ")); 54 std::fprintf(stderr, "\n"); 55 } 56 57 bool checkCommand(const std::string& command) 58 { 59 return (command == "update"); 60 } 61 62 bool checkInterface(const std::string& interface) 63 { 64 auto intf = 65 std::find(interfaceList.begin(), interfaceList.end(), interface); 66 return (intf != interfaceList.end()); 67 } 68 69 int main(int argc, char* argv[]) 70 { 71 std::string command, interface, imagePath, signaturePath; 72 73 while (1) 74 { 75 // clang-format off 76 static struct option long_options[] = { 77 {"command", required_argument, 0, 'c'}, 78 {"interface", required_argument, 0, 'i'}, 79 {"image", required_argument, 0, 'm'}, 80 {"sig", required_argument, 0, 's'}, 81 {0, 0, 0, 0} 82 }; 83 // clang-format on 84 85 int option_index = 0; 86 int c = 87 getopt_long(argc, argv, "c:i:m:s:", long_options, &option_index); 88 if (c == -1) 89 { 90 break; 91 } 92 93 switch (c) 94 { 95 case 'c': 96 command = std::string{optarg}; 97 if (!checkCommand(command)) 98 { 99 usage(argv[0]); 100 exit(EXIT_FAILURE); 101 } 102 103 break; 104 case 'i': 105 interface = std::string{optarg}; 106 if (!checkInterface(interface)) 107 { 108 usage(argv[0]); 109 exit(EXIT_FAILURE); 110 } 111 break; 112 case 'm': 113 imagePath = std::string{optarg}; 114 break; 115 case 's': 116 signaturePath = std::string{optarg}; 117 break; 118 default: 119 usage(argv[0]); 120 exit(EXIT_FAILURE); 121 } 122 } 123 124 if (command.empty()) 125 { 126 usage(argv[0]); 127 exit(EXIT_FAILURE); 128 } 129 130 /* They want to update the firmware. */ 131 if (command == "update") 132 { 133 if (interface.empty() || imagePath.empty() || signaturePath.empty()) 134 { 135 usage(argv[0]); 136 exit(EXIT_FAILURE); 137 } 138 139 host_tool::IpmiHandler ipmi; 140 host_tool::BlobHandler blob(&ipmi); 141 142 std::unique_ptr<host_tool::DataInterface> handler; 143 144 /* Input has already been validated in this case. */ 145 if (interface == IPMIBT) 146 { 147 handler = std::make_unique<host_tool::BtDataHandler>(&blob); 148 } 149 else if (interface == IPMILPC) 150 { 151 handler = std::make_unique<host_tool::LpcDataHandler>(&blob); 152 } 153 154 if (!handler) 155 { 156 /* TODO(venture): use a custom exception. */ 157 std::fprintf(stderr, "Interface %s is unavailable\n", 158 interface.c_str()); 159 exit(EXIT_FAILURE); 160 } 161 162 /* The parameters are all filled out. */ 163 try 164 { 165 host_tool::updaterMain(&blob, handler.get(), imagePath, 166 signaturePath); 167 } 168 catch (const host_tool::ToolException& e) 169 { 170 std::fprintf(stderr, "Exception received: %s\n", e.what()); 171 return -1; 172 } 173 } 174 175 return 0; 176 } 177