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