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 "config.h"
18 
19 #include "file_handler.hpp"
20 #include "firmware_handler.hpp"
21 #include "firmware_handlers_builder.hpp"
22 #include "flags.hpp"
23 #include "general_systemd.hpp"
24 #include "image_handler.hpp"
25 #include "lpc_aspeed.hpp"
26 #include "lpc_handler.hpp"
27 #include "lpc_nuvoton.hpp"
28 #include "net_handler.hpp"
29 #include "pci_handler.hpp"
30 #include "status.hpp"
31 #include "util.hpp"
32 
33 #include <sdbusplus/bus.hpp>
34 
35 #include <cstdint>
36 #include <memory>
37 #include <string>
38 #include <unordered_map>
39 #include <vector>
40 
41 namespace ipmi_flash
42 {
43 
44 namespace
45 {
46 
47 static constexpr const char* jsonConfigurationPath =
48     "/usr/share/phosphor-ipmi-flash/";
49 
50 /**
51  * Given a name and path, create a HandlerPack.
52  *
53  * @param[in] name - the blob id path for this
54  * @param[in] path - the file path to write the contents.
55  * @return the HandlerPack.
56  */
57 HandlerPack CreateFileHandlerPack(const std::string& name,
58                                   const std::string& path)
59 {
60     return HandlerPack(name, std::make_unique<FileHandler>(path));
61 }
62 
63 #ifdef NUVOTON_P2A_MBOX
64 static constexpr std::size_t memoryRegionSize = 16 * 1024UL;
65 #elif defined NUVOTON_P2A_VGA
66 static constexpr std::size_t memoryRegionSize = 4 * 1024 * 1024UL;
67 #else
68 /* The maximum external buffer size we expect is 64KB. */
69 static constexpr std::size_t memoryRegionSize = 64 * 1024UL;
70 #endif
71 
72 } // namespace
73 } // namespace ipmi_flash
74 
75 extern "C"
76 {
77     std::unique_ptr<blobs::GenericBlobInterface> createHandler();
78 }
79 
80 std::unique_ptr<blobs::GenericBlobInterface> createHandler()
81 {
82     using namespace ipmi_flash;
83 
84     std::vector<DataHandlerPack> supportedTransports;
85 
86     supportedTransports.emplace_back(FirmwareFlags::UpdateFlags::ipmi, nullptr);
87 
88 #ifdef ENABLE_PCI_BRIDGE
89     supportedTransports.emplace_back(
90         FirmwareFlags::UpdateFlags::p2a,
91         std::make_unique<PciDataHandler>(MAPPED_ADDRESS, memoryRegionSize));
92 #endif
93 
94 #ifdef ENABLE_LPC_BRIDGE
95 #if defined(ASPEED_LPC)
96     supportedTransports.emplace_back(
97         FirmwareFlags::UpdateFlags::lpc,
98         std::make_unique<LpcDataHandler>(LpcMapperAspeed::createAspeedMapper(
99             MAPPED_ADDRESS, memoryRegionSize)));
100 #elif defined(NUVOTON_LPC)
101     supportedTransports.emplace_back(
102         FirmwareFlags::UpdateFlags::lpc,
103         std::make_unique<LpcDataHandler>(LpcMapperNuvoton::createNuvotonMapper(
104             MAPPED_ADDRESS, memoryRegionSize)));
105 #else
106 #error "You must specify a hardware implementation."
107 #endif
108 #endif
109 
110 #ifdef ENABLE_NET_BRIDGE
111     supportedTransports.emplace_back(FirmwareFlags::UpdateFlags::net,
112                                      std::make_unique<NetDataHandler>());
113 #endif
114 
115     ActionMap actionPacks = {};
116     FirmwareHandlersBuilder builder;
117 
118     std::vector<HandlerConfig<ActionPack>> configsFromJson =
119         builder.buildHandlerConfigs(jsonConfigurationPath);
120 
121     std::vector<HandlerPack> supportedFirmware;
122 
123     supportedFirmware.push_back(
124         std::move(CreateFileHandlerPack(hashBlobId, HASH_FILENAME)));
125 
126     for (auto& config : configsFromJson)
127     {
128         supportedFirmware.emplace_back(config.blobId,
129                                        std::move(config.handler));
130         actionPacks[config.blobId] = std::move(config.actions);
131 
132         std::fprintf(stderr, "config loaded: %s\n", config.blobId.c_str());
133     }
134 
135     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
136         std::move(supportedFirmware), std::move(supportedTransports),
137         std::move(actionPacks));
138 
139     if (!handler)
140     {
141         std::fprintf(stderr, "Firmware Handler has an invalid configuration");
142         return nullptr;
143     }
144 
145     return handler;
146 }
147