Merge "lpmake: Add an option for including partition data in sparse images."
diff --git a/partition_tools/README.md b/partition_tools/README.md
index 0993ce2..44c10e4 100644
--- a/partition_tools/README.md
+++ b/partition_tools/README.md
@@ -19,7 +19,8 @@
 * `--alignment=N` - By default, lpmake will align partitions to 1MiB boundaries. However, an alternate alignment can be specified if desired. This is useful for devices with a minimum I/O request size where mis-aligned partition boundaries could be a performance issue.
 * `--alignment-offset=N` - In some cases, the "super" partition is misaligned within its parent block device. This offset can be used to correct for that.
 * `--sparse` - If set, the output image will be in sparse format for flashing with fastboot. Otherwise, by default, the image will be a minimal format usable with lpdump and lpflash.
-* `-b,--block-size=N` - When writing sparse files, the device may require a specific block size. That block size can be specified here. The alignment must be a multiple of the block size. By default the block size is 4096.
+* `-b,--block-size=N` - When writing a sparse image, the device may require a specific block size. That block size can be specified here. The alignment must be a multiple of the block size. By default the block size is 4096.
+* `-i,--image=[NAME=FILE]` - When writing a sparse image, include the contents of FILE as the data for the partition named NAME. The file can be a normal file or a sparse image, but the destination size must be less than or equal to the partition size. This option is only available when creating sparse images.
 
 Example usage. This specifies a 10GB super partition for an A/B device, with a single 64MiB "cache" partition.
 
@@ -28,7 +29,8 @@
        --metadata-size 65536     \
        --metadata-slots 2        \
        -o /tmp/super.img         \
-       -p "cache:2da85788-f0e1-4fda-9ee7-e5177eab184b:none:67108864"
+       -p "cache:2da85788-f0e1-4fda-9ee7-e5177eab184b:none:67108864" \
+       -i "cache=out/target/hikey960/cache.img"
 ```
 
 ## lpdump
diff --git a/partition_tools/lpmake.cc b/partition_tools/lpmake.cc
index 2513344..9ba688d 100644
--- a/partition_tools/lpmake.cc
+++ b/partition_tools/lpmake.cc
@@ -49,6 +49,9 @@
             "  -a,--alignment=N              Optimal partition alignment in bytes.\n"
             "  -O,--alignment-offset=N       Alignment offset in bytes to device parent.\n"
             "  -S,--sparse                   Output a sparse image for fastboot.\n"
+            "  -i,--image=PARTITION=FILE     If building a sparse image for fastboot, include\n"
+            "                                the given file (or sparse file) as initial data for\n"
+            "                                the named partition.\n"
             "\n"
             "Partition data format:\n"
             "  <name>:<guid>:<attributes>:<size>\n"
@@ -69,6 +72,7 @@
         { "alignment", required_argument, nullptr, 'a' },
         { "sparse", no_argument, nullptr, 'S' },
         { "block-size", required_argument, nullptr, 'b' },
+        { "image", required_argument, nullptr, 'i' },
         { nullptr, 0, nullptr, 0 },
     };
 
@@ -80,6 +84,7 @@
     uint32_t block_size = 4096;
     std::string output_path;
     std::vector<std::string> partitions;
+    std::map<std::string, std::string> images;
     bool output_sparse = false;
 
     int rv;
@@ -133,6 +138,20 @@
                     return EX_USAGE;
                 }
                 break;
+            case 'i':
+            {
+                char* separator = strchr(optarg, '=');
+                if (!separator || separator == optarg || !strlen(separator + 1)) {
+                    fprintf(stderr, "Expected PARTITION=FILE.\n");
+                    return EX_USAGE;
+                }
+                *separator = '\0';
+
+                std::string partition_name(optarg);
+                std::string file(separator + 1);
+                images[partition_name] = file;
+                break;
+            }
             default:
                 break;
         }
@@ -164,6 +183,10 @@
         fprintf(stderr, "Partition table must have at least one entry.\n");
         return EX_USAGE;
     }
+    if (!images.empty() && !output_sparse) {
+        fprintf(stderr, "Cannot write partition data for non-sparse images.\n");
+        return EX_USAGE;
+    }
 
     BlockDeviceInfo device_info(blockdevice_size, alignment, alignment_offset);
 
@@ -208,7 +231,7 @@
 
     std::unique_ptr<LpMetadata> metadata = builder->Export();
     if (output_sparse) {
-        if (!WriteToSparseFile(output_path.c_str(), *metadata.get(), block_size)) {
+        if (!WriteToSparseFile(output_path.c_str(), *metadata.get(), block_size, images)) {
             return EX_CANTCREAT;
         }
     } else if (!WriteToImageFile(output_path.c_str(), *metadata.get())) {