blob: 2fbd970c3ea77770a0c7232ce01aca70ec0aee99 [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 <base/macros.h>
#include <cros_config/cros_config.h>
#include "modemfwd/proto_bindings/firmware_manifest.pb.h"
#include "modemfwd/proto_file_io.h"
namespace modemfwd {
namespace {
const char kManifestName[] = "firmware_manifest.prototxt";
// Returns the modem firmware variant for the current model of the device by
// reading the /modem/firmware-variant property of the current model via
// chromeos-config. Returns an empty string if it fails to read the modem
// firmware variant from chromeos-config or no modem firmware variant is
// specified.
std::string GetModemFirmwareVariant() {
brillo::CrosConfig config;
if (!config.InitModel()) {
LOG(WARNING) << "Failed to load Chrome OS configuration";
return std::string();
}
std::string variant;
if (!config.GetString("/modem", "firmware-variant", &variant)) {
LOG(INFO) << "No modem firmware variant is specified";
return std::string();
}
LOG(INFO) << "Use modem firmware variant: " << variant;
return variant;
}
FirmwareFileInfo::Compression ToFirmwareFileInfoCompression(
Compression compression) {
switch (compression) {
case Compression::NONE:
return FirmwareFileInfo::Compression::NONE;
case Compression::XZ:
return FirmwareFileInfo::Compression::XZ;
default:
LOG(FATAL) << "Invalid compression: " << compression;
return FirmwareFileInfo::Compression::NONE;
}
}
} // namespace
const char FirmwareDirectory::kGenericCarrierId[] = "generic";
class FirmwareDirectoryImpl : public FirmwareDirectory {
public:
FirmwareDirectoryImpl(const FirmwareManifest& manifest,
const base::FilePath& directory)
: manifest_(manifest),
directory_(directory),
variant_(GetModemFirmwareVariant()) {}
// modemfwd::FirmwareDirectory overrides.
bool FindMainFirmware(const std::string& device_id,
FirmwareFileInfo* out_info) override {
DCHECK(out_info);
for (const MainFirmware& file_info : manifest_.main_firmware()) {
if (file_info.device_id() == device_id &&
(file_info.variant().empty() || file_info.variant() == variant_) &&
!file_info.filename().empty() && !file_info.version().empty()) {
out_info->firmware_path = directory_.Append(file_info.filename());
out_info->version = file_info.version();
out_info->compression =
ToFirmwareFileInfoCompression(file_info.compression());
return true;
}
}
return false;
}
bool FindCarrierFirmware(const std::string& device_id,
std::string* carrier_id,
FirmwareFileInfo* out_info) override {
DCHECK(carrier_id);
if (FindSpecificCarrierFirmware(device_id, *carrier_id, out_info))
return true;
if (FindSpecificCarrierFirmware(device_id, kGenericCarrierId, out_info)) {
*carrier_id = kGenericCarrierId;
return true;
}
return false;
}
private:
bool FindSpecificCarrierFirmware(const std::string& device_id,
const std::string& carrier_id,
FirmwareFileInfo* out_info) {
DCHECK(out_info);
for (const CarrierFirmware& file_info : manifest_.carrier_firmware()) {
if (file_info.device_id() != device_id ||
(!file_info.variant().empty() && file_info.variant() != variant_) ||
file_info.filename().empty() || file_info.version().empty()) {
continue;
}
for (const std::string& supported_carrier : file_info.carrier_id()) {
if (supported_carrier == carrier_id) {
out_info->firmware_path = directory_.Append(file_info.filename());
out_info->version = file_info.version();
out_info->compression =
ToFirmwareFileInfoCompression(file_info.compression());
return true;
}
}
}
return false;
}
FirmwareManifest manifest_;
base::FilePath directory_;
std::string variant_;
DISALLOW_COPY_AND_ASSIGN(FirmwareDirectoryImpl);
};
std::unique_ptr<FirmwareDirectory> CreateFirmwareDirectory(
const base::FilePath& directory) {
FirmwareManifest parsed_manifest;
if (!ReadProtobuf(directory.Append(kManifestName), &parsed_manifest))
return nullptr;
return std::make_unique<FirmwareDirectoryImpl>(parsed_manifest, directory);
}
} // namespace modemfwd