bis_factory.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <fmt/format.h>
  4. #include "common/fs/path_util.h"
  5. #include "core/file_sys/bis_factory.h"
  6. #include "core/file_sys/mode.h"
  7. #include "core/file_sys/registered_cache.h"
  8. #include "core/file_sys/vfs.h"
  9. namespace FileSys {
  10. constexpr u64 NAND_USER_SIZE = 0x680000000; // 26624 MiB
  11. constexpr u64 NAND_SYSTEM_SIZE = 0xA0000000; // 2560 MiB
  12. constexpr u64 NAND_TOTAL_SIZE = 0x747C00000; // 29820 MiB
  13. BISFactory::BISFactory(VirtualDir nand_root_, VirtualDir load_root_, VirtualDir dump_root_)
  14. : nand_root(std::move(nand_root_)), load_root(std::move(load_root_)),
  15. dump_root(std::move(dump_root_)),
  16. sysnand_cache(std::make_unique<RegisteredCache>(
  17. GetOrCreateDirectoryRelative(nand_root, "/system/Contents/registered"))),
  18. usrnand_cache(std::make_unique<RegisteredCache>(
  19. GetOrCreateDirectoryRelative(nand_root, "/user/Contents/registered"))),
  20. sysnand_placeholder(std::make_unique<PlaceholderCache>(
  21. GetOrCreateDirectoryRelative(nand_root, "/system/Contents/placehld"))),
  22. usrnand_placeholder(std::make_unique<PlaceholderCache>(
  23. GetOrCreateDirectoryRelative(nand_root, "/user/Contents/placehld"))) {}
  24. BISFactory::~BISFactory() = default;
  25. VirtualDir BISFactory::GetSystemNANDContentDirectory() const {
  26. return GetOrCreateDirectoryRelative(nand_root, "/system/Contents");
  27. }
  28. VirtualDir BISFactory::GetUserNANDContentDirectory() const {
  29. return GetOrCreateDirectoryRelative(nand_root, "/user/Contents");
  30. }
  31. RegisteredCache* BISFactory::GetSystemNANDContents() const {
  32. return sysnand_cache.get();
  33. }
  34. RegisteredCache* BISFactory::GetUserNANDContents() const {
  35. return usrnand_cache.get();
  36. }
  37. PlaceholderCache* BISFactory::GetSystemNANDPlaceholder() const {
  38. return sysnand_placeholder.get();
  39. }
  40. PlaceholderCache* BISFactory::GetUserNANDPlaceholder() const {
  41. return usrnand_placeholder.get();
  42. }
  43. VirtualDir BISFactory::GetModificationLoadRoot(u64 title_id) const {
  44. // LayeredFS doesn't work on updates and title id-less homebrew
  45. if (title_id == 0 || (title_id & 0xFFF) == 0x800)
  46. return nullptr;
  47. return GetOrCreateDirectoryRelative(load_root, fmt::format("/{:016X}", title_id));
  48. }
  49. VirtualDir BISFactory::GetModificationDumpRoot(u64 title_id) const {
  50. if (title_id == 0)
  51. return nullptr;
  52. return GetOrCreateDirectoryRelative(dump_root, fmt::format("/{:016X}", title_id));
  53. }
  54. VirtualDir BISFactory::OpenPartition(BisPartitionId id) const {
  55. switch (id) {
  56. case BisPartitionId::CalibrationFile:
  57. return GetOrCreateDirectoryRelative(nand_root, "/prodinfof");
  58. case BisPartitionId::SafeMode:
  59. return GetOrCreateDirectoryRelative(nand_root, "/safe");
  60. case BisPartitionId::System:
  61. return GetOrCreateDirectoryRelative(nand_root, "/system");
  62. case BisPartitionId::User:
  63. return GetOrCreateDirectoryRelative(nand_root, "/user");
  64. default:
  65. return nullptr;
  66. }
  67. }
  68. VirtualFile BISFactory::OpenPartitionStorage(BisPartitionId id,
  69. VirtualFilesystem file_system) const {
  70. auto& keys = Core::Crypto::KeyManager::Instance();
  71. Core::Crypto::PartitionDataManager pdm{file_system->OpenDirectory(
  72. Common::FS::GetYuzuPathString(Common::FS::YuzuPath::NANDDir), Mode::Read)};
  73. keys.PopulateFromPartitionData(pdm);
  74. switch (id) {
  75. case BisPartitionId::CalibrationBinary:
  76. return pdm.GetDecryptedProdInfo();
  77. case BisPartitionId::BootConfigAndPackage2Part1:
  78. case BisPartitionId::BootConfigAndPackage2Part2:
  79. case BisPartitionId::BootConfigAndPackage2Part3:
  80. case BisPartitionId::BootConfigAndPackage2Part4:
  81. case BisPartitionId::BootConfigAndPackage2Part5:
  82. case BisPartitionId::BootConfigAndPackage2Part6: {
  83. const auto new_id = static_cast<u8>(id) -
  84. static_cast<u8>(BisPartitionId::BootConfigAndPackage2Part1) +
  85. static_cast<u8>(Core::Crypto::Package2Type::NormalMain);
  86. return pdm.GetPackage2Raw(static_cast<Core::Crypto::Package2Type>(new_id));
  87. }
  88. default:
  89. return nullptr;
  90. }
  91. }
  92. VirtualDir BISFactory::GetImageDirectory() const {
  93. return GetOrCreateDirectoryRelative(nand_root, "/user/Album");
  94. }
  95. u64 BISFactory::GetSystemNANDFreeSpace() const {
  96. const auto sys_dir = GetOrCreateDirectoryRelative(nand_root, "/system");
  97. if (sys_dir == nullptr) {
  98. return GetSystemNANDTotalSpace();
  99. }
  100. return GetSystemNANDTotalSpace() - sys_dir->GetSize();
  101. }
  102. u64 BISFactory::GetSystemNANDTotalSpace() const {
  103. return NAND_SYSTEM_SIZE;
  104. }
  105. u64 BISFactory::GetUserNANDFreeSpace() const {
  106. // For some reason games such as BioShock 1 checks whether this is exactly 0x680000000 bytes.
  107. // Set the free space to be 1 MiB less than the total as a workaround to this issue.
  108. return GetUserNANDTotalSpace() - 0x100000;
  109. }
  110. u64 BISFactory::GetUserNANDTotalSpace() const {
  111. return NAND_USER_SIZE;
  112. }
  113. u64 BISFactory::GetFullNANDTotalSpace() const {
  114. return NAND_TOTAL_SIZE;
  115. }
  116. VirtualDir BISFactory::GetBCATDirectory(u64 title_id) const {
  117. return GetOrCreateDirectoryRelative(nand_root,
  118. fmt::format("/system/save/bcat/{:016X}", title_id));
  119. }
  120. } // namespace FileSys