mirror of
https://github.com/wiiu-env/wudd.git
synced 2024-11-25 11:16:57 +01:00
120 lines
4.4 KiB
C++
120 lines
4.4 KiB
C++
/****************************************************************************
|
|
* Copyright (C) 2016-2021 Maschell
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
****************************************************************************/
|
|
#include "DiscReaderDiscDrive.h"
|
|
#include "utils/utils.h"
|
|
#include <WUD/content/WiiUDiscContentsHeader.h>
|
|
#include <common/common.h>
|
|
#include <malloc.h>
|
|
#include <mocha/fsa.h>
|
|
#include <mocha/mocha.h>
|
|
#include <utils/logger.h>
|
|
#include <utils/rijndael.h>
|
|
|
|
DiscReaderDiscDrive::DiscReaderDiscDrive() : DiscReader() {
|
|
auto sector_buf = (uint8_t *) memalign(0x40, (size_t) READ_SECTOR_SIZE);
|
|
if (!sector_buf) {
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to allocate buffer");
|
|
return;
|
|
}
|
|
|
|
auto ret = FSAEx_RawOpenEx(gFSAClientHandle, "/dev/odd01", &device_handle);
|
|
if (ret < 0) {
|
|
free(sector_buf);
|
|
return;
|
|
}
|
|
|
|
auto res = FSAEx_RawReadEx(gFSAClientHandle, sector_buf, READ_SECTOR_SIZE, 1, 3, device_handle);
|
|
if (res >= 0) {
|
|
if (((uint32_t *) sector_buf)[0] != WiiUDiscContentsHeader::MAGIC) {
|
|
uint8_t iv[16];
|
|
memset(iv, 0, 16);
|
|
|
|
WUDDiscKey discKeyLocal;
|
|
|
|
auto discKeyRes = Mocha_ODMGetDiscKey(&discKeyLocal);
|
|
if (discKeyRes == MOCHA_RESULT_SUCCESS) {
|
|
hasDiscKey = true;
|
|
memcpy(this->discKey, discKeyLocal.key, 16);
|
|
auto sector_buf_decrypted = make_unique_nothrow<uint8_t[]>((size_t) READ_SECTOR_SIZE);
|
|
if (!sector_buf_decrypted) {
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to allocate memory");
|
|
free(sector_buf);
|
|
return;
|
|
}
|
|
aes_set_key((uint8_t *) discKey);
|
|
aes_decrypt((uint8_t *) iv, (uint8_t *) §or_buf[0], (uint8_t *) §or_buf_decrypted[0], READ_SECTOR_SIZE);
|
|
if (((uint32_t *) sector_buf_decrypted.get())[0] == WiiUDiscContentsHeader::MAGIC) {
|
|
this->init_done = true;
|
|
} else {
|
|
DEBUG_FUNCTION_LINE_ERR("Invalid disc key");
|
|
}
|
|
} else {
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to get the DiscKey");
|
|
this->init_done = false;
|
|
}
|
|
} else {
|
|
this->init_done = true;
|
|
}
|
|
} else {
|
|
DEBUG_FUNCTION_LINE_ERR("Raw read failed %d", ret);
|
|
}
|
|
}
|
|
|
|
bool DiscReaderDiscDrive::readEncryptedSector(uint8_t *buffer, uint32_t block_cnt, uint32_t block_offset) const {
|
|
if (FSAEx_RawReadEx(gFSAClientHandle, buffer, READ_SECTOR_SIZE, block_cnt, block_offset, device_handle) < 0) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool DiscReaderDiscDrive::IsReady() {
|
|
return init_done;
|
|
}
|
|
|
|
DiscReaderDiscDrive::~DiscReaderDiscDrive() {
|
|
if (device_handle != -1) {
|
|
FSAEx_RawCloseEx(gFSAClientHandle, device_handle);
|
|
device_handle = -1;
|
|
}
|
|
}
|
|
|
|
bool DiscReaderDiscDrive::readEncrypted(uint8_t *buf, uint64_t offset, uint32_t size) {
|
|
if (size == 0) {
|
|
return true;
|
|
}
|
|
|
|
if ((offset & (SECTOR_SIZE - 0x1)) != 0 || (size & (SECTOR_SIZE - 0x1)) != 0) {
|
|
return DiscReader::readEncrypted(buf, offset, size);
|
|
}
|
|
uint32_t block_cnt = size >> 15;
|
|
uint32_t offset_in_sectors = offset >> 15;
|
|
if (FSAEx_RawReadEx(gFSAClientHandle, buf, 0x8000, block_cnt, offset_in_sectors, device_handle) < 0) {
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to read from Disc");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
std::optional<std::unique_ptr<DiscReaderDiscDrive>> DiscReaderDiscDrive::make_unique() {
|
|
auto discReader = make_unique_nothrow<DiscReaderDiscDrive>();
|
|
if (!discReader || !discReader->IsReady()) {
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to init DiscReader %d %d", !discReader, discReader->IsReady());
|
|
return {};
|
|
}
|
|
return discReader;
|
|
}
|