blob: bb05a71279af9b963fb699a4d085bd1acda5b7b8 [file] [log] [blame] [edit]
// 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 {
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;
}
} // namespace
namespace modemfwd {
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();
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();
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