| // Copyright 2022 The ChromiumOS Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "brillo/blkdev_utils/ufs.h" | |
| #include <base/bits.h> | |
| #include <base/files/file_path.h> | |
| #include <base/files/file_util.h> | |
| #include <base/logging.h> | |
| #include <brillo/brillo_export.h> | |
| #include <brillo/process/process.h> | |
| namespace brillo { | |
| namespace { | |
| constexpr char kDevToController[] = "../../../../../"; | |
| constexpr char kUnitDescriptorDir[] = "device/unit_descriptor"; | |
| constexpr uint32_t kUFSPurgeTimeoutSecPerGB = 5; | |
| constexpr uint64_t kGiB = 1024 * 1024 * 1024; | |
| constexpr const char kFactoryUfsTool[] = "factory_ufs"; | |
| } // namespace | |
| bool IsUfs(const base::FilePath& dev_node) { | |
| base::FilePath unit_descriptor_node = dev_node.Append(kUnitDescriptorDir); | |
| return base::DirectoryExists(unit_descriptor_node); | |
| } | |
| base::FilePath UfsSysfsToControllerNode(const base::FilePath& dev_node) { | |
| if (!base::PathExists(dev_node)) { | |
| PLOG(ERROR) << "Node doesn't exists: " << dev_node; | |
| return base::FilePath(); | |
| } | |
| base::FilePath path = dev_node.Append(kDevToController); | |
| base::FilePath normalized_path; | |
| normalized_path = base::MakeAbsoluteFilePath(path); | |
| if (normalized_path.empty()) { | |
| LOG(ERROR) << "Couldn't normalize: " << path; | |
| return base::FilePath(); | |
| } | |
| return normalized_path; | |
| } | |
| bool Ufs::SupportPhysicalErasure() const { | |
| return true; | |
| } | |
| LogicalErasureIoctl Ufs::GetLogicalErasureIoctlType() const { | |
| return LogicalErasureIoctl::blkdiscard; | |
| } | |
| bool Ufs::PhysicalErasure(const base::FilePath& device_path, | |
| const uint64_t device_length) const { | |
| int purge_timeout_sec = base::bits::AlignUp(device_length, kGiB) / kGiB * | |
| kUFSPurgeTimeoutSecPerGB; | |
| brillo::ProcessImpl factory_ufs; | |
| factory_ufs.SetSearchPath(true); | |
| factory_ufs.AddArg(kFactoryUfsTool); | |
| factory_ufs.AddArg("purge"); | |
| factory_ufs.AddIntOption("-t", purge_timeout_sec); | |
| factory_ufs.RedirectUsingMemory(STDOUT_FILENO); | |
| factory_ufs.RedirectUsingMemory(STDERR_FILENO); | |
| LOG(INFO) << "Running `factory_ufs purge` with timeout set to " | |
| << purge_timeout_sec << " seconds ..."; | |
| int factory_ufs_ret = factory_ufs.Run(); | |
| if (factory_ufs_ret) { | |
| LOG(ERROR) << "Failed to run `factory_ufs purge` (Error Code: " | |
| << factory_ufs_ret << "):\n" | |
| << factory_ufs.GetOutputString(STDERR_FILENO); | |
| } else { | |
| LOG(INFO) << factory_ufs.GetOutputString(STDOUT_FILENO); | |
| } | |
| return factory_ufs_ret == 0; | |
| } | |
| } // namespace brillo |