2017-03-19 01:00:49 -06:00
|
|
|
// Copyright 2017 Dolphin Emulator Project
|
2021-07-04 19:22:19 -06:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2017-03-19 01:00:49 -06:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2021-12-29 21:03:50 -07:00
|
|
|
#include <array>
|
2017-03-19 01:00:49 -06:00
|
|
|
#include <functional>
|
2021-12-29 20:40:00 -07:00
|
|
|
#include <memory>
|
2017-03-19 01:00:49 -06:00
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
2021-12-29 16:26:46 -07:00
|
|
|
#include <fmt/format.h>
|
|
|
|
|
2017-03-19 01:00:49 -06:00
|
|
|
#include "Common/CommonTypes.h"
|
2021-12-29 16:26:46 -07:00
|
|
|
#include "Common/Swap.h"
|
2017-03-19 01:00:49 -06:00
|
|
|
|
|
|
|
namespace DiscIO
|
|
|
|
{
|
|
|
|
class NANDImporter final
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
NANDImporter();
|
|
|
|
~NANDImporter();
|
|
|
|
|
2017-10-26 13:22:16 -06: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 15:19:21 -07:00
|
|
|
bool ExtractCertificates();
|
2017-03-19 01:00:49 -06:00
|
|
|
|
2021-12-29 16:26:46 -07:00
|
|
|
enum class Type
|
|
|
|
{
|
|
|
|
File = 1,
|
|
|
|
Directory = 2,
|
|
|
|
};
|
|
|
|
|
2017-03-19 01:00:49 -06:00
|
|
|
#pragma pack(push, 1)
|
|
|
|
struct NANDFSTEntry
|
|
|
|
{
|
2017-10-28 14:40:05 -06:00
|
|
|
char name[12];
|
2021-12-29 16:26:46 -07: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 01:00:49 -06:00
|
|
|
};
|
2021-12-29 16:26:46 -07:00
|
|
|
static_assert(sizeof(NANDFSTEntry) == 0x20, "Wrong size");
|
2021-12-29 20:40:00 -07:00
|
|
|
|
|
|
|
struct NANDSuperblock
|
|
|
|
{
|
|
|
|
char magic[4]; // "SFFS"
|
|
|
|
Common::BigEndianValue<u32> version;
|
|
|
|
Common::BigEndianValue<u32> unknown;
|
|
|
|
Common::BigEndianValue<u16> fat[0x8000];
|
|
|
|
NANDFSTEntry fst[0x17FF];
|
|
|
|
u8 pad[0x14];
|
|
|
|
};
|
|
|
|
static_assert(sizeof(NANDSuperblock) == 0x40000, "Wrong size");
|
2017-03-19 01:00:49 -06:00
|
|
|
#pragma pack(pop)
|
|
|
|
|
2021-12-29 16:26:46 -07:00
|
|
|
private:
|
2017-10-26 13:22:16 -06:00
|
|
|
bool ReadNANDBin(const std::string& path_to_bin, std::function<std::string()> get_otp_dump_path);
|
2021-12-29 20:40:00 -07:00
|
|
|
bool FindSuperblock();
|
2017-03-19 01:00:49 -06:00
|
|
|
std::string GetPath(const NANDFSTEntry& entry, const std::string& parent_path);
|
2017-05-14 18:47:02 -06:00
|
|
|
std::string FormatDebugString(const NANDFSTEntry& entry);
|
2017-03-19 01:00:49 -06:00
|
|
|
void ProcessEntry(u16 entry_number, const std::string& parent_path);
|
2021-12-29 18:28:54 -07:00
|
|
|
std::vector<u8> GetEntryData(const NANDFSTEntry& entry);
|
2021-12-29 15:19:21 -07:00
|
|
|
void ExportKeys();
|
2017-03-19 01:00:49 -06:00
|
|
|
|
2021-12-29 15:19:21 -07:00
|
|
|
std::string m_nand_root;
|
2017-03-19 01:00:49 -06:00
|
|
|
std::vector<u8> m_nand;
|
|
|
|
std::vector<u8> m_nand_keys;
|
2021-12-29 21:03:50 -07:00
|
|
|
std::array<u8, 16> m_aes_key;
|
2021-12-29 20:40:00 -07:00
|
|
|
std::unique_ptr<NANDSuperblock> m_superblock;
|
2017-05-06 21:26:46 -06:00
|
|
|
std::function<void()> m_update_callback;
|
2017-03-19 01:00:49 -06:00
|
|
|
};
|
2019-05-05 17:48:12 -06:00
|
|
|
} // namespace DiscIO
|
2021-12-29 16:26:46 -07: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);
|
|
|
|
}
|
|
|
|
};
|