| // 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 |