1*ded66d0fSJason Ling /*
2*ded66d0fSJason Ling  * Copyright 2018 Google Inc.
3*ded66d0fSJason Ling  *
4*ded66d0fSJason Ling  * Licensed under the Apache License, Version 2.0 (the "License");
5*ded66d0fSJason Ling  * you may not use this file except in compliance with the License.
6*ded66d0fSJason Ling  * You may obtain a copy of the License at
7*ded66d0fSJason Ling  *
8*ded66d0fSJason Ling  *     http://www.apache.org/licenses/LICENSE-2.0
9*ded66d0fSJason Ling  *
10*ded66d0fSJason Ling  * Unless required by applicable law or agreed to in writing, software
11*ded66d0fSJason Ling  * distributed under the License is distributed on an "AS IS" BASIS,
12*ded66d0fSJason Ling  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ded66d0fSJason Ling  * See the License for the specific language governing permissions and
14*ded66d0fSJason Ling  * limitations under the License.
15*ded66d0fSJason Ling  */
16*ded66d0fSJason Ling 
17*ded66d0fSJason Ling #include "config.h"
18*ded66d0fSJason Ling 
19*ded66d0fSJason Ling #include "buildjson.hpp"
20*ded66d0fSJason Ling #include "file_handler.hpp"
21*ded66d0fSJason Ling #include "firmware_handler.hpp"
22*ded66d0fSJason Ling #include "flags.hpp"
23*ded66d0fSJason Ling #include "general_systemd.hpp"
24*ded66d0fSJason Ling #include "image_handler.hpp"
25*ded66d0fSJason Ling #include "lpc_aspeed.hpp"
26*ded66d0fSJason Ling #include "lpc_handler.hpp"
27*ded66d0fSJason Ling #include "lpc_nuvoton.hpp"
28*ded66d0fSJason Ling #include "net_handler.hpp"
29*ded66d0fSJason Ling #include "pci_handler.hpp"
30*ded66d0fSJason Ling #include "status.hpp"
31*ded66d0fSJason Ling #include "util.hpp"
32*ded66d0fSJason Ling 
33*ded66d0fSJason Ling #include <sdbusplus/bus.hpp>
34*ded66d0fSJason Ling 
35*ded66d0fSJason Ling #include <cstdint>
36*ded66d0fSJason Ling #include <memory>
37*ded66d0fSJason Ling #include <string>
38*ded66d0fSJason Ling #include <unordered_map>
39*ded66d0fSJason Ling #include <vector>
40*ded66d0fSJason Ling 
41*ded66d0fSJason Ling namespace ipmi_flash
42*ded66d0fSJason Ling {
43*ded66d0fSJason Ling 
44*ded66d0fSJason Ling namespace
45*ded66d0fSJason Ling {
46*ded66d0fSJason Ling 
47*ded66d0fSJason Ling static constexpr const char* jsonConfigurationPath =
48*ded66d0fSJason Ling     "/usr/share/phosphor-ipmi-flash/";
49*ded66d0fSJason Ling 
50*ded66d0fSJason Ling /**
51*ded66d0fSJason Ling  * Given a name and path, create a HandlerPack.
52*ded66d0fSJason Ling  *
53*ded66d0fSJason Ling  * @param[in] name - the blob id path for this
54*ded66d0fSJason Ling  * @param[in] path - the file path to write the contents.
55*ded66d0fSJason Ling  * @return the HandlerPack.
56*ded66d0fSJason Ling  */
57*ded66d0fSJason Ling HandlerPack CreateFileHandlerPack(const std::string& name,
58*ded66d0fSJason Ling                                   const std::string& path)
59*ded66d0fSJason Ling {
60*ded66d0fSJason Ling     return HandlerPack(name, std::make_unique<FileHandler>(path));
61*ded66d0fSJason Ling }
62*ded66d0fSJason Ling 
63*ded66d0fSJason Ling #ifdef NUVOTON_P2A_MBOX
64*ded66d0fSJason Ling static constexpr std::size_t memoryRegionSize = 16 * 1024UL;
65*ded66d0fSJason Ling #elif defined NUVOTON_P2A_VGA
66*ded66d0fSJason Ling static constexpr std::size_t memoryRegionSize = 4 * 1024 * 1024UL;
67*ded66d0fSJason Ling #else
68*ded66d0fSJason Ling /* The maximum external buffer size we expect is 64KB. */
69*ded66d0fSJason Ling static constexpr std::size_t memoryRegionSize = 64 * 1024UL;
70*ded66d0fSJason Ling #endif
71*ded66d0fSJason Ling 
72*ded66d0fSJason Ling } // namespace
73*ded66d0fSJason Ling } // namespace ipmi_flash
74*ded66d0fSJason Ling 
75*ded66d0fSJason Ling extern "C"
76*ded66d0fSJason Ling {
77*ded66d0fSJason Ling     std::unique_ptr<blobs::GenericBlobInterface> createHandler();
78*ded66d0fSJason Ling }
79*ded66d0fSJason Ling 
80*ded66d0fSJason Ling std::unique_ptr<blobs::GenericBlobInterface> createHandler()
81*ded66d0fSJason Ling {
82*ded66d0fSJason Ling     using namespace ipmi_flash;
83*ded66d0fSJason Ling 
84*ded66d0fSJason Ling     std::vector<DataHandlerPack> supportedTransports;
85*ded66d0fSJason Ling 
86*ded66d0fSJason Ling     supportedTransports.emplace_back(FirmwareFlags::UpdateFlags::ipmi, nullptr);
87*ded66d0fSJason Ling 
88*ded66d0fSJason Ling #ifdef ENABLE_PCI_BRIDGE
89*ded66d0fSJason Ling     supportedTransports.emplace_back(
90*ded66d0fSJason Ling         FirmwareFlags::UpdateFlags::p2a,
91*ded66d0fSJason Ling         std::make_unique<PciDataHandler>(MAPPED_ADDRESS, memoryRegionSize));
92*ded66d0fSJason Ling #endif
93*ded66d0fSJason Ling 
94*ded66d0fSJason Ling #ifdef ENABLE_LPC_BRIDGE
95*ded66d0fSJason Ling #if defined(ASPEED_LPC)
96*ded66d0fSJason Ling     supportedTransports.emplace_back(
97*ded66d0fSJason Ling         FirmwareFlags::UpdateFlags::lpc,
98*ded66d0fSJason Ling         std::make_unique<LpcDataHandler>(LpcMapperAspeed::createAspeedMapper(
99*ded66d0fSJason Ling             MAPPED_ADDRESS, memoryRegionSize)));
100*ded66d0fSJason Ling #elif defined(NUVOTON_LPC)
101*ded66d0fSJason Ling     supportedTransports.emplace_back(
102*ded66d0fSJason Ling         FirmwareFlags::UpdateFlags::lpc,
103*ded66d0fSJason Ling         std::make_unique<LpcDataHandler>(LpcMapperNuvoton::createNuvotonMapper(
104*ded66d0fSJason Ling             MAPPED_ADDRESS, memoryRegionSize)));
105*ded66d0fSJason Ling #else
106*ded66d0fSJason Ling #error "You must specify a hardware implementation."
107*ded66d0fSJason Ling #endif
108*ded66d0fSJason Ling #endif
109*ded66d0fSJason Ling 
110*ded66d0fSJason Ling #ifdef ENABLE_NET_BRIDGE
111*ded66d0fSJason Ling     supportedTransports.emplace_back(FirmwareFlags::UpdateFlags::net,
112*ded66d0fSJason Ling                                      std::make_unique<NetDataHandler>());
113*ded66d0fSJason Ling #endif
114*ded66d0fSJason Ling 
115*ded66d0fSJason Ling     ActionMap actionPacks = {};
116*ded66d0fSJason Ling 
117*ded66d0fSJason Ling     std::vector<HandlerConfig> configsFromJson =
118*ded66d0fSJason Ling         BuildHandlerConfigs(jsonConfigurationPath);
119*ded66d0fSJason Ling 
120*ded66d0fSJason Ling     std::vector<HandlerPack> supportedFirmware;
121*ded66d0fSJason Ling 
122*ded66d0fSJason Ling     supportedFirmware.push_back(
123*ded66d0fSJason Ling         std::move(CreateFileHandlerPack(hashBlobId, HASH_FILENAME)));
124*ded66d0fSJason Ling 
125*ded66d0fSJason Ling     for (auto& config : configsFromJson)
126*ded66d0fSJason Ling     {
127*ded66d0fSJason Ling         supportedFirmware.emplace_back(config.blobId,
128*ded66d0fSJason Ling                                        std::move(config.handler));
129*ded66d0fSJason Ling         actionPacks[config.blobId] = std::move(config.actions);
130*ded66d0fSJason Ling 
131*ded66d0fSJason Ling         std::fprintf(stderr, "config loaded: %s\n", config.blobId.c_str());
132*ded66d0fSJason Ling     }
133*ded66d0fSJason Ling 
134*ded66d0fSJason Ling     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
135*ded66d0fSJason Ling         std::move(supportedFirmware), std::move(supportedTransports),
136*ded66d0fSJason Ling         std::move(actionPacks));
137*ded66d0fSJason Ling 
138*ded66d0fSJason Ling     if (!handler)
139*ded66d0fSJason Ling     {
140*ded66d0fSJason Ling         std::fprintf(stderr, "Firmware Handler has an invalid configuration");
141*ded66d0fSJason Ling         return nullptr;
142*ded66d0fSJason Ling     }
143*ded66d0fSJason Ling 
144*ded66d0fSJason Ling     return handler;
145*ded66d0fSJason Ling }
146