2017-03-19 07:00:49 +00:00
|
|
|
// Copyright 2017 Dolphin Emulator Project
|
2021-07-05 01:22:19 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2017-03-19 07:00:49 +00:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2021-12-30 04:03:50 +00:00
|
|
|
#include <array>
|
2017-03-19 07:00:49 +00:00
|
|
|
#include <functional>
|
2021-12-30 03:40:00 +00:00
|
|
|
#include <memory>
|
2017-03-19 07:00:49 +00:00
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
2021-12-29 23:26:46 +00:00
|
|
|
#include <fmt/format.h>
|
|
|
|
|
2017-03-19 07:00:49 +00:00
|
|
|
#include "Common/CommonTypes.h"
|
2022-07-27 08:51:19 +00:00
|
|
|
#include "Common/Crypto/AES.h"
|
2021-12-29 23:26:46 +00:00
|
|
|
#include "Common/Swap.h"
|
2017-03-19 07:00:49 +00:00
|
|
|
|
|
|
|
namespace DiscIO
|
|
|
|
{
|
|
|
|
class NANDImporter final
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
NANDImporter();
|
|
|
|
~NANDImporter();
|
|
|
|
|
2017-10-26 19:22:16 +00:00
|
|
|
// Extract a NAND image to the configured NAND root.
|
|
|
|
// If the associated OTP/SEEPROM dump (keys.bin) is not included in the image,
|
|
|
|
// get_otp_dump_path will be called to get a path to it.
|
|
|
|
void ImportNANDBin(const std::string& path_to_bin, std::function<void()> update_callback,
|
|
|
|
std::function<std::string()> get_otp_dump_path);
|
2021-12-29 22:19:21 +00:00
|
|
|
bool ExtractCertificates();
|
2017-03-19 07:00:49 +00:00
|
|
|
|
2021-12-29 23:26:46 +00:00
|
|
|
enum class Type
|
|
|
|
{
|
|
|
|
File = 1,
|
|
|
|
Directory = 2,
|
|
|
|
};
|
|
|
|
|
2017-03-19 07:00:49 +00:00
|
|
|
#pragma pack(push, 1)
|
|
|
|
struct NANDFSTEntry
|
|
|
|
{
|
2017-10-28 20:40:05 +00:00
|
|
|
char name[12];
|
2021-12-29 23:26:46 +00:00
|
|
|
u8 mode;
|
|
|
|
u8 attr;
|
|
|
|
Common::BigEndianValue<u16> sub;
|
|
|
|
Common::BigEndianValue<u16> sib;
|
|
|
|
Common::BigEndianValue<u32> size;
|
|
|
|
Common::BigEndianValue<u32> uid;
|
|
|
|
Common::BigEndianValue<u16> gid;
|
|
|
|
Common::BigEndianValue<u32> x3;
|
2017-03-19 07:00:49 +00:00
|
|
|
};
|
2021-12-29 23:26:46 +00:00
|
|
|
static_assert(sizeof(NANDFSTEntry) == 0x20, "Wrong size");
|
2021-12-30 03:40:00 +00:00
|
|
|
|
|
|
|
struct NANDSuperblock
|
|
|
|
{
|
2023-04-01 02:19:15 +00:00
|
|
|
std::array<char, 4> magic; // "SFFS"
|
2021-12-30 03:40:00 +00:00
|
|
|
Common::BigEndianValue<u32> version;
|
|
|
|
Common::BigEndianValue<u32> unknown;
|
2023-04-01 02:19:15 +00:00
|
|
|
std::array<Common::BigEndianValue<u16>, 0x8000> fat;
|
|
|
|
std::array<NANDFSTEntry, 0x17FF> fst;
|
|
|
|
std::array<u8, 0x14> pad;
|
2021-12-30 03:40:00 +00:00
|
|
|
};
|
|
|
|
static_assert(sizeof(NANDSuperblock) == 0x40000, "Wrong size");
|
2017-03-19 07:00:49 +00:00
|
|
|
#pragma pack(pop)
|
|
|
|
|
2021-12-29 23:26:46 +00:00
|
|
|
private:
|
2017-10-26 19:22:16 +00:00
|
|
|
bool ReadNANDBin(const std::string& path_to_bin, std::function<std::string()> get_otp_dump_path);
|
2021-12-30 03:40:00 +00:00
|
|
|
bool FindSuperblock();
|
2017-03-19 07:00:49 +00:00
|
|
|
std::string GetPath(const NANDFSTEntry& entry, const std::string& parent_path);
|
2017-05-15 00:47:02 +00:00
|
|
|
std::string FormatDebugString(const NANDFSTEntry& entry);
|
2017-03-19 07:00:49 +00:00
|
|
|
void ProcessEntry(u16 entry_number, const std::string& parent_path);
|
2021-12-30 01:28:54 +00:00
|
|
|
std::vector<u8> GetEntryData(const NANDFSTEntry& entry);
|
2021-12-29 22:19:21 +00:00
|
|
|
void ExportKeys();
|
2017-03-19 07:00:49 +00:00
|
|
|
|
2021-12-29 22:19:21 +00:00
|
|
|
std::string m_nand_root;
|
2017-03-19 07:00:49 +00:00
|
|
|
std::vector<u8> m_nand;
|
|
|
|
std::vector<u8> m_nand_keys;
|
2022-07-27 08:51:19 +00:00
|
|
|
std::unique_ptr<Common::AES::Context> m_aes_ctx;
|
2021-12-30 03:40:00 +00:00
|
|
|
std::unique_ptr<NANDSuperblock> m_superblock;
|
2017-05-07 03:26:46 +00:00
|
|
|
std::function<void()> m_update_callback;
|
2017-03-19 07:00:49 +00:00
|
|
|
};
|
2019-05-05 23:48:12 +00:00
|
|
|
} // namespace DiscIO
|
2021-12-29 23:26:46 +00:00
|
|
|
|
|
|
|
template <>
|
|
|
|
struct fmt::formatter<DiscIO::NANDImporter::NANDFSTEntry>
|
|
|
|
{
|
|
|
|
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
|
|
|
|
template <typename FormatContext>
|
|
|
|
auto format(const DiscIO::NANDImporter::NANDFSTEntry& entry, FormatContext& ctx) const
|
|
|
|
{
|
|
|
|
return fmt::format_to(
|
|
|
|
ctx.out(), "{:12.12} {:#010b} {:#04x} {:#06x} {:#06x} {:#010x} {:#010x} {:#06x} {:#010x}",
|
|
|
|
entry.name, entry.mode, entry.attr, entry.sub, entry.sib, entry.size, entry.uid, entry.gid,
|
|
|
|
entry.x3);
|
|
|
|
}
|
|
|
|
};
|