blob: 249cde756085a87a86da1201a51595edabf54ad8 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/storage/factory/factoryfs/format.h"
#include <block-client/cpp/block-device.h>
#include <block-client/cpp/client.h>
#include <fs/trace.h>
#include <storage/buffer/owned_vmoid.h>
#include "src/storage/factory/factoryfs/factoryfs.h"
#include "src/storage/factory/factoryfs/mkfs.h"
#include "src/storage/factory/factoryfs/superblock.h"
namespace factoryfs {
namespace {
// Take the contents of the filesystem, generated in-memory, and transfer
// them to the underlying device.
zx_status_t WriteFilesystemToDisk(block_client::BlockDevice* device, const Superblock& superblock,
uint32_t block_size) {
zx::vmo vmo;
zx_status_t status = zx::vmo::create(kFactoryfsBlockSize, 0, &vmo);
if (status != ZX_OK) {
return status;
}
storage::OwnedVmoid vmoid;
status = device->BlockAttachVmo(vmo, &vmoid.GetReference(device));
if (status != ZX_OK) {
return status;
}
// Write the superblock.
status = vmo.write(&superblock, 0, kFactoryfsBlockSize);
if (status != ZX_OK) {
FS_TRACE_INFO("\nfactoryfs: error writing superblock block\n");
return status;
}
fuchsia_hardware_block_BlockInfo block_info;
status = device->BlockGetInfo(&block_info);
if (status != ZX_OK) {
FS_TRACE_ERROR("factoryfs: cannot acquire block info: %d\n", status);
return status;
}
block_fifo_request_t request = {};
// write superblock.
request.opcode = BLOCKIO_WRITE;
request.vmoid = vmoid.get();
request.length = FsToDeviceBlocks(1, block_info.block_size);
request.vmo_offset = FsToDeviceBlocks(0, block_info.block_size);
request.dev_offset = FsToDeviceBlocks(0, block_info.block_size);
return device->FifoTransaction(&request, 1);
}
} // namespace
zx_status_t FormatFilesystem(block_client::BlockDevice* device) {
zx_status_t status;
fuchsia_hardware_block_BlockInfo block_info = {};
status = device->BlockGetInfo(&block_info);
if (status != ZX_OK) {
FS_TRACE_ERROR("factoryfs: cannot acquire block info: %d\n", status);
return status;
}
if (block_info.flags & BLOCK_FLAG_READONLY) {
FS_TRACE_ERROR("factoryfs: cannot format read-only device\n");
return ZX_ERR_ACCESS_DENIED;
}
if (block_info.block_size == 0 || block_info.block_count == 0) {
return ZX_ERR_NO_SPACE;
}
if (kFactoryfsBlockSize % block_info.block_size != 0) {
return ZX_ERR_IO_INVALID;
}
uint64_t blocks = (block_info.block_size * block_info.block_count) / kFactoryfsBlockSize;
Superblock superblock;
InitializeSuperblock(blocks, &superblock);
status = CheckSuperblock(&superblock);
ZX_DEBUG_ASSERT(status == ZX_OK);
status = WriteFilesystemToDisk(device, superblock, block_info.block_size);
if (status != ZX_OK) {
FS_TRACE_ERROR("factoryfs: Failed to write to disk: %d\n", status);
return status;
}
FS_TRACE_DEBUG("factoryfs: mkfs success\n");
return ZX_OK;
}
} // namespace factoryfs