• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2015 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #ifndef UPDATE_ENGINE_COMMON_FAKE_BOOT_CONTROL_H_
18 #define UPDATE_ENGINE_COMMON_FAKE_BOOT_CONTROL_H_
19 
20 #include <map>
21 #include <memory>
22 #include <string>
23 #include <vector>
24 
25 #include <base/time/time.h>
26 
27 #include "update_engine/common/boot_control_interface.h"
28 #include "update_engine/common/dynamic_partition_control_stub.h"
29 
30 namespace chromeos_update_engine {
31 
32 // Implements a fake bootloader control interface used for testing.
33 class FakeBootControl : public BootControlInterface {
34  public:
FakeBootControl()35   FakeBootControl() {
36     SetNumSlots(num_slots_);
37     // The current slot should be bootable.
38     is_bootable_[current_slot_] = true;
39 
40     dynamic_partition_control_.reset(new DynamicPartitionControlStub());
41   }
42 
SetDynamicPartitionControl(std::unique_ptr<DynamicPartitionControlInterface> dynamic_control)43   void SetDynamicPartitionControl(
44       std::unique_ptr<DynamicPartitionControlInterface> dynamic_control) {
45     dynamic_partition_control_ = std::move(dynamic_control);
46   }
47 
48   // BootControlInterface overrides.
GetNumSlots()49   unsigned int GetNumSlots() const override { return num_slots_; }
GetCurrentSlot()50   BootControlInterface::Slot GetCurrentSlot() const override {
51     return current_slot_;
52   }
53 
GetPartitionDevice(const std::string & partition_name,BootControlInterface::Slot slot,bool not_in_payload,std::string * device,bool * is_dynamic)54   bool GetPartitionDevice(const std::string& partition_name,
55                           BootControlInterface::Slot slot,
56                           bool not_in_payload,
57                           std::string* device,
58                           bool* is_dynamic) const override {
59     auto dev =
60         GetPartitionDevice(partition_name, slot, current_slot_, not_in_payload);
61     if (!dev.has_value()) {
62       return false;
63     }
64     if (is_dynamic) {
65       *is_dynamic = dev->is_dynamic;
66     }
67     if (device) {
68       *device = dev->rw_device_path;
69     }
70     return true;
71   }
72 
GetPartitionDevice(const std::string & partition_name,BootControlInterface::Slot slot,std::string * device)73   bool GetPartitionDevice(const std::string& partition_name,
74                           BootControlInterface::Slot slot,
75                           std::string* device) const override {
76     return GetPartitionDevice(partition_name, slot, false, device, nullptr);
77   }
78 
IsSlotBootable(BootControlInterface::Slot slot)79   bool IsSlotBootable(BootControlInterface::Slot slot) const override {
80     return slot < num_slots_ && is_bootable_[slot];
81   }
82 
MarkSlotUnbootable(BootControlInterface::Slot slot)83   bool MarkSlotUnbootable(BootControlInterface::Slot slot) override {
84     if (slot >= num_slots_)
85       return false;
86     is_bootable_[slot] = false;
87     return true;
88   }
89 
SetActiveBootSlot(Slot slot)90   bool SetActiveBootSlot(Slot slot) override { return true; }
GetActiveBootSlot()91   Slot GetActiveBootSlot() override { return kInvalidSlot; }
92 
MarkBootSuccessfulAsync(base::Callback<void (bool)> callback)93   bool MarkBootSuccessfulAsync(base::Callback<void(bool)> callback) override {
94     // We run the callback directly from here to avoid having to setup a message
95     // loop in the test environment.
96     is_marked_successful_[GetCurrentSlot()] = true;
97     callback.Run(true);
98     return true;
99   }
100 
IsSlotMarkedSuccessful(Slot slot)101   bool IsSlotMarkedSuccessful(Slot slot) const override {
102     return slot < num_slots_ && is_marked_successful_[slot];
103   }
104 
105   // Setters
SetNumSlots(unsigned int num_slots)106   void SetNumSlots(unsigned int num_slots) {
107     num_slots_ = num_slots;
108     is_bootable_.resize(num_slots_, false);
109     is_marked_successful_.resize(num_slots_, false);
110     devices_.resize(num_slots_);
111   }
112 
SetCurrentSlot(BootControlInterface::Slot slot)113   void SetCurrentSlot(BootControlInterface::Slot slot) { current_slot_ = slot; }
114 
SetPartitionDevice(const std::string & partition_name,BootControlInterface::Slot slot,const std::string & device)115   void SetPartitionDevice(const std::string& partition_name,
116                           BootControlInterface::Slot slot,
117                           const std::string& device) {
118     DCHECK(slot < num_slots_);
119     devices_[slot][partition_name] = device;
120   }
121 
SetSlotBootable(BootControlInterface::Slot slot,bool bootable)122   void SetSlotBootable(BootControlInterface::Slot slot, bool bootable) {
123     DCHECK(slot < num_slots_);
124     is_bootable_[slot] = bootable;
125   }
126 
GetDynamicPartitionControl()127   DynamicPartitionControlInterface* GetDynamicPartitionControl() override {
128     return dynamic_partition_control_.get();
129   }
130 
131   std::optional<PartitionDevice> GetPartitionDevice(
132       const std::string& partition_name,
133       uint32_t slot,
134       uint32_t current_slot,
135       bool not_in_payload = false) const override {
136     if (slot >= devices_.size()) {
137       return {};
138     }
139     auto device_path = devices_[slot].find(partition_name);
140     if (device_path == devices_[slot].end()) {
141       return {};
142     }
143     PartitionDevice device;
144     device.is_dynamic = false;
145     device.rw_device_path = device_path->second;
146     device.readonly_device_path = device.rw_device_path;
147     return device;
148   }
149 
150  private:
151   BootControlInterface::Slot num_slots_{2};
152   BootControlInterface::Slot current_slot_{0};
153 
154   std::vector<bool> is_bootable_;
155   std::vector<bool> is_marked_successful_;
156   std::vector<std::map<std::string, std::string>> devices_;
157 
158   std::unique_ptr<DynamicPartitionControlInterface> dynamic_partition_control_;
159 
160   DISALLOW_COPY_AND_ASSIGN(FakeBootControl);
161 };
162 
163 }  // namespace chromeos_update_engine
164 
165 #endif  // UPDATE_ENGINE_COMMON_FAKE_BOOT_CONTROL_H_
166