mirror of
https://github.com/wiiu-env/AromaBasePlugin.git
synced 2024-11-26 21:44:21 +01:00
Automatically save a OTP/SEEPROM dump to the sd card
This commit is contained in:
parent
cc04c1ae96
commit
2a995e2591
@ -5,5 +5,6 @@ COPY --from=ghcr.io/wiiu-env/libnotifications:20240426 /artifacts $DEVKITPRO
|
||||
COPY --from=ghcr.io/wiiu-env/librpxloader:20240425 /artifacts $DEVKITPRO
|
||||
COPY --from=ghcr.io/wiiu-env/libcurlwrapper:20240505 /artifacts $DEVKITPRO
|
||||
COPY --from=ghcr.io/wiiu-env/libsdutils:20230621 /artifacts $DEVKITPRO
|
||||
COPY --from=ghcr.io/wiiu-env/libmocha:20231127 /artifacts $DEVKITPRO
|
||||
|
||||
WORKDIR project
|
||||
|
4
Makefile
4
Makefile
@ -48,13 +48,13 @@ CXXFLAGS += -DDEBUG -DVERBOSE_DEBUG -g
|
||||
CFLAGS += -DDEBUG -DVERBOSE_DEBUG -g
|
||||
endif
|
||||
|
||||
LIBS := -lcurlwrapper -lnotifications -lrpxloader -lsdutils -lwups -lwut
|
||||
LIBS := -lmocha -lcurlwrapper -lnotifications -lrpxloader -lsdutils -lwups -lwut
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level
|
||||
# containing include and lib
|
||||
#-------------------------------------------------------------------------------
|
||||
LIBDIRS := $(PORTLIBS) $(WUPS_ROOT) $(WUMS_ROOT) $(WUT_ROOT)
|
||||
LIBDIRS := $(PORTLIBS) $(WUPS_ROOT) $(WUMS_ROOT) $(WUT_ROOT) $(WUT_ROOT)/usr
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
|
@ -36,6 +36,7 @@ For building you need:
|
||||
- [librpxloader](https://github.com/wiiu-env/librpxloader)
|
||||
- [libcurlwrapper](https://github.com/wiiu-env/libcurlwrapper)
|
||||
- [libsdutils](https://github.com/wiiu-env/libsdutils)
|
||||
- [libmocha](https://github.com/wiiu-env/libmocha)
|
||||
|
||||
## Building using the Dockerfile
|
||||
|
||||
|
@ -6,4 +6,8 @@
|
||||
#define AROMA_UPDATER_OLD_PATH_FULL SD_CARD_PATH AROMA_UPDATER_OLD_PATH
|
||||
#define AROMA_UPDATER_NEW_PATH_FULL SD_CARD_PATH AROMA_UPDATER_NEW_PATH
|
||||
#define AROMA_UPDATER_NEW_DIRECTORY_FULL SD_CARD_PATH AROMA_UPDATER_NEW_DIRECTORY
|
||||
#define AROMA_UPDATER_LAST_UPDATE_URL "https://aroma.foryour.cafe/api/latest_version"
|
||||
#define AROMA_UPDATER_LAST_UPDATE_URL "https://aroma.foryour.cafe/api/latest_version"
|
||||
|
||||
|
||||
#define BACKUPS_DIRECTORY "wiiu/backups"
|
||||
#define BACKUPS_DIRECTORY_FULL SD_CARD_PATH BACKUPS_DIRECTORY
|
49
src/main.cpp
49
src/main.cpp
@ -1,12 +1,13 @@
|
||||
#include "main.h"
|
||||
#include "Hints.h"
|
||||
#include "UpdaterCheck.h"
|
||||
#include "common.h"
|
||||
#include "utils/DownloadUtils.h"
|
||||
#include "utils/LatestVersion.h"
|
||||
#include "utils/config.h"
|
||||
#include "utils/utils.h"
|
||||
#include <coreinit/title.h>
|
||||
#include <malloc.h>
|
||||
#include <mocha/mocha.h>
|
||||
#include <nn/spm.h>
|
||||
#include <notifications/notifications.h>
|
||||
#include <rpxloader/rpxloader.h>
|
||||
@ -72,44 +73,6 @@ bool InitConfigValuesFromStorage() {
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Migrates wiiu/apps/AromaUpdater.wuhb to wiiu/apps/AromaUpdater/AromaUpdater.wuhb
|
||||
*/
|
||||
void MigrateAromaUpdater() {
|
||||
struct stat st {};
|
||||
bool oldExists = false;
|
||||
bool newExists = false;
|
||||
if (stat(AROMA_UPDATER_NEW_PATH_FULL, &st) >= 0 && S_ISREG(st.st_mode)) {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("\"%s\" exists", AROMA_UPDATER_NEW_PATH_FULL);
|
||||
newExists = true;
|
||||
}
|
||||
st = {};
|
||||
if (stat(AROMA_UPDATER_OLD_PATH_FULL, &st) >= 0 && S_ISREG(st.st_mode)) {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("\"%s\" exists", AROMA_UPDATER_OLD_PATH_FULL);
|
||||
oldExists = true;
|
||||
}
|
||||
if (newExists) {
|
||||
if (oldExists) {
|
||||
if (remove(AROMA_UPDATER_OLD_PATH_FULL) < 0) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to remove old Aroma Updater: %d", errno);
|
||||
}
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("Only new AromaUpdater.wuhb exists");
|
||||
}
|
||||
return;
|
||||
} else if (oldExists) {
|
||||
if (stat(AROMA_UPDATER_NEW_DIRECTORY_FULL, &st) < 0 || !S_ISDIR(st.st_mode)) {
|
||||
if (mkdir(AROMA_UPDATER_NEW_DIRECTORY_FULL, 0777) < 0) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to create: \"%s\"", AROMA_UPDATER_NEW_DIRECTORY_FULL);
|
||||
}
|
||||
}
|
||||
if (rename(AROMA_UPDATER_OLD_PATH_FULL, AROMA_UPDATER_NEW_PATH_FULL) < 0) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to move Aroma Updater to new path");
|
||||
}
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("No AromaUpdater.wuhb exists");
|
||||
}
|
||||
}
|
||||
|
||||
INITIALIZE_PLUGIN() {
|
||||
initLogging();
|
||||
@ -123,11 +86,17 @@ INITIALIZE_PLUGIN() {
|
||||
DEBUG_FUNCTION_LINE_ERR("SDUtils_InitLibrary failed");
|
||||
}
|
||||
|
||||
if (Mocha_InitLibrary() != MOCHA_RESULT_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Mocha_InitLibrary failed");
|
||||
}
|
||||
|
||||
InitConfigValuesFromStorage();
|
||||
|
||||
InitConfigMenu();
|
||||
|
||||
MigrateAromaUpdater();
|
||||
Utils::MigrateAromaUpdater();
|
||||
|
||||
Utils::DumpOTPAndSeeprom();
|
||||
}
|
||||
|
||||
ON_APPLICATION_START() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "version.h"
|
||||
|
||||
#define PLUGIN_VERSION "v0.1.4"
|
||||
#define PLUGIN_VERSION "v0.1.5"
|
||||
#define PLUGIN_VERSION_FULL PLUGIN_VERSION PLUGIN_VERSION_EXTRA
|
||||
|
173
src/utils/CFile.cpp
Normal file
173
src/utils/CFile.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
|
||||
#include "CFile.hpp"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
|
||||
CFile::CFile() {
|
||||
iFd = -1;
|
||||
mem_file = nullptr;
|
||||
filesize = 0;
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
CFile::CFile(const std::string &filepath, eOpenTypes mode) {
|
||||
iFd = -1;
|
||||
this->open(filepath, mode);
|
||||
}
|
||||
|
||||
CFile::CFile(const uint8_t *mem, int32_t size) {
|
||||
iFd = -1;
|
||||
this->open(mem, size);
|
||||
}
|
||||
|
||||
CFile::~CFile() {
|
||||
this->close();
|
||||
}
|
||||
|
||||
int32_t CFile::open(const std::string &filepath, eOpenTypes mode) {
|
||||
this->close();
|
||||
int32_t openMode = 0;
|
||||
|
||||
// This depend on the devoptab implementation.
|
||||
// see https://github.com/devkitPro/wut/blob/master/libraries/wutdevoptab/devoptab_fs_open.c#L21 fpr reference
|
||||
|
||||
switch (mode) {
|
||||
default:
|
||||
case ReadOnly: // file must exist
|
||||
openMode = O_RDONLY;
|
||||
break;
|
||||
case WriteOnly: // file will be created / zerod
|
||||
openMode = O_TRUNC | O_CREAT | O_WRONLY;
|
||||
break;
|
||||
case ReadWrite: // file must exist
|
||||
openMode = O_RDWR;
|
||||
break;
|
||||
case Append: // append to file, file will be created if missing. write only
|
||||
openMode = O_CREAT | O_APPEND | O_WRONLY;
|
||||
break;
|
||||
}
|
||||
|
||||
//! Using fopen works only on the first launch as expected
|
||||
//! on the second launch it causes issues because we don't overwrite
|
||||
//! the .data sections which is needed for a normal application to re-init
|
||||
//! this will be added with launching as RPX
|
||||
iFd = ::open(filepath.c_str(), openMode);
|
||||
if (iFd < 0)
|
||||
return iFd;
|
||||
|
||||
|
||||
filesize = ::lseek(iFd, 0, SEEK_END);
|
||||
::lseek(iFd, 0, SEEK_SET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t CFile::open(const uint8_t *mem, int32_t size) {
|
||||
this->close();
|
||||
|
||||
mem_file = mem;
|
||||
filesize = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CFile::close() {
|
||||
if (iFd >= 0)
|
||||
::close(iFd);
|
||||
|
||||
iFd = -1;
|
||||
mem_file = NULL;
|
||||
filesize = 0;
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
int32_t CFile::read(uint8_t *ptr, size_t size) {
|
||||
if (iFd >= 0) {
|
||||
int32_t ret = ::read(iFd, ptr, size);
|
||||
if (ret > 0)
|
||||
pos += ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t readsize = size;
|
||||
|
||||
if (readsize > (int64_t) (filesize - pos))
|
||||
readsize = filesize - pos;
|
||||
|
||||
if (readsize <= 0)
|
||||
return readsize;
|
||||
|
||||
if (mem_file != NULL) {
|
||||
memcpy(ptr, mem_file + pos, readsize);
|
||||
pos += readsize;
|
||||
return readsize;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t CFile::write(const uint8_t *ptr, size_t size) {
|
||||
if (iFd >= 0) {
|
||||
size_t done = 0;
|
||||
while (done < size) {
|
||||
int32_t ret = ::write(iFd, ptr, size - done);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
ptr += ret;
|
||||
done += ret;
|
||||
pos += ret;
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t CFile::seek(long int offset, int32_t origin) {
|
||||
int32_t ret = 0;
|
||||
int64_t newPos = pos;
|
||||
|
||||
if (origin == SEEK_SET) {
|
||||
newPos = offset;
|
||||
} else if (origin == SEEK_CUR) {
|
||||
newPos += offset;
|
||||
} else if (origin == SEEK_END) {
|
||||
newPos = filesize + offset;
|
||||
}
|
||||
|
||||
if (newPos < 0) {
|
||||
pos = 0;
|
||||
} else {
|
||||
pos = newPos;
|
||||
}
|
||||
|
||||
if (iFd >= 0)
|
||||
ret = ::lseek(iFd, pos, SEEK_SET);
|
||||
|
||||
if (mem_file != NULL) {
|
||||
if (pos > filesize) {
|
||||
pos = filesize;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t CFile::fwrite(const char *format, ...) {
|
||||
char tmp[512];
|
||||
tmp[0] = 0;
|
||||
int32_t result = -1;
|
||||
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
if ((vsprintf(tmp, format, va) >= 0)) {
|
||||
result = this->write((uint8_t *) tmp, strlen(tmp));
|
||||
}
|
||||
va_end(va);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
71
src/utils/CFile.hpp
Normal file
71
src/utils/CFile.hpp
Normal file
@ -0,0 +1,71 @@
|
||||
#ifndef CFILE_HPP_
|
||||
#define CFILE_HPP_
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <wut_types.h>
|
||||
|
||||
class CFile {
|
||||
public:
|
||||
enum eOpenTypes {
|
||||
ReadOnly,
|
||||
WriteOnly,
|
||||
ReadWrite,
|
||||
Append
|
||||
};
|
||||
|
||||
CFile();
|
||||
|
||||
CFile(const std::string &filepath, eOpenTypes mode);
|
||||
|
||||
CFile(const uint8_t *memory, int32_t memsize);
|
||||
|
||||
virtual ~CFile();
|
||||
|
||||
int32_t open(const std::string &filepath, eOpenTypes mode);
|
||||
|
||||
int32_t open(const uint8_t *memory, int32_t memsize);
|
||||
|
||||
BOOL isOpen() const {
|
||||
if (iFd >= 0)
|
||||
return true;
|
||||
|
||||
if (mem_file)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void close();
|
||||
|
||||
int32_t read(uint8_t *ptr, size_t size);
|
||||
|
||||
int32_t write(const uint8_t *ptr, size_t size);
|
||||
|
||||
int32_t fwrite(const char *format, ...);
|
||||
|
||||
int32_t seek(long int offset, int32_t origin);
|
||||
|
||||
uint64_t tell() {
|
||||
return pos;
|
||||
};
|
||||
|
||||
uint64_t size() {
|
||||
return filesize;
|
||||
};
|
||||
|
||||
void rewind() {
|
||||
this->seek(0, SEEK_SET);
|
||||
};
|
||||
|
||||
protected:
|
||||
int32_t iFd;
|
||||
const uint8_t *mem_file{};
|
||||
uint64_t filesize{};
|
||||
uint64_t pos{};
|
||||
};
|
||||
|
||||
#endif
|
127
src/utils/FSUtils.cpp
Normal file
127
src/utils/FSUtils.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
#include "FSUtils.h"
|
||||
#include "CFile.hpp"
|
||||
#include "logger.h"
|
||||
#include <fcntl.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
int32_t FSUtils::CheckFile(const char *filepath) {
|
||||
if (!filepath)
|
||||
return 0;
|
||||
|
||||
struct stat filestat {};
|
||||
|
||||
char dirnoslash[strlen(filepath) + 2];
|
||||
snprintf(dirnoslash, sizeof(dirnoslash), "%s", filepath);
|
||||
|
||||
while (dirnoslash[strlen(dirnoslash) - 1] == '/')
|
||||
dirnoslash[strlen(dirnoslash) - 1] = '\0';
|
||||
|
||||
char *notRoot = strrchr(dirnoslash, '/');
|
||||
if (!notRoot) {
|
||||
strcat(dirnoslash, "/");
|
||||
}
|
||||
|
||||
if (stat(dirnoslash, &filestat) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t FSUtils::CreateSubfolder(const char *fullpath) {
|
||||
if (!fullpath)
|
||||
return 0;
|
||||
|
||||
int32_t result = 0;
|
||||
|
||||
char dirnoslash[strlen(fullpath) + 1];
|
||||
strcpy(dirnoslash, fullpath);
|
||||
|
||||
int32_t pos = strlen(dirnoslash) - 1;
|
||||
while (dirnoslash[pos] == '/') {
|
||||
dirnoslash[pos] = '\0';
|
||||
pos--;
|
||||
}
|
||||
|
||||
if (CheckFile(dirnoslash)) {
|
||||
return 1;
|
||||
} else {
|
||||
char parentpath[strlen(dirnoslash) + 2];
|
||||
strcpy(parentpath, dirnoslash);
|
||||
char *ptr = strrchr(parentpath, '/');
|
||||
|
||||
if (!ptr) {
|
||||
//!Device root directory (must be with '/')
|
||||
strcat(parentpath, "/");
|
||||
struct stat filestat;
|
||||
if (stat(parentpath, &filestat) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ptr++;
|
||||
ptr[0] = '\0';
|
||||
|
||||
result = CreateSubfolder(parentpath);
|
||||
}
|
||||
|
||||
if (!result)
|
||||
return 0;
|
||||
|
||||
if (mkdir(dirnoslash, 0777) == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t FSUtils::saveBufferToFile(const char *path, void *buffer, uint32_t size) {
|
||||
CFile file(path, CFile::WriteOnly);
|
||||
if (!file.isOpen()) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to open %s\n", path);
|
||||
return 0;
|
||||
}
|
||||
int32_t written = file.write((const uint8_t *) buffer, size);
|
||||
file.close();
|
||||
return written;
|
||||
}
|
||||
|
||||
bool FSUtils::copyFile(const std::string &in, const std::string &out) {
|
||||
// Using C++ buffers is **really** slow. Copying in 1023 byte chunks.
|
||||
// Let's do it the old way.
|
||||
size_t size;
|
||||
|
||||
int source = open(in.c_str(), O_RDONLY, 0);
|
||||
if (source < 0) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to open source %s", in.c_str());
|
||||
|
||||
return false;
|
||||
}
|
||||
int dest = open(out.c_str(), 0x602, 0644);
|
||||
if (dest < 0) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to open dest %s", out.c_str());
|
||||
close(source);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto bufferSize = 128 * 1024;
|
||||
char *buf = (char *) malloc(bufferSize);
|
||||
if (buf == nullptr) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to alloc buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
while ((size = read(source, buf, bufferSize)) > 0) {
|
||||
write(dest, buf, size);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
close(source);
|
||||
close(dest);
|
||||
return true;
|
||||
}
|
16
src/utils/FSUtils.h
Normal file
16
src/utils/FSUtils.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <wut_types.h>
|
||||
|
||||
class FSUtils {
|
||||
public:
|
||||
//! todo: C++ class
|
||||
static int32_t CreateSubfolder(const char *fullpath);
|
||||
|
||||
static int32_t CheckFile(const char *filepath);
|
||||
|
||||
static int32_t saveBufferToFile(const char *path, void *buffer, uint32_t size);
|
||||
|
||||
static bool copyFile(const std::string &in, const std::string &out);
|
||||
};
|
116
src/utils/utils.cpp
Normal file
116
src/utils/utils.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
#include "utils.h"
|
||||
#include "FSUtils.h"
|
||||
#include "common.h"
|
||||
#include "logger.h"
|
||||
#include <coreinit/mcp.h>
|
||||
#include <mocha/mocha.h>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
|
||||
bool Utils::GetSerialId(std::string &serialID) {
|
||||
bool result = false;
|
||||
alignas(0x40) MCPSysProdSettings settings{};
|
||||
auto handle = MCP_Open();
|
||||
if (handle >= 0) {
|
||||
if (MCP_GetSysProdSettings(handle, &settings) == 0) {
|
||||
serialID = std::string(settings.code_id) + settings.serial_id;
|
||||
result = true;
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to get SerialId");
|
||||
}
|
||||
MCP_Close(handle);
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_ERR("MCP_Open failed");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline bool existsAsFile(std::string_view path) {
|
||||
struct stat st {};
|
||||
if (stat(path.data(), &st) >= 0 && S_ISREG(st.st_mode)) {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("\"%s\" exists", path.data());
|
||||
return true;
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("\"%s\" doesn't exists", path.data());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Migrates wiiu/apps/AromaUpdater.wuhb to wiiu/apps/AromaUpdater/AromaUpdater.wuhb
|
||||
*/
|
||||
void Utils::MigrateAromaUpdater() {
|
||||
bool newExists = existsAsFile(AROMA_UPDATER_NEW_PATH_FULL);
|
||||
bool oldExists = existsAsFile(AROMA_UPDATER_OLD_PATH_FULL);
|
||||
|
||||
if (newExists) {
|
||||
if (oldExists) {
|
||||
if (remove(AROMA_UPDATER_OLD_PATH_FULL) < 0) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to remove old Aroma Updater: %d", errno);
|
||||
}
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("Only new AromaUpdater.wuhb exists");
|
||||
}
|
||||
return;
|
||||
} else if (oldExists) {
|
||||
if (!FSUtils::CreateSubfolder(AROMA_UPDATER_NEW_DIRECTORY_FULL)) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to create \"%s\"", AROMA_UPDATER_NEW_DIRECTORY_FULL);
|
||||
}
|
||||
|
||||
if (rename(AROMA_UPDATER_OLD_PATH_FULL, AROMA_UPDATER_NEW_PATH_FULL) < 0) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to move Aroma Updater to new path");
|
||||
}
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("No AromaUpdater.wuhb exists");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Dumps the OTP and SEEPROM when if it's no exists.
|
||||
*/
|
||||
void Utils::DumpOTPAndSeeprom() {
|
||||
std::string serialId;
|
||||
if (!Utils::GetSerialId(serialId)) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get SerialId of the console, skip OTP/SEEPROM dumping");
|
||||
return;
|
||||
}
|
||||
std::string backupPathConsole = string_format(BACKUPS_DIRECTORY_FULL "/%s", serialId.c_str());
|
||||
std::string backupPathConsoleOtpPath = backupPathConsole + "/opt.bin";
|
||||
std::string backupPathConsoleSeepromPath = backupPathConsole + "/seeprom.bin";
|
||||
|
||||
if (!FSUtils::CreateSubfolder(backupPathConsole.c_str())) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to create \"%s\"", backupPathConsole.c_str());
|
||||
}
|
||||
|
||||
bool seepromExists = FSUtils::CheckFile(backupPathConsoleSeepromPath.c_str());
|
||||
bool optExists = FSUtils::CheckFile(backupPathConsoleOtpPath.c_str());
|
||||
|
||||
if (!seepromExists) {
|
||||
uint8_t data[0x200] = {};
|
||||
if (Mocha_SEEPROMRead(data, 0, sizeof(data)) != sizeof(data)) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to read SEEPROM");
|
||||
} else {
|
||||
if (FSUtils::saveBufferToFile(backupPathConsoleSeepromPath.c_str(), (void *) data, sizeof(data)) != sizeof(data)) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to write SEEPROM backup (\"%s\")", backupPathConsoleSeepromPath.c_str());
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_INFO("Created SEEPROM backup: \"%s\"", backupPathConsoleSeepromPath.c_str());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("SEEPROM backup already exists");
|
||||
}
|
||||
if (!optExists) {
|
||||
WiiUConsoleOTP otp = {};
|
||||
if (Mocha_ReadOTP(&otp) != MOCHA_RESULT_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to read otp");
|
||||
} else {
|
||||
if (FSUtils::saveBufferToFile(backupPathConsoleOtpPath.c_str(), (void *) &otp, sizeof(otp)) != sizeof(otp)) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to write otp backup (\"%s\")", backupPathConsoleOtpPath.c_str());
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_INFO("Created OTP backup: \"%s\"", backupPathConsoleOtpPath.c_str());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("OTP backup already exists");
|
||||
}
|
||||
}
|
21
src/utils/utils.h
Normal file
21
src/utils/utils.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace Utils {
|
||||
bool GetSerialId(std::string &serialID);
|
||||
|
||||
void MigrateAromaUpdater();
|
||||
void DumpOTPAndSeeprom();
|
||||
} // namespace Utils
|
||||
|
||||
template<typename... Args>
|
||||
std::string string_format(const std::string &format, Args... args) {
|
||||
int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0'
|
||||
auto size = static_cast<size_t>(size_s);
|
||||
auto buf = std::make_unique<char[]>(size);
|
||||
std::snprintf(buf.get(), size, format.c_str(), args...);
|
||||
return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
|
||||
}
|
Loading…
Reference in New Issue
Block a user