Aktualizr
C++ SOTA Client
bootloader.cc
1 #include "bootloader.h"
2 
3 #include <fcntl.h>
4 #include <sys/reboot.h>
5 #include <sys/stat.h>
6 #include <unistd.h>
7 
8 #include <boost/filesystem.hpp>
9 
10 #include "storage/invstorage.h"
11 #include "utilities/exceptions.h"
12 #include "utilities/utils.h"
13 
14 Bootloader::Bootloader(BootloaderConfig config, INvStorage& storage) : config_(std::move(config)), storage_(storage) {
15  reboot_sentinel_ = config_.reboot_sentinel_dir / config_.reboot_sentinel_name;
16  reboot_command_ = config_.reboot_command;
17 
18  if (!Utils::createSecureDirectory(config_.reboot_sentinel_dir)) {
19  LOG_WARNING << "Could not create " << config_.reboot_sentinel_dir << " securely, reboot detection support disabled";
20  reboot_detect_supported_ = false;
21  return;
22  }
23 
24  reboot_detect_supported_ = true;
25 }
26 
27 void Bootloader::setBootOK() const {
28  std::string sink;
29  switch (config_.rollback_mode) {
30  case RollbackMode::kBootloaderNone:
31  break;
32  case RollbackMode::kUbootGeneric:
33  if (Utils::shell("fw_setenv bootcount 0", &sink) != 0) {
34  LOG_WARNING << "Failed resetting bootcount";
35  }
36  break;
37  case RollbackMode::kUbootMasked:
38  if (Utils::shell("fw_setenv bootcount 0", &sink) != 0) {
39  LOG_WARNING << "Failed resetting bootcount";
40  }
41  if (Utils::shell("fw_setenv upgrade_available 0", &sink) != 0) {
42  LOG_WARNING << "Failed resetting upgrade_available for u-boot";
43  }
44  break;
45  default:
47  }
48 }
49 
50 void Bootloader::updateNotify() const {
51  std::string sink;
52  switch (config_.rollback_mode) {
53  case RollbackMode::kBootloaderNone:
54  break;
55  case RollbackMode::kUbootGeneric:
56  if (Utils::shell("fw_setenv bootcount 0", &sink) != 0) {
57  LOG_WARNING << "Failed resetting bootcount";
58  }
59  if (Utils::shell("fw_setenv rollback 0", &sink) != 0) {
60  LOG_WARNING << "Failed resetting rollback flag";
61  }
62  break;
63  case RollbackMode::kUbootMasked:
64  if (Utils::shell("fw_setenv bootcount 0", &sink) != 0) {
65  LOG_WARNING << "Failed resetting bootcount";
66  }
67  if (Utils::shell("fw_setenv upgrade_available 1", &sink) != 0) {
68  LOG_WARNING << "Failed setting upgrade_available for u-boot";
69  }
70  if (Utils::shell("fw_setenv rollback 0", &sink) != 0) {
71  LOG_WARNING << "Failed resetting rollback flag";
72  }
73  break;
74  default:
76  }
77 }
78 
79 bool Bootloader::supportRebootDetection() const { return reboot_detect_supported_; }
80 
81 bool Bootloader::rebootDetected() const {
82  if (!reboot_detect_supported_) {
83  return false;
84  }
85 
86  // true if set in storage and no volatile flag
87 
88  bool sentinel_exists = boost::filesystem::exists(reboot_sentinel_);
89  bool need_reboot = false;
90 
91  storage_.loadNeedReboot(&need_reboot);
92 
93  return need_reboot && !sentinel_exists;
94 }
95 
96 void Bootloader::rebootFlagSet() {
97  if (!reboot_detect_supported_) {
98  return;
99  }
100 
101  // set in storage + volatile flag
102 
103  Utils::writeFile(reboot_sentinel_, std::string(), false); // empty file
104  storage_.storeNeedReboot();
105 }
106 
107 void Bootloader::rebootFlagClear() {
108  if (!reboot_detect_supported_) {
109  return;
110  }
111 
112  // clear in storage + volatile flag
113 
114  storage_.clearNeedReboot();
115  boost::filesystem::remove(reboot_sentinel_);
116 }
117 
118 void Bootloader::reboot(bool fake_reboot) {
119  if (fake_reboot) {
120  boost::filesystem::remove(reboot_sentinel_);
121  return;
122  }
123  if (setuid(0) != 0) {
124  LOG_ERROR << "Failed to set/verify a root user so cannot reboot system programmatically";
125  return;
126  }
127  sync();
128  if (system(reboot_command_.c_str()) != 0) {
129  LOG_ERROR << "Failed to execute the reboot command: " << reboot_command_;
130  }
131 }
NotImplementedException
Definition: exceptions.h:14
BootloaderConfig
Definition: config.h:156
INvStorage
Definition: invstorage.h:43