bis_factory.cpp 5.2 KB

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