1856166594771c61973856f563e622ccb7dd48aa1Alex Deymo//
2856166594771c61973856f563e622ccb7dd48aa1Alex Deymo// Copyright (C) 2015 The Android Open Source Project
3856166594771c61973856f563e622ccb7dd48aa1Alex Deymo//
4856166594771c61973856f563e622ccb7dd48aa1Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License");
5856166594771c61973856f563e622ccb7dd48aa1Alex Deymo// you may not use this file except in compliance with the License.
6856166594771c61973856f563e622ccb7dd48aa1Alex Deymo// You may obtain a copy of the License at
7856166594771c61973856f563e622ccb7dd48aa1Alex Deymo//
8856166594771c61973856f563e622ccb7dd48aa1Alex Deymo//      http://www.apache.org/licenses/LICENSE-2.0
9856166594771c61973856f563e622ccb7dd48aa1Alex Deymo//
10856166594771c61973856f563e622ccb7dd48aa1Alex Deymo// Unless required by applicable law or agreed to in writing, software
11856166594771c61973856f563e622ccb7dd48aa1Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS,
12856166594771c61973856f563e622ccb7dd48aa1Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13856166594771c61973856f563e622ccb7dd48aa1Alex Deymo// See the License for the specific language governing permissions and
14856166594771c61973856f563e622ccb7dd48aa1Alex Deymo// limitations under the License.
15856166594771c61973856f563e622ccb7dd48aa1Alex Deymo//
16856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
17856166594771c61973856f563e622ccb7dd48aa1Alex Deymo#include "update_engine/image_properties.h"
18856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
19856166594771c61973856f563e622ccb7dd48aa1Alex Deymo#include <string>
20856166594771c61973856f563e622ccb7dd48aa1Alex Deymo#include <vector>
21856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
22856166594771c61973856f563e622ccb7dd48aa1Alex Deymo#include <base/files/file_util.h>
23856166594771c61973856f563e622ccb7dd48aa1Alex Deymo#include <base/logging.h>
24856166594771c61973856f563e622ccb7dd48aa1Alex Deymo#include <brillo/key_value_store.h>
25856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
2639910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/constants.h"
2739910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/hardware_interface.h"
2839910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/platform_constants.h"
29afd8cea0060751f969f7d4d20b4c4100ff37626dAmin Hassani#include "update_engine/common/utils.h"
30856166594771c61973856f563e622ccb7dd48aa1Alex Deymo#include "update_engine/system_state.h"
31856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
32856166594771c61973856f563e622ccb7dd48aa1Alex Deymonamespace {
33856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
34856166594771c61973856f563e622ccb7dd48aa1Alex Deymoconst char kLsbRelease[] = "/etc/lsb-release";
35856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
36856166594771c61973856f563e622ccb7dd48aa1Alex Deymoconst char kLsbReleaseAppIdKey[] = "CHROMEOS_RELEASE_APPID";
37856166594771c61973856f563e622ccb7dd48aa1Alex Deymoconst char kLsbReleaseAutoUpdateServerKey[] = "CHROMEOS_AUSERVER";
38856166594771c61973856f563e622ccb7dd48aa1Alex Deymoconst char kLsbReleaseBoardAppIdKey[] = "CHROMEOS_BOARD_APPID";
39856166594771c61973856f563e622ccb7dd48aa1Alex Deymoconst char kLsbReleaseBoardKey[] = "CHROMEOS_RELEASE_BOARD";
40856166594771c61973856f563e622ccb7dd48aa1Alex Deymoconst char kLsbReleaseCanaryAppIdKey[] = "CHROMEOS_CANARY_APPID";
41856166594771c61973856f563e622ccb7dd48aa1Alex Deymoconst char kLsbReleaseIsPowerwashAllowedKey[] = "CHROMEOS_IS_POWERWASH_ALLOWED";
42856166594771c61973856f563e622ccb7dd48aa1Alex Deymoconst char kLsbReleaseUpdateChannelKey[] = "CHROMEOS_RELEASE_TRACK";
43856166594771c61973856f563e622ccb7dd48aa1Alex Deymoconst char kLsbReleaseVersionKey[] = "CHROMEOS_RELEASE_VERSION";
44856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
45856166594771c61973856f563e622ccb7dd48aa1Alex Deymoconst char kDefaultAppId[] = "{87efface-864d-49a5-9bb3-4b050a7c227a}";
46856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
47856166594771c61973856f563e622ccb7dd48aa1Alex Deymo// A prefix added to the path, used for testing.
483be05c82442b2fbab693b6399f64610e8542462bAlex Deymoconst char* root_prefix = nullptr;
49856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
50856166594771c61973856f563e622ccb7dd48aa1Alex Deymostd::string GetStringWithDefault(const brillo::KeyValueStore& store,
51856166594771c61973856f563e622ccb7dd48aa1Alex Deymo                                 const std::string& key,
52856166594771c61973856f563e622ccb7dd48aa1Alex Deymo                                 const std::string& default_value) {
53856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  std::string result;
54856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  if (store.GetString(key, &result))
55856166594771c61973856f563e622ccb7dd48aa1Alex Deymo    return result;
56856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  LOG(INFO) << "Cannot load ImageProperty " << key << ", using default value "
57856166594771c61973856f563e622ccb7dd48aa1Alex Deymo            << default_value;
58856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  return default_value;
59856166594771c61973856f563e622ccb7dd48aa1Alex Deymo}
60856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
61856166594771c61973856f563e622ccb7dd48aa1Alex Deymoenum class LsbReleaseSource {
62856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  kSystem,
63856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  kStateful,
64856166594771c61973856f563e622ccb7dd48aa1Alex Deymo};
65856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
66856166594771c61973856f563e622ccb7dd48aa1Alex Deymo// Loads the lsb-release properties into the key-value |store| reading the file
67856166594771c61973856f563e622ccb7dd48aa1Alex Deymo// from either the system image or the stateful partition as specified by
68856166594771c61973856f563e622ccb7dd48aa1Alex Deymo// |source|. The loaded values are added to the store, possibly overriding
69856166594771c61973856f563e622ccb7dd48aa1Alex Deymo// existing values.
70856166594771c61973856f563e622ccb7dd48aa1Alex Deymovoid LoadLsbRelease(LsbReleaseSource source, brillo::KeyValueStore* store) {
713be05c82442b2fbab693b6399f64610e8542462bAlex Deymo  std::string path;
723be05c82442b2fbab693b6399f64610e8542462bAlex Deymo  if (root_prefix)
733be05c82442b2fbab693b6399f64610e8542462bAlex Deymo    path = root_prefix;
74856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  if (source == LsbReleaseSource::kStateful)
75856166594771c61973856f563e622ccb7dd48aa1Alex Deymo    path += chromeos_update_engine::kStatefulPartition;
76856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  store->Load(base::FilePath(path + kLsbRelease));
77856166594771c61973856f563e622ccb7dd48aa1Alex Deymo}
78856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
79856166594771c61973856f563e622ccb7dd48aa1Alex Deymo}  // namespace
80856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
81856166594771c61973856f563e622ccb7dd48aa1Alex Deymonamespace chromeos_update_engine {
82856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
83856166594771c61973856f563e622ccb7dd48aa1Alex Deymonamespace test {
84856166594771c61973856f563e622ccb7dd48aa1Alex Deymovoid SetImagePropertiesRootPrefix(const char* test_root_prefix) {
85856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  root_prefix = test_root_prefix;
86856166594771c61973856f563e622ccb7dd48aa1Alex Deymo}
87856166594771c61973856f563e622ccb7dd48aa1Alex Deymo}  // namespace test
88856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
89856166594771c61973856f563e622ccb7dd48aa1Alex DeymoImageProperties LoadImageProperties(SystemState* system_state) {
90856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  ImageProperties result;
91856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
92856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  brillo::KeyValueStore lsb_release;
93856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  LoadLsbRelease(LsbReleaseSource::kSystem, &lsb_release);
94856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  result.current_channel = GetStringWithDefault(
95856166594771c61973856f563e622ccb7dd48aa1Alex Deymo      lsb_release, kLsbReleaseUpdateChannelKey, "stable-channel");
96856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
97856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  // In dev-mode and unofficial build we can override the image properties set
98856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  // in the system image with the ones from the stateful partition, except the
99856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  // channel of the current image.
100856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  HardwareInterface* const hardware = system_state->hardware();
101856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  if (!hardware->IsOfficialBuild() || !hardware->IsNormalBootMode())
102856166594771c61973856f563e622ccb7dd48aa1Alex Deymo    LoadLsbRelease(LsbReleaseSource::kStateful, &lsb_release);
103856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
104856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  // The release_app_id is used as the default appid, but can be override by
105856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  // the board appid in the general case or the canary appid for the canary
106856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  // channel only.
107856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  std::string release_app_id =
108856166594771c61973856f563e622ccb7dd48aa1Alex Deymo      GetStringWithDefault(lsb_release, kLsbReleaseAppIdKey, kDefaultAppId);
109856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
110856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  result.product_id = GetStringWithDefault(
111856166594771c61973856f563e622ccb7dd48aa1Alex Deymo      lsb_release, kLsbReleaseBoardAppIdKey, release_app_id);
112856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  result.canary_product_id = GetStringWithDefault(
113856166594771c61973856f563e622ccb7dd48aa1Alex Deymo      lsb_release, kLsbReleaseCanaryAppIdKey, release_app_id);
114856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  result.board = GetStringWithDefault(lsb_release, kLsbReleaseBoardKey, "");
115856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  result.version = GetStringWithDefault(lsb_release, kLsbReleaseVersionKey, "");
116856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  result.omaha_url =
117856166594771c61973856f563e622ccb7dd48aa1Alex Deymo      GetStringWithDefault(lsb_release, kLsbReleaseAutoUpdateServerKey,
118856166594771c61973856f563e622ccb7dd48aa1Alex Deymo                           constants::kOmahaDefaultProductionURL);
119ebf6e1228e6e42c19334bb8b3da62f4aef105deaAlex Deymo  // Build fingerprint not used in Chrome OS.
120558fe6ad38c6c419a135ce1ed1e3d1152f55ff7cAlex Deymo  result.build_fingerprint = "";
1217f785f584d943308b06596f8d279e9c4b711adb6Sen Jiang  result.allow_arbitrary_channels = false;
122856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
123856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  return result;
124856166594771c61973856f563e622ccb7dd48aa1Alex Deymo}
125856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
126856166594771c61973856f563e622ccb7dd48aa1Alex DeymoMutableImageProperties LoadMutableImageProperties(SystemState* system_state) {
127856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  MutableImageProperties result;
128856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  brillo::KeyValueStore lsb_release;
129856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  LoadLsbRelease(LsbReleaseSource::kSystem, &lsb_release);
130856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  LoadLsbRelease(LsbReleaseSource::kStateful, &lsb_release);
131856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  result.target_channel = GetStringWithDefault(
132856166594771c61973856f563e622ccb7dd48aa1Alex Deymo      lsb_release, kLsbReleaseUpdateChannelKey, "stable-channel");
133856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  if (!lsb_release.GetBoolean(kLsbReleaseIsPowerwashAllowedKey,
134856166594771c61973856f563e622ccb7dd48aa1Alex Deymo                              &result.is_powerwash_allowed))
135856166594771c61973856f563e622ccb7dd48aa1Alex Deymo    result.is_powerwash_allowed = false;
136856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  return result;
137856166594771c61973856f563e622ccb7dd48aa1Alex Deymo}
138856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
139856166594771c61973856f563e622ccb7dd48aa1Alex Deymobool StoreMutableImageProperties(SystemState* system_state,
140856166594771c61973856f563e622ccb7dd48aa1Alex Deymo                                 const MutableImageProperties& properties) {
141856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  brillo::KeyValueStore lsb_release;
142856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  LoadLsbRelease(LsbReleaseSource::kStateful, &lsb_release);
143856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  lsb_release.SetString(kLsbReleaseUpdateChannelKey, properties.target_channel);
144856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  lsb_release.SetBoolean(kLsbReleaseIsPowerwashAllowedKey,
145856166594771c61973856f563e622ccb7dd48aa1Alex Deymo                         properties.is_powerwash_allowed);
146856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
1475378f5e3d9420521a1afff935ed37b726d42ead6Alex Deymo  std::string root_prefix_str = root_prefix ? root_prefix : "";
1485378f5e3d9420521a1afff935ed37b726d42ead6Alex Deymo  base::FilePath path(root_prefix_str + kStatefulPartition + kLsbRelease);
149856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  if (!base::DirectoryExists(path.DirName()))
150856166594771c61973856f563e622ccb7dd48aa1Alex Deymo    base::CreateDirectory(path.DirName());
151856166594771c61973856f563e622ccb7dd48aa1Alex Deymo  return lsb_release.Save(path);
152856166594771c61973856f563e622ccb7dd48aa1Alex Deymo}
153856166594771c61973856f563e622ccb7dd48aa1Alex Deymo
154afd8cea0060751f969f7d4d20b4c4100ff37626dAmin Hassanivoid LogImageProperties() {
155afd8cea0060751f969f7d4d20b4c4100ff37626dAmin Hassani  std::string lsb_release;
156afd8cea0060751f969f7d4d20b4c4100ff37626dAmin Hassani  if (utils::ReadFile(kLsbRelease, &lsb_release)) {
157afd8cea0060751f969f7d4d20b4c4100ff37626dAmin Hassani    LOG(INFO) << "lsb-release inside the old rootfs:\n" << lsb_release;
158afd8cea0060751f969f7d4d20b4c4100ff37626dAmin Hassani  }
159afd8cea0060751f969f7d4d20b4c4100ff37626dAmin Hassani
160afd8cea0060751f969f7d4d20b4c4100ff37626dAmin Hassani  std::string stateful_lsb_release;
161afd8cea0060751f969f7d4d20b4c4100ff37626dAmin Hassani  if (utils::ReadFile(std::string(kStatefulPartition) + kLsbRelease,
162afd8cea0060751f969f7d4d20b4c4100ff37626dAmin Hassani                      &stateful_lsb_release)) {
163afd8cea0060751f969f7d4d20b4c4100ff37626dAmin Hassani    LOG(INFO) << "stateful lsb-release:\n" << stateful_lsb_release;
164afd8cea0060751f969f7d4d20b4c4100ff37626dAmin Hassani  }
165afd8cea0060751f969f7d4d20b4c4100ff37626dAmin Hassani}
166afd8cea0060751f969f7d4d20b4c4100ff37626dAmin Hassani
167856166594771c61973856f563e622ccb7dd48aa1Alex Deymo}  // namespace chromeos_update_engine
168