blob: 833fbf747d4cdee7cc7776ffd0b1a6a82b631c55 [file] [log] [blame]
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <flashupdate/config.hpp>
#include <nlohmann/json.hpp>
#include <format>
#include <fstream>
#include <optional>
namespace flashupdate
{
Config createConfig(std::optional<std::string> configFile, uint8_t stagingIndex,
const std::string& configPath)
{
if (!configFile)
{
throw std::runtime_error("Configuration file is missing");
}
Config config;
std::string name = *configFile;
// Not full file path
if (name.find(".") == std::string::npos &&
name.find("/") == std::string::npos)
{
name = configPath + name + ".json";
}
std::ifstream configJson(name);
if (!configJson.is_open())
{
throw std::runtime_error(
std::format("Config file `{}` is missing", name));
}
auto data = nlohmann::json::parse(configJson, nullptr, false);
if (data.is_discarded())
{
throw std::runtime_error("failed to parse the config.json");
}
auto flash = data.at("flash");
flash.at("validation_key").get_to(config.flash.validationKey);
auto primary = flash.at("primary");
primary.at("location").get_to(config.flash.primary.location);
auto muxSelect = primary.at("mux_select");
if (muxSelect.is_null())
{
throw std::runtime_error(
"mux_select for primary partition is required");
}
uint16_t mux;
muxSelect.get_to(mux);
config.flash.primary.muxSelect = mux;
auto secondaries = flash.at("secondary");
for (const auto& secondary : secondaries)
{
Config::Partition partition;
secondary.at("location").get_to(partition.location);
auto muxSelect = secondary.at("mux_select");
if (!muxSelect.is_null())
{
muxSelect.get_to(mux);
partition.muxSelect = mux;
}
config.flash.secondary.emplace_back(partition);
}
if (stagingIndex >= secondaries.size())
{
throw std::runtime_error(std::format(
"stage index is greater than or equal to the number of staging "
"partitions: {} >= {}",
stagingIndex, secondaries.size()));
}
config.flash.stagingIndex = stagingIndex;
flash.at("device_id").get_to(config.flash.deviceId);
flash.at("driver").get_to(config.flash.driver);
auto metadata = data.at("metadata");
metadata.at("path").get_to(config.metadata.path);
metadata.at("offset").get_to(config.metadata.offset);
auto cr51 = data.at("cr51");
if (!cr51.is_null())
{
Config::Cr51 cr51Config;
cr51.at("prod_to_dev").get_to(cr51Config.prodToDev);
cr51.at("production_mode").get_to(cr51Config.productionMode);
cr51.at("unsigned_to_dev").get_to(cr51Config.unsignedToDev);
if (cr51.contains("image_family"))
{
cr51.at("image_family").get_to(cr51Config.imageFamily.emplace());
}
config.cr51 = cr51Config;
}
if (data.contains("supported_version"))
{
config.supportedVersion = std::vector<Config::SupportedVersion>();
auto supportedVersion = data.at("supported_version");
for (const auto& version : supportedVersion.items())
{
Config::SupportedVersion currentVersion;
if (version.value().contains("min"))
{
auto minVersion = version.value().at("min");
currentVersion.min = version::Version();
minVersion.at("major").get_to(currentVersion.min->major);
minVersion.at("minor").get_to(currentVersion.min->minor);
minVersion.at("point").get_to(currentVersion.min->point);
minVersion.at("subpoint").get_to(currentVersion.min->subpoint);
}
if (version.value().contains("max"))
{
auto maxVersion = version.value().at("max");
currentVersion.max = version::Version();
maxVersion.at("major").get_to(currentVersion.max->major);
maxVersion.at("minor").get_to(currentVersion.max->minor);
maxVersion.at("point").get_to(currentVersion.max->point);
maxVersion.at("subpoint").get_to(currentVersion.max->subpoint);
}
if (currentVersion.min == std::nullopt &&
currentVersion.max == std::nullopt)
{
continue;
}
config.supportedVersion->emplace_back(currentVersion);
}
}
return config;
}
} // namespace flashupdate