blob: c8b28ce6fb5e02a60c51ca943f297a3c0227713f [file] [log] [blame]
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "modemfwd/firmware_directory.h"
#include <memory>
#include <utility>
#include <base/files/file_path.h>
#include <base/logging.h>
#include <cros_config/cros_config.h>
#include "modemfwd/firmware_manifest.h"
#include "modemfwd/logging.h"
namespace modemfwd {
const char FirmwareDirectory::kGenericCarrierId[] = "generic";
class FirmwareDirectoryImpl : public FirmwareDirectory {
public:
FirmwareDirectoryImpl(std::unique_ptr<FirmwareIndex> index,
const base::FilePath& fw_manifest_directory,
std::string variant)
: index_(std::move(index)),
fw_manifest_directory_(fw_manifest_directory),
variant_(variant) {}
FirmwareDirectoryImpl(const FirmwareDirectoryImpl&) = delete;
FirmwareDirectoryImpl& operator=(const FirmwareDirectoryImpl&) = delete;
// modemfwd::FirmwareDirectory overrides.
FirmwareDirectory::Files FindFirmware(const std::string& device_id,
std::string* carrier_id) override {
FirmwareDirectory::Files result;
DeviceType type{device_id, variant_};
auto device_it = index_->find(type);
if (device_it == index_->end()) {
ELOG(INFO) << "Firmware directory has no firmware for device ID ["
<< device_id << "]";
return result;
}
const DeviceFirmwareCache& cache = device_it->second;
FirmwareFileInfo info;
// Null carrier ID -> just go for generic main and OEM firmwares.
if (!carrier_id) {
if (FindSpecificFirmware(cache.main_firmware, kGenericCarrierId, &info))
result.main_firmware = info;
if (FindSpecificFirmware(cache.oem_firmware, kGenericCarrierId, &info))
result.oem_firmware = info;
return result;
}
// Searching for carrier firmware may change the carrier to generic. This
// is fine, and the main firmware should use the same one in that case.
if (FindFirmwareForCarrier(cache.carrier_firmware, carrier_id, &info))
result.carrier_firmware = info;
if (FindFirmwareForCarrier(cache.main_firmware, carrier_id, &info))
result.main_firmware = info;
if (FindFirmwareForCarrier(cache.oem_firmware, carrier_id, &info))
result.oem_firmware = info;
return result;
}
const base::FilePath& GetFirmwarePath() override {
return fw_manifest_directory_;
};
// modemfwd::IsUsingSameFirmware overrides.
bool IsUsingSameFirmware(const std::string& device_id,
const std::string& carrier_a,
const std::string& carrier_b) override {
// easy case: identical carrier UUID
if (carrier_a == carrier_b)
return true;
DeviceType type{device_id, variant_};
auto device_it = index_->find(type);
// no firmware for this device
if (device_it == index_->end())
return true;
const DeviceFirmwareCache& cache = device_it->second;
auto main_a = cache.main_firmware.find(carrier_a);
auto main_b = cache.main_firmware.find(carrier_b);
auto cust_a = cache.carrier_firmware.find(carrier_a);
auto cust_b = cache.carrier_firmware.find(carrier_b);
// one or several firmwares are missing
if (main_a == cache.main_firmware.end() ||
main_b == cache.main_firmware.end() ||
cust_a == cache.carrier_firmware.end() ||
cust_b == cache.carrier_firmware.end())
return main_a == main_b && cust_a == cust_b;
// same firmware if they are pointing to the 2 same files.
return main_a->second == main_b->second && cust_a->second == cust_b->second;
}
// modemfwd::OverrideVariantForTesting overrides.
void OverrideVariantForTesting(const std::string& variant) override {
if (variant.empty() || variant == variant_)
return;
LOG(INFO) << "Override variant value: " << variant;
variant_ = variant;
};
private:
bool FindFirmwareForCarrier(
const DeviceFirmwareCache::CarrierIndex& carrier_index,
std::string* carrier_id,
FirmwareFileInfo* out_info) {
if (FindSpecificFirmware(carrier_index, *carrier_id, out_info))
return true;
if (FindSpecificFirmware(carrier_index, kGenericCarrierId, out_info)) {
*carrier_id = kGenericCarrierId;
return true;
}
return false;
}
bool FindSpecificFirmware(
const DeviceFirmwareCache::CarrierIndex& carrier_index,
const std::string& carrier_id,
FirmwareFileInfo* out_info) {
auto it = carrier_index.find(carrier_id);
if (it == carrier_index.end())
return false;
*out_info = *it->second;
return true;
}
std::unique_ptr<FirmwareIndex> index_;
base::FilePath fw_manifest_directory_;
std::string variant_;
};
std::unique_ptr<FirmwareDirectory> CreateFirmwareDirectory(
std::unique_ptr<FirmwareIndex> index,
const base::FilePath& directory,
const std::string& variant) {
return std::make_unique<FirmwareDirectoryImpl>(std::move(index), directory,
variant);
}
} // namespace modemfwd