[paver] Add support for non-managed NAND partitions.
On several NAND parts, we have NAND partitions managed by a special
skip-block algorithm, rather than an FTL. These do not expose a block
IOCTL interface, but rather a different
Change-Id: Icb6bbdcb151b1127f95509aee55683db52ab80b6
Tested: TODO: Paved ZIRCON-R to a gauss.
diff --git a/system/uapp/disk-pave/device-partitioner.cpp b/system/uapp/disk-pave/device-partitioner.cpp
index 60cb71f..7de2605 100644
--- a/system/uapp/disk-pave/device-partitioner.cpp
+++ b/system/uapp/disk-pave/device-partitioner.cpp
@@ -55,7 +55,8 @@
return fbl::move(device_partitioner);
}
#elif defined(__aarch64__)
- if (FixedDevicePartitioner::Initialize(&device_partitioner) == ZX_OK) {
+ if ((NandDevicePartitioner::Initialize(&device_partitioner) == ZX_OK) ||
+ (FixedDevicePartitioner::Initialize(&device_partitioner) == ZX_OK)) {
return fbl::move(device_partitioner);
}
#endif
@@ -429,7 +430,7 @@
}
return gpt_->AddPartition(name, type, minimum_size_bytes,
- optional_reserve_bytes, out_fd);
+ optional_reserve_bytes, out_fd);
}
bool EfiDevicePartitioner::FilterZirconPartition(const block_info_t& info,
@@ -546,7 +547,7 @@
return status;
}
- gpt_device_t *gpt = gpt_partitioner->GetGpt();
+ gpt_device_t* gpt = gpt_partitioner->GetGpt();
if (!is_cros(gpt)) {
return ZX_ERR_NOT_FOUND;
}
@@ -600,7 +601,7 @@
return ZX_ERR_NOT_SUPPORTED;
}
return gpt_->AddPartition(name, type, minimum_size_bytes,
- optional_reserve_bytes, out_fd);
+ optional_reserve_bytes, out_fd);
}
zx_status_t CrosDevicePartitioner::FindPartition(Partition partition_type,
@@ -729,7 +730,7 @@
}
/*====================================================*
- * NON-GPT *
+ * FIXED PARTITION MAP *
*====================================================*/
zx_status_t FixedDevicePartitioner::Initialize(fbl::unique_ptr<DevicePartitioner>* partitioner) {
@@ -739,7 +740,7 @@
}
zx_status_t FixedDevicePartitioner::FindPartition(Partition partition_type,
- fbl::unique_fd* out_fd) const {
+ fbl::unique_fd* out_fd) const {
uint8_t type[GPT_GUID_LEN];
switch (partition_type) {
@@ -776,7 +777,7 @@
}
zx_status_t FixedDevicePartitioner::GetBlockInfo(const fbl::unique_fd& block_fd,
- block_info_t* block_info) const {
+ block_info_t* block_info) const {
ssize_t r;
if ((r = ioctl_block_get_info(block_fd.get(), block_info) < 0)) {
return ZX_ERR_IO;
@@ -784,4 +785,65 @@
return ZX_OK;
}
+/*====================================================*
+ * NAND SPECIFIC *
+ *====================================================*/
+
+zx_status_t NandDevicePartitioner::Initialize(fbl::unique_ptr<DevicePartitioner>* partitioner) {
+ return ZX_ERR_NOT_SUPPORTED;
+ // TODO: Check if this is a NAND part.
+#if 0
+ LOG("Successfully intitialized NandDevicePartitioner Device Partitioner\n");
+ *partitioner = fbl::move(WrapUnique(new NandDevicePartitioner));
+#endif
+}
+
+zx_status_t NandDevicePartitioner::FindPartition(Partition partition_type,
+ fbl::unique_fd* out_fd) const {
+ uint8_t type[GPT_GUID_LEN];
+
+ switch (partition_type) {
+ case Partition::kZirconA: {
+ const uint8_t zircon_a_type[GPT_GUID_LEN] = GUID_ZIRCON_A_VALUE;
+ memcpy(type, zircon_a_type, GPT_GUID_LEN);
+ break;
+ }
+ case Partition::kZirconB: {
+ const uint8_t zircon_b_type[GPT_GUID_LEN] = GUID_ZIRCON_B_VALUE;
+ memcpy(type, zircon_b_type, GPT_GUID_LEN);
+ break;
+ }
+ case Partition::kZirconR: {
+ const uint8_t zircon_r_type[GPT_GUID_LEN] = GUID_ZIRCON_R_VALUE;
+ memcpy(type, zircon_r_type, GPT_GUID_LEN);
+ break;
+ }
+ case Partition::kFuchsiaVolumeManager: {
+ const uint8_t fvm_type[GPT_GUID_LEN] = GUID_FVM_VALUE;
+ memcpy(type, fvm_type, GPT_GUID_LEN);
+ out_fd->reset(open_partition(nullptr, type, ZX_SEC(5), nullptr));
+ if (!out_fd) {
+ return ZX_ERR_NOT_FOUND;
+ }
+ return ZX_OK;
+ }
+ default:
+ ERROR("partition_type is invalid!\n");
+ return ZX_ERR_NOT_SUPPORTED;
+ }
+
+ // TODO: Find skip-block partition.
+ return ZX_ERR_NOT_SUPPORTED;
+}
+
+zx_status_t NandDevicePartitioner::GetBlockInfo(const fbl::unique_fd& block_fd,
+ block_info_t* block_info) const {
+ skip_block_partition_info_t info;
+ ssize_t r;
+ if ((r = ioctl_skip_block_get_info(block_fd.get(), block_info) < 0)) {
+ return ZX_ERR_IO;
+ }
+ return ZX_OK;
+}
+
} // namespace paver
diff --git a/system/uapp/disk-pave/device-partitioner.h b/system/uapp/disk-pave/device-partitioner.h
index af630b9..122a10b 100644
--- a/system/uapp/disk-pave/device-partitioner.h
+++ b/system/uapp/disk-pave/device-partitioner.h
@@ -207,4 +207,33 @@
FixedDevicePartitioner() {}
};
+// DevicePartitioner implementation for devices which have fixed partition maps, but do no expose a
+// block device interface. Instead they expose devices with skip-block IOCTL interfaces. Like the
+// FixedDevicePartitioner, it will not attempt to write a partition map of any kind to the device.
+// Assumes standardized partition layout structure (e.g. ZIRCON-A, ZIRCON-B,
+// ZIRCON-R).
+class NandDevicePartitioner : public DevicePartitioner {
+public:
+ static zx_status_t Initialize(fbl::unique_ptr<DevicePartitioner>* partitioner);
+
+ bool IsCros() const override { return false; }
+
+ zx_status_t AddPartition(Partition partition_type, fbl::unique_fd* out_fd) override {
+ return ZX_ERR_NOT_SUPPORTED;
+ }
+
+ zx_status_t FindPartition(Partition partition_type, fbl::unique_fd* out_fd) const override;
+
+ zx_status_t FinalizePartition(Partition unused) override { return ZX_OK; }
+
+ zx_status_t WipePartitions(const fbl::Vector<Partition>& partitions) override {
+ return ZX_ERR_NOT_SUPPORTED;
+ }
+
+ zx_status_t GetBlockInfo(const fbl::unique_fd& block_fd,
+ block_info_t* block_info) const override;
+
+private:
+ NandDevicePartitioner() {}
+};
} // namespace paver