|  | // Copyright 2019 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 <gpt/gpt.h> | 
|  | #include <gpt/guid.h> | 
|  |  | 
|  | namespace gpt { | 
|  |  | 
|  | #define GUID_NAMETAB(name) \ | 
|  | GuidProperties(GUID_##name##_NAME, uuid::Uuid(GUID_##name##_VALUE), PartitionScheme::kLegacy) | 
|  |  | 
|  | // clang-format off | 
|  | std::array<GuidProperties, kKnownGuidEntries> const KnownGuid::nametab_ = {{ | 
|  | // Legacy GUID definitions - each entry has its own type GUID. | 
|  | GUID_NAMETAB(EMPTY), | 
|  | GUID_NAMETAB(EFI), | 
|  | GUID_NAMETAB(SYSTEM), | 
|  | GUID_NAMETAB(DATA), | 
|  | GUID_NAMETAB(INSTALL), | 
|  | GUID_NAMETAB(BLOB), | 
|  | GUID_NAMETAB(FVM), | 
|  | GUID_NAMETAB(ZIRCON_A), | 
|  | GUID_NAMETAB(ZIRCON_B), | 
|  | GUID_NAMETAB(ZIRCON_R), | 
|  | GUID_NAMETAB(SYS_CONFIG), | 
|  | GUID_NAMETAB(FACTORY_CONFIG), | 
|  | GUID_NAMETAB(BOOTLOADER), | 
|  | GUID_NAMETAB(TEST), | 
|  | GUID_NAMETAB(VBMETA_A), | 
|  | GUID_NAMETAB(VBMETA_B), | 
|  | GUID_NAMETAB(VBMETA_R), | 
|  | GUID_NAMETAB(ABR_META), | 
|  | GUID_NAMETAB(CROS_KERNEL), | 
|  | GUID_NAMETAB(CROS_ROOTFS), | 
|  | GUID_NAMETAB(CROS_RESERVED), | 
|  | GUID_NAMETAB(CROS_FIRMWARE), | 
|  | GUID_NAMETAB(CROS_DATA), | 
|  | GUID_NAMETAB(BIOS), | 
|  | GUID_NAMETAB(EMMC_BOOT1), | 
|  | GUID_NAMETAB(EMMC_BOOT2), | 
|  | GUID_NAMETAB(LINUX_FILESYSTEM_DATA), | 
|  |  | 
|  | // New GUID definitions - slotted partitions share a type GUID. | 
|  | GuidProperties(GPT_BOOTLOADER_A_NAME, GPT_BOOTLOADER_ABR_TYPE_GUID, PartitionScheme::kNew), | 
|  | GuidProperties(GPT_BOOTLOADER_B_NAME, GPT_BOOTLOADER_ABR_TYPE_GUID, PartitionScheme::kNew), | 
|  | GuidProperties(GPT_BOOTLOADER_R_NAME, GPT_BOOTLOADER_ABR_TYPE_GUID, PartitionScheme::kNew), | 
|  | GuidProperties(GPT_DURABLE_NAME,      GPT_DURABLE_TYPE_GUID,        PartitionScheme::kNew), | 
|  | GuidProperties(GPT_DURABLE_BOOT_NAME, GPT_DURABLE_BOOT_TYPE_GUID,   PartitionScheme::kNew), | 
|  | GuidProperties(GPT_FACTORY_NAME,      GPT_FACTORY_TYPE_GUID,        PartitionScheme::kNew), | 
|  | GuidProperties(GPT_FACTORY_BOOT_NAME, GPT_FACTORY_BOOT_TYPE_GUID,   PartitionScheme::kNew), | 
|  | GuidProperties(GPT_FVM_NAME,          GPT_FVM_TYPE_GUID,            PartitionScheme::kNew), | 
|  | GuidProperties(GPT_VBMETA_A_NAME,     GPT_VBMETA_ABR_TYPE_GUID,     PartitionScheme::kNew), | 
|  | GuidProperties(GPT_VBMETA_B_NAME,     GPT_VBMETA_ABR_TYPE_GUID,     PartitionScheme::kNew), | 
|  | GuidProperties(GPT_VBMETA_R_NAME,     GPT_VBMETA_ABR_TYPE_GUID,     PartitionScheme::kNew), | 
|  | GuidProperties(GPT_ZIRCON_A_NAME,     GPT_ZIRCON_ABR_TYPE_GUID,     PartitionScheme::kNew), | 
|  | GuidProperties(GPT_ZIRCON_B_NAME,     GPT_ZIRCON_ABR_TYPE_GUID,     PartitionScheme::kNew), | 
|  | GuidProperties(GPT_ZIRCON_R_NAME,     GPT_ZIRCON_ABR_TYPE_GUID,     PartitionScheme::kNew), | 
|  | }}; | 
|  | // clang-format on | 
|  |  | 
|  | std::list<const GuidProperties*> KnownGuid::Find(std::optional<std::string_view> name, | 
|  | std::optional<uuid::Uuid> type_guid, | 
|  | std::optional<PartitionScheme> scheme) { | 
|  | std::list<const GuidProperties*> result; | 
|  | for (const GuidProperties& properties : nametab_) { | 
|  | if ((!name || *name == properties.name()) && | 
|  | (!type_guid || *type_guid == properties.type_guid()) && | 
|  | (!scheme || *scheme == properties.scheme())) { | 
|  | result.push_back(&properties); | 
|  | } | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | // Returns the longest common prefix between |a| and |b|. | 
|  | std::string_view CommonPrefix(std::string_view a, std::string_view b) { | 
|  | const size_t end = std::min(a.size(), b.size()); | 
|  | for (size_t i = 0; i < end; ++i) { | 
|  | if (a[i] != b[i]) { | 
|  | return std::string_view(a.data(), i); | 
|  | } | 
|  | } | 
|  | return std::string_view(a.data(), end); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | std::string KnownGuid::TypeDescription(const uuid::Uuid& type_guid) { | 
|  | auto matches = Find(std::nullopt, type_guid, std::nullopt); | 
|  |  | 
|  | // No matches: return empty string. | 
|  | if (matches.empty()) { | 
|  | return ""; | 
|  | } | 
|  |  | 
|  | // One match: just return the partition name directly. | 
|  | if (matches.size() == 1) { | 
|  | return std::string(matches.front()->name()); | 
|  | } | 
|  |  | 
|  | // Multiple matches: use the longest common prefix. | 
|  | std::string_view prefix = matches.front()->name(); | 
|  | for (auto iter = ++matches.begin(); iter != matches.end(); ++iter) { | 
|  | prefix = CommonPrefix(prefix, (*iter)->name()); | 
|  | } | 
|  |  | 
|  | // Return "<prefix>*". | 
|  | return std::string(prefix) + "*"; | 
|  | } | 
|  |  | 
|  | std::string KnownGuid::TypeDescription(const uint8_t* type_guid) { | 
|  | return TypeDescription(uuid::Uuid(type_guid)); | 
|  | } | 
|  |  | 
|  | }  // namespace gpt |