summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--partition_tools/Android.bp76
-rw-r--r--partition_tools/lpdump.cc126
-rw-r--r--partition_tools/lpflash.cc56
-rw-r--r--partition_tools/lpmake.cc178
4 files changed, 436 insertions, 0 deletions
diff --git a/partition_tools/Android.bp b/partition_tools/Android.bp
new file mode 100644
index 00000000..265ee666
--- /dev/null
+++ b/partition_tools/Android.bp
@@ -0,0 +1,76 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_defaults {
+ name: "lp_defaults",
+ cflags: [
+ "-Werror",
+ "-Wextra",
+ ],
+ target: {
+ linux_bionic: {
+ enabled: true,
+ },
+ },
+}
+
+cc_binary {
+ name: "lpdump",
+ defaults: ["lp_defaults"],
+ host_supported: true,
+ static_libs: [
+ "libbase",
+ "libcrypto",
+ "libcrypto_utils",
+ "liblog",
+ "liblp",
+ ],
+ srcs: [
+ "lpdump.cc",
+ ],
+}
+
+cc_binary {
+ name: "lpmake",
+ defaults: ["lp_defaults"],
+ host_supported: true,
+ static_libs: [
+ "libbase",
+ "libcrypto",
+ "libcrypto_utils",
+ "liblog",
+ "liblp",
+ ],
+ srcs: [
+ "lpmake.cc",
+ ],
+}
+
+cc_binary {
+ name: "lpflash",
+ defaults: ["lp_defaults"],
+ host_supported: true,
+ static_libs: [
+ "libbase",
+ "libcrypto",
+ "libcrypto_utils",
+ "liblog",
+ "liblp",
+ ],
+ srcs: [
+ "lpflash.cc",
+ ],
+}
diff --git a/partition_tools/lpdump.cc b/partition_tools/lpdump.cc
new file mode 100644
index 00000000..c54119a3
--- /dev/null
+++ b/partition_tools/lpdump.cc
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <getopt.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include <string>
+
+#include <android-base/parseint.h>
+#include <liblp/reader.h>
+
+using namespace android;
+using namespace android::fs_mgr;
+
+static int usage(int /* argc */, char* argv[]) {
+ fprintf(stderr,
+ "%s - command-line tool for dumping Android Logical Partition images.\n"
+ "\n"
+ "Usage:\n"
+ " %s [-s,--slot] file-or-device\n"
+ "\n"
+ "Options:\n"
+ " -s, --slot=N Slot number or suffix.\n",
+ argv[0], argv[0]);
+ return EX_USAGE;
+}
+
+static std::string BuildAttributeString(uint32_t attrs) {
+ return (attrs & LP_PARTITION_ATTR_READONLY) ? "readonly" : "none";
+}
+
+static bool IsBlockDevice(const char* file) {
+ struct stat s;
+ return !stat(file, &s) && S_ISBLK(s.st_mode);
+}
+
+int main(int argc, char* argv[]) {
+ struct option options[] = {
+ { "slot", required_argument, nullptr, 's' },
+ { "help", no_argument, nullptr, 'h' },
+ { nullptr, 0, nullptr, 0 },
+ };
+
+ int rv;
+ int index;
+ uint32_t slot = 0;
+ while ((rv = getopt_long_only(argc, argv, "s:h", options, &index)) != -1) {
+ switch (rv) {
+ case 'h':
+ return usage(argc, argv);
+ case 's':
+ if (!android::base::ParseUint(optarg, &slot)) {
+ slot = SlotNumberForSlotSuffix(optarg);
+ }
+ break;
+ }
+ }
+
+ if (optind >= argc) {
+ return usage(argc, argv);
+ }
+ const char* file = argv[optind++];
+
+ std::unique_ptr<LpMetadata> pt;
+ if (IsBlockDevice(file)) {
+ pt = ReadMetadata(file, slot);
+ } else {
+ pt = ReadFromImageFile(file);
+ }
+ if (!pt) {
+ fprintf(stderr, "Failed to read metadata.\n");
+ return EX_NOINPUT;
+ }
+
+ printf("Metadata version: %u.%u\n", pt->header.major_version, pt->header.minor_version);
+ printf("Metadata size: %u bytes\n", pt->header.header_size + pt->header.tables_size);
+ printf("Metadata max size: %u bytes\n", pt->geometry.metadata_max_size);
+ printf("Metadata slot count: %u\n", pt->geometry.metadata_slot_count);
+ printf("First logical sector: %" PRIu64 "\n", pt->geometry.first_logical_sector);
+ printf("Last logical sector: %" PRIu64 "\n", pt->geometry.last_logical_sector);
+ printf("Partition table:\n");
+ printf("------------------------\n");
+
+ for (const auto& partition : pt->partitions) {
+ std::string name = GetPartitionName(partition);
+ std::string guid = GetPartitionGuid(partition);
+ printf(" Name: %s\n", name.c_str());
+ printf(" GUID: %s\n", guid.c_str());
+ printf(" Attributes: %s\n", BuildAttributeString(partition.attributes).c_str());
+ printf(" Extents:\n");
+ uint64_t first_sector = 0;
+ for (size_t i = 0; i < partition.num_extents; i++) {
+ const LpMetadataExtent& extent = pt->extents[partition.first_extent_index + i];
+ printf(" %" PRIu64 " .. %" PRIu64 " ", first_sector,
+ (first_sector + extent.num_sectors - 1));
+ first_sector += extent.num_sectors;
+ if (extent.target_type == LP_TARGET_TYPE_LINEAR) {
+ printf("linear %" PRIu64, extent.target_data);
+ } else if (extent.target_type == LP_TARGET_TYPE_ZERO) {
+ printf("zero");
+ }
+ printf("\n");
+ }
+ printf("------------------------\n");
+ }
+
+ return EX_OK;
+}
diff --git a/partition_tools/lpflash.cc b/partition_tools/lpflash.cc
new file mode 100644
index 00000000..83e5008d
--- /dev/null
+++ b/partition_tools/lpflash.cc
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <sysexits.h>
+
+#include <string>
+
+#include <liblp/reader.h>
+#include <liblp/writer.h>
+
+using namespace android;
+using namespace android::fs_mgr;
+
+/* Prints program usage to |where|. */
+static int usage(int /* argc */, char* argv[]) {
+ fprintf(stderr,
+ "%s - command-line tool for dumping Android Logical Partition images.\n"
+ "\n"
+ "Usage:\n"
+ " %s [block-device] [img-file]\n",
+ argv[0], argv[0]);
+ return EX_USAGE;
+}
+
+int main(int argc, char* argv[]) {
+ if (argc != 3) {
+ return usage(argc, argv);
+ }
+
+ std::unique_ptr<LpMetadata> pt = ReadFromImageFile(argv[2]);
+ if (!pt) {
+ printf("Failed to read image file.\n");
+ return EX_NOINPUT;
+ }
+
+ if (!WritePartitionTable(argv[1], *pt.get(), SyncMode::Flash, 0)) {
+ printf("Failed to flash partition table.\n");
+ return EX_SOFTWARE;
+ }
+ printf("Successfully flashed partition table.\n");
+ return EX_OK;
+}
diff --git a/partition_tools/lpmake.cc b/partition_tools/lpmake.cc
new file mode 100644
index 00000000..016b32d7
--- /dev/null
+++ b/partition_tools/lpmake.cc
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <getopt.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <sysexits.h>
+
+#include <memory>
+
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
+#include <liblp/builder.h>
+#include <liblp/writer.h>
+
+using namespace android;
+using namespace android::fs_mgr;
+
+/* Prints program usage to |where|. */
+static int usage(int /* argc */, char* argv[]) {
+ fprintf(stderr,
+ "%s - command-line tool for creating Android Logical Partition images.\n"
+ "\n"
+ "Usage:\n"
+ " %s [options]\n"
+ "\n"
+ "Required options:\n"
+ " -d,--device-size=SIZE Size of the block device for logical partitions.\n"
+ " -m,--metadata-size=SIZE Maximum size to reserve for partition metadata.\n"
+ " -s,--metadata-slots=COUNT Number of slots to store metadata copies.\n"
+ " -p,--partition=DATA Add a partition given the data, see below.\n"
+ " -o,--output=FILE Output file.\n"
+ "\n"
+ "Partition format:\n"
+ " <name>:<guid>:<attributes>:<size>\n"
+ " Attrs must be 'none' or 'readonly'.\n",
+ argv[0], argv[0]);
+ return EX_USAGE;
+}
+
+int main(int argc, char* argv[]) {
+ struct option options[] = {
+ { "device-size", required_argument, nullptr, 'd' },
+ { "metadata-size", required_argument, nullptr, 'm' },
+ { "metadata-slots", required_argument, nullptr, 's' },
+ { "partition", required_argument, nullptr, 'p' },
+ { "output", required_argument, nullptr, 'o' },
+ { "help", no_argument, nullptr, 'h' },
+ { nullptr, 0, nullptr, 0 },
+ };
+
+ uint64_t blockdevice_size = 0;
+ uint32_t metadata_size = 0;
+ uint32_t metadata_slots = 0;
+ std::string output_path;
+ std::vector<std::string> partitions;
+
+ int rv;
+ int index;
+ while ((rv = getopt_long_only(argc, argv, "d:m:s:p:o:h", options, &index)) != -1) {
+ switch (rv) {
+ case 'h':
+ return usage(argc, argv);
+ case 'd':
+ if (!android::base::ParseUint(optarg, &blockdevice_size)) {
+ fprintf(stderr, "Invalid argument to --device-size.\n");
+ return EX_USAGE;
+ }
+ break;
+ case 'm':
+ if (!android::base::ParseUint(optarg, &metadata_size)) {
+ fprintf(stderr, "Invalid argument to --metadata-size.\n");
+ return EX_USAGE;
+ }
+ break;
+ case 's':
+ if (!android::base::ParseUint(optarg, &metadata_slots)) {
+ fprintf(stderr, "Invalid argument to --metadata-slots.\n");
+ return EX_USAGE;
+ }
+ break;
+ case 'p':
+ partitions.push_back(optarg);
+ break;
+ case 'o':
+ output_path = optarg;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Check for empty arguments so we can print a more helpful message rather
+ // than error on each individual missing argument.
+ if (optind == 1) {
+ return usage(argc, argv);
+ }
+
+ if (!blockdevice_size) {
+ fprintf(stderr, "--device-size needs more than 0 bytes of disk space.\n");
+ return EX_USAGE;
+ }
+ if (!metadata_size) {
+ fprintf(stderr, "--metadata-size must be more than 0 bytes.\n");
+ return EX_USAGE;
+ }
+ if (!metadata_slots) {
+ fprintf(stderr, "--metadata-slots must be more than 0.\n");
+ return EX_USAGE;
+ }
+ if (output_path.empty()) {
+ fprintf(stderr, "--output must specify a valid path.\n");
+ return EX_USAGE;
+ }
+ if (partitions.empty()) {
+ fprintf(stderr, "Partition table must have at least one entry.\n");
+ return EX_USAGE;
+ }
+
+ std::unique_ptr<MetadataBuilder> builder =
+ MetadataBuilder::New(blockdevice_size, metadata_size, metadata_slots);
+
+ for (const auto& partition_info : partitions) {
+ std::vector<std::string> parts = android::base::Split(partition_info, ":");
+ if (parts.size() != 4) {
+ fprintf(stderr, "Partition info has invalid formatting.\n");
+ return EX_USAGE;
+ }
+
+ std::string name = parts[0];
+ if (!name.length()) {
+ fprintf(stderr, "Partition must have a valid name.\n");
+ return EX_USAGE;
+ }
+
+ uint64_t size;
+ if (!android::base::ParseUint(parts[3].c_str(), &size)) {
+ fprintf(stderr, "Partition must have a valid size.\n");
+ return EX_USAGE;
+ }
+
+ uint32_t attribute_flags = 0;
+ std::string attributes = parts[2];
+ if (attributes == "readonly") {
+ attribute_flags |= LP_PARTITION_ATTR_READONLY;
+ } else if (attributes != "none") {
+ fprintf(stderr, "Attribute not recognized: %s\n", attributes.c_str());
+ return EX_USAGE;
+ }
+
+ Partition* partition = builder->AddPartition(name, parts[1], attribute_flags);
+ if (!builder->GrowPartition(partition, size)) {
+ fprintf(stderr, "Not enough space on device for partition %s with size %" PRIu64 "\n",
+ name.c_str(), size);
+ return EX_SOFTWARE;
+ }
+ }
+
+ std::unique_ptr<LpMetadata> metadata = builder->Export();
+ if (!WriteToImageFile(output_path.c_str(), *metadata.get())) {
+ return EX_CANTCREAT;
+ }
+
+ return EX_OK;
+}