Add a new "virtual disk" feature.

It's extremely difficult to test storage related logic on devices
that don't have physical SD card slots.  So to support better
debugging and testing, add a new "virtual disk" feature which mounts
a 512MB file through loop device.

It relies on the kernel having the "loop.max_part" value set to
something other than 0 via the boot command line, since that allows
all the existing partition logic to fall into place.

Bug: 34903607
Test: builds, boots, virtual disk works
Change-Id: I04c5b33e37319d867542985a56b7999a9b7cf35d
diff --git a/Disk.cpp b/Disk.cpp
index 6562d96..8e58be0 100644
--- a/Disk.cpp
+++ b/Disk.cpp
@@ -47,8 +47,10 @@
 static const char* kSgdiskPath = "/system/bin/sgdisk";
 static const char* kSgdiskToken = " \t\n";
 
+static const char* kSysfsLoopMaxMinors = "/sys/module/loop/parameters/max_part";
 static const char* kSysfsMmcMaxMinors = "/sys/module/mmcblk/parameters/perdev_minors";
 
+static const unsigned int kMajorBlockLoop = 7;
 static const unsigned int kMajorBlockScsiA = 8;
 static const unsigned int kMajorBlockScsiB = 65;
 static const unsigned int kMajorBlockScsiC = 66;
@@ -229,6 +231,10 @@
 
     unsigned int majorId = major(mDevice);
     switch (majorId) {
+    case kMajorBlockLoop: {
+        mLabel = "Virtual";
+        break;
+    }
     case kMajorBlockScsiA: case kMajorBlockScsiB: case kMajorBlockScsiC: case kMajorBlockScsiD:
     case kMajorBlockScsiE: case kMajorBlockScsiF: case kMajorBlockScsiG: case kMajorBlockScsiH:
     case kMajorBlockScsiI: case kMajorBlockScsiJ: case kMajorBlockScsiK: case kMajorBlockScsiL:
@@ -534,6 +540,14 @@
     // Figure out maximum partition devices supported
     unsigned int majorId = major(mDevice);
     switch (majorId) {
+    case kMajorBlockLoop: {
+        std::string tmp;
+        if (!ReadFileToString(kSysfsLoopMaxMinors, &tmp)) {
+            LOG(ERROR) << "Failed to read max minors";
+            return -errno;
+        }
+        return atoi(tmp.c_str());
+    }
     case kMajorBlockScsiA: case kMajorBlockScsiB: case kMajorBlockScsiC: case kMajorBlockScsiD:
     case kMajorBlockScsiE: case kMajorBlockScsiF: case kMajorBlockScsiG: case kMajorBlockScsiH:
     case kMajorBlockScsiI: case kMajorBlockScsiJ: case kMajorBlockScsiK: case kMajorBlockScsiL: