update_engine: Support full update on MTD devices
This CL fleshes out the MTD and UBI FileDescriptor subclasses and
modifies the utility functions that deal with device name and partition
number to support NAND scheme.
BUG=brillo:45
BUG=brillo:43
TEST=unittest on rambi
TEST=cros flash to storm_nand, reboot, make sure rootdev -s says something
different. Then repeat and make sure that another device is reported.
TEST=If the above was done with verified-rootfs, repeat with
non-verified image.
Change-Id: I31b9a00642f9a7ff67ea51a4cf3dc31b86095e98
Reviewed-on: https://chromium-review.googlesource.com/257192
Reviewed-by: Nam Nguyen <namnguyen@chromium.org>
Commit-Queue: Nam Nguyen <namnguyen@chromium.org>
Tested-by: Nam Nguyen <namnguyen@chromium.org>
diff --git a/delta_performer.cc b/delta_performer.cc
index 9392af3..28f61b8 100644
--- a/delta_performer.cc
+++ b/delta_performer.cc
@@ -60,15 +60,30 @@
namespace {
const int kUpdateStateOperationInvalid = -1;
const int kMaxResumedUpdateFailures = 10;
+#if USE_MTD
+const int kUbiVolumeAttachTimeout = 5 * 60;
+#endif
FileDescriptorPtr CreateFileDescriptor(const char* path) {
FileDescriptorPtr ret;
#if USE_MTD
- if (UbiFileDescriptor::IsUbi(path)) {
- ret.reset(new UbiFileDescriptor);
+ if (strstr(path, "/dev/ubi") == path) {
+ if (!UbiFileDescriptor::IsUbi(path)) {
+ // The volume might not have been attached at boot time.
+ int volume_no;
+ if (utils::SplitPartitionName(path, nullptr, &volume_no)) {
+ utils::TryAttachingUbiVolume(volume_no, kUbiVolumeAttachTimeout);
+ }
+ }
+ if (UbiFileDescriptor::IsUbi(path)) {
+ LOG(INFO) << path << " is a UBI device.";
+ ret.reset(new UbiFileDescriptor);
+ }
} else if (MtdFileDescriptor::IsMtd(path)) {
+ LOG(INFO) << path << " is an MTD device.";
ret.reset(new MtdFileDescriptor);
} else {
+ LOG(INFO) << path << " is not an MTD nor a UBI device.";
#endif
ret.reset(new EintrSafeFileDescriptor);
#if USE_MTD
@@ -81,8 +96,15 @@
// and sets *err to 0. On failure, sets *err to errno and returns nullptr.
FileDescriptorPtr OpenFile(const char* path, int* err) {
FileDescriptorPtr fd = CreateFileDescriptor(path);
- // TODO(namnguyen): If we're working with MTD or UBI, DO NOT use O_RDWR.
- if (!fd->Open(path, O_RDWR, 000)) {
+ int mode = O_RDWR;
+#if USE_MTD
+ // On NAND devices, we can either read, or write, but not both. So here we
+ // use O_WRONLY.
+ if (UbiFileDescriptor::IsUbi(path) || MtdFileDescriptor::IsMtd(path)) {
+ mode = O_WRONLY;
+ }
+#endif
+ if (!fd->Open(path, mode, 000)) {
*err = errno;
PLOG(ERROR) << "Unable to open file " << path;
return nullptr;