diff --git a/src/main.cpp b/src/main.cpp index 3105b89..e6b911b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -24,6 +24,7 @@ #include "dynamic.h" #include "kernel.h" +#include "utils/DirList.h" #include "utils/ElfUtils.h" #include "utils/logger.h" #include @@ -33,14 +34,11 @@ #include #include #include -#include #include -#include +#include std::map get_all_payloads(const char *relativefilepath); -std::vector readDirFull(const char *base_path, const char *path, FSCmdBlock &cmd, FSClient &client, int filter); - std::string PayloadSelectionScreen(const std::map &payloads); extern "C" void __init_wut(); @@ -96,6 +94,7 @@ extern "C" uint32_t start_wrapper(int argc, char **argv) { return entryPoint; } + extern "C" int _start(int argc, char **argv) { uint32_t entryPoint = start_wrapper(argc, argv); @@ -125,87 +124,34 @@ extern "C" int _start(int argc, char **argv) { std::map get_all_payloads(const char *relativefilepath) { std::map result; - const char *sdRootPath = ""; std::vector payload_folders; std::vector files_inFolder; - bool clientAdded = false; - if (!WHBMountSdCard()) { - DEBUG_FUNCTION_LINE("Failed to mount SD Card..."); - goto exit; - } - FSCmdBlock cmd; - FSClient client; + DirList dirList(std::string("fs:/vol/external01/") + relativefilepath, nullptr, DirList::Dirs, 1); + dirList.SortList(); - sdRootPath = WHBGetSdCardMountPath(); + for (int i = 0; i < dirList.GetFilecount(); i++) { + auto curDirName = dirList.GetFilename(i); + auto curPath = dirList.GetFilepath(i); + DEBUG_FUNCTION_LINE("Reading path %s", curDirName); - FSAddClient(&client, FS_ERROR_FLAG_ALL); - clientAdded = true; - - FSInitCmdBlock(&cmd); - - payload_folders = readDirFull(sdRootPath, relativefilepath, cmd, client, 1); - - for (auto &e : payload_folders) { - DEBUG_FUNCTION_LINE("Reading path %s", e.c_str()); - files_inFolder = readDirFull(sdRootPath, e.c_str(), cmd, client, 2); - - for (auto &child : files_inFolder) { - if (StringTools::EndsWith(child, "payload.elf")) { - std::vector folders = StringTools::stringSplit(e, "/"); - std::string folder_name = e; - if (folders.size() > 1) { - folder_name = folders.at(folders.size() - 1); - } - - DEBUG_FUNCTION_LINE("%s is valid!", folder_name.c_str()); - result[folder_name] = child; - break; - } + auto payloadPath = std::string(curPath) + "/payload.elf"; + auto fd = fopen(payloadPath.c_str(), "r"); + if (fd) { + fclose(fd); + result[curDirName] = payloadPath; } } -exit: - WHBUnmountSdCard(); - if (clientAdded) { - FSDelClient(&client, FS_ERROR_FLAG_ALL); - } return result; } -std::vector readDirFull(const char *base_path, const char *path, FSCmdBlock &cmd, FSClient &client, int filter) { - std::string full_dir_path = StringTools::strfmt("%s/%s", base_path, path); - FSStatus status; - FSDirectoryHandle handle; - std::vector result; - if (FSOpenDir(&client, &cmd, full_dir_path.c_str(), &handle, FS_ERROR_FLAG_ALL) == FS_STATUS_OK) { - FSDirectoryEntry entry; - while (true) { - status = FSReadDir(&client, &cmd, handle, &entry, FS_ERROR_FLAG_ALL); - if (status < 0) { - break; - } - std::string filepath = StringTools::strfmt("%s/%s", path, entry.name); - - if (entry.info.flags & FS_STAT_DIRECTORY && filter <= 1) { - result.push_back(filepath); - } else if (filter == 0 || filter == 2) { - result.push_back(filepath); - } - } - } else { - DEBUG_FUNCTION_LINE("Failed to open dir %s", path); - } - return result; -} - - std::string PayloadSelectionScreen(const std::map &payloads) { // Init screen and screen buffers OSScreenInit(); uint32_t screen_buf0_size = OSScreenGetBufferSizeEx(SCREEN_TV); uint32_t screen_buf1_size = OSScreenGetBufferSizeEx(SCREEN_DRC); - uint8_t *screenBuffer = (uint8_t *) memalign(0x100, screen_buf0_size + screen_buf1_size); + auto *screenBuffer = (uint8_t *) memalign(0x100, screen_buf0_size + screen_buf1_size); OSScreenSetBufferEx(SCREEN_TV, (void *) screenBuffer); OSScreenSetBufferEx(SCREEN_DRC, (void *) (screenBuffer + screen_buf0_size)); diff --git a/src/utils/DirList.cpp b/src/utils/DirList.cpp new file mode 100644 index 0000000..1b13235 --- /dev/null +++ b/src/utils/DirList.cpp @@ -0,0 +1,218 @@ +/**************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * DirList Class + * for WiiXplorer 2010 + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DirList.h" +#include "StringTools.h" + +DirList::DirList() { + Flags = 0; + Filter = 0; + Depth = 0; +} + +DirList::DirList(const std::string &path, const char *filter, uint32_t flags, uint32_t maxDepth) { + this->LoadPath(path, filter, flags, maxDepth); + this->SortList(); +} + +DirList::~DirList() { + ClearList(); +} + +BOOL DirList::LoadPath(const std::string &folder, const char *filter, uint32_t flags, uint32_t maxDepth) { + if (folder.empty()) + return false; + + Flags = flags; + Filter = filter; + Depth = maxDepth; + + std::string folderpath(folder); + uint32_t length = folderpath.size(); + + //! clear path of double slashes + StringTools::RemoveDoubleSlashs(folderpath); + + //! remove last slash if exists + if (length > 0 && folderpath[length - 1] == '/') + folderpath.erase(length - 1); + + //! add root slash if missing + if (folderpath.find('/') == std::string::npos) { + folderpath += '/'; + } + + return InternalLoadPath(folderpath); +} + +BOOL DirList::InternalLoadPath(std::string &folderpath) { + if (folderpath.size() < 3) + return false; + + struct dirent *dirent = nullptr; + DIR *dir = nullptr; + + dir = opendir(folderpath.c_str()); + if (dir == nullptr) + return false; + + while ((dirent = readdir(dir)) != 0) { + BOOL isDir = dirent->d_type & DT_DIR; + const char *filename = dirent->d_name; + + if (isDir) { + if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) + continue; + + if ((Flags & CheckSubfolders) && (Depth > 0)) { + int32_t length = folderpath.size(); + if (length > 2 && folderpath[length - 1] != '/') { + folderpath += '/'; + } + folderpath += filename; + + Depth--; + InternalLoadPath(folderpath); + folderpath.erase(length); + Depth++; + } + + if (!(Flags & Dirs)) + continue; + } else if (!(Flags & Files)) { + continue; + } + + if (Filter) { + char *fileext = strrchr(filename, '.'); + if (!fileext) + continue; + + if (StringTools::strtokcmp(fileext, Filter, ",") == 0) + AddEntrie(folderpath, filename, isDir); + } else { + AddEntrie(folderpath, filename, isDir); + } + } + closedir(dir); + + return true; +} + +void DirList::AddEntrie(const std::string &filepath, const char *filename, BOOL isDir) { + if (!filename) + return; + + int32_t pos = FileInfo.size(); + + FileInfo.resize(pos + 1); + + FileInfo[pos].FilePath = (char *) malloc(filepath.size() + strlen(filename) + 2); + if (!FileInfo[pos].FilePath) { + FileInfo.resize(pos); + return; + } + + sprintf(FileInfo[pos].FilePath, "%s/%s", filepath.c_str(), filename); + FileInfo[pos].isDir = isDir; +} + +void DirList::ClearList() { + for (uint32_t i = 0; i < FileInfo.size(); ++i) { + if (FileInfo[i].FilePath) { + free(FileInfo[i].FilePath); + FileInfo[i].FilePath = nullptr; + } + } + + FileInfo.clear(); + std::vector().swap(FileInfo); +} + +const char *DirList::GetFilename(int32_t ind) const { + if (!valid(ind)) + return ""; + + return StringTools::FullpathToFilename(FileInfo[ind].FilePath); +} + +static BOOL SortCallback(const DirEntry &f1, const DirEntry &f2) { + if (f1.isDir && !(f2.isDir)) + return true; + if (!(f1.isDir) && f2.isDir) + return false; + + if (f1.FilePath && !f2.FilePath) + return true; + if (!f1.FilePath) + return false; + + if (strcasecmp(f1.FilePath, f2.FilePath) > 0) + return false; + + return true; +} + +void DirList::SortList() { + if (FileInfo.size() > 1) + std::sort(FileInfo.begin(), FileInfo.end(), SortCallback); +} + +void DirList::SortList(BOOL (*SortFunc)(const DirEntry &a, const DirEntry &b)) { + if (FileInfo.size() > 1) + std::sort(FileInfo.begin(), FileInfo.end(), SortFunc); +} + +uint64_t DirList::GetFilesize(int32_t index) const { + struct stat st; + const char *path = GetFilepath(index); + + if (!path || stat(path, &st) != 0) + return 0; + + return st.st_size; +} + +int32_t DirList::GetFileIndex(const char *filename) const { + if (!filename) + return -1; + + for (uint32_t i = 0; i < FileInfo.size(); ++i) { + if (strcasecmp(GetFilename(i), filename) == 0) + return i; + } + + return -1; +} diff --git a/src/utils/DirList.h b/src/utils/DirList.h new file mode 100644 index 0000000..3cc62e1 --- /dev/null +++ b/src/utils/DirList.h @@ -0,0 +1,122 @@ +/**************************************************************************** + * Copyright (C) 2010 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + * DirList Class + * for WiiXplorer 2010 + ***************************************************************************/ +#ifndef ___DIRLIST_H_ +#define ___DIRLIST_H_ + +#include +#include +#include + +typedef struct { + char *FilePath; + BOOL isDir; +} DirEntry; + +class DirList { +public: + //!Constructor + DirList(void); + + //!\param path Path from where to load the filelist of all files + //!\param filter A fileext that needs to be filtered + //!\param flags search/filter flags from the enum + DirList(const std::string &path, const char *filter = nullptr, uint32_t flags = Files | Dirs, uint32_t maxDepth = 0xffffffff); + + //!Destructor + virtual ~DirList(); + + //! Load all the files from a directory + BOOL LoadPath(const std::string &path, const char *filter = nullptr, uint32_t flags = Files | Dirs, uint32_t maxDepth = 0xffffffff); + + //! Get a filename of the list + //!\param list index + const char *GetFilename(int32_t index) const; + + //! Get the a filepath of the list + //!\param list index + const char *GetFilepath(int32_t index) const { + if (!valid(index)) + return ""; + else + return FileInfo[index].FilePath; + } + + //! Get the a filesize of the list + //!\param list index + uint64_t GetFilesize(int32_t index) const; + + //! Is index a dir or a file + //!\param list index + BOOL IsDir(int32_t index) const { + if (!valid(index)) + return false; + return FileInfo[index].isDir; + }; + + //! Get the filecount of the whole list + int32_t GetFilecount() const { + return FileInfo.size(); + }; + + //! Sort list by filepath + void SortList(); + + //! Custom sort command for custom sort functions definitions + void SortList(BOOL (*SortFunc)(const DirEntry &a, const DirEntry &b)); + + //! Get the index of the specified filename + int32_t GetFileIndex(const char *filename) const; + + //! Enum for search/filter flags + enum { + Files = 0x01, + Dirs = 0x02, + CheckSubfolders = 0x08, + }; + +protected: + // Internal parser + BOOL InternalLoadPath(std::string &path); + + //!Add a list entrie + void AddEntrie(const std::string &filepath, const char *filename, BOOL isDir); + + //! Clear the list + void ClearList(); + + //! Check if valid pos is requested + inline BOOL valid(uint32_t pos) const { + return (pos < FileInfo.size()); + }; + + uint32_t Flags; + uint32_t Depth; + const char *Filter; + std::vector FileInfo; +}; + +#endif diff --git a/src/utils/ElfUtils.c b/src/utils/ElfUtils.c index 7b5ba9e..d905747 100644 --- a/src/utils/ElfUtils.c +++ b/src/utils/ElfUtils.c @@ -1,43 +1,68 @@ -#include -#include - +#include "utils/logger.h" #include #include #include +#include +#include #include +#include +#include +#include #include -#include -#include -#include #include "elf_abi.h" -int32_t LoadFileToMem(const char *relativefilepath, char **fileOut, uint32_t *sizeOut) { - char path[256]; - int result = 0; - const char *sdRootPath = ""; - if (!WHBMountSdCard()) { - DEBUG_FUNCTION_LINE("Failed to mount SD Card..."); - result = -1; - goto exit; +int32_t LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_t *size) { + //! always initialze input + *inbuffer = NULL; + if (size) { + *size = 0; } - sdRootPath = WHBGetSdCardMountPath(); - sprintf(path, "%s/%s", sdRootPath, relativefilepath); - - DEBUG_FUNCTION_LINE("Loading file %s.", path); - - *fileOut = WHBReadWholeFile(path, sizeOut); - if (!(*fileOut)) { - result = -2; - DEBUG_FUNCTION_LINE("WHBReadWholeFile(%s) returned NULL", path); - goto exit; + int32_t iFd = open(filepath, O_RDONLY); + if (iFd < 0) { + return -1; } -exit: - WHBUnmountSdCard(); - WHBDeInitFileSystem(); - return result; + uint32_t filesize = lseek(iFd, 0, SEEK_END); + lseek(iFd, 0, SEEK_SET); + + uint8_t *buffer = (uint8_t *) memalign(0x40, (filesize + 0x3F) & ~(0x3F)); + if (buffer == NULL) { + close(iFd); + return -2; + } + + uint32_t blocksize = 0x20000; + uint32_t done = 0; + int32_t readBytes = 0; + + while (done < filesize) { + if (done + blocksize > filesize) { + blocksize = filesize - done; + } + readBytes = read(iFd, buffer + done, blocksize); + if (readBytes <= 0) + break; + done += readBytes; + } + + close(iFd); + + if (done != filesize) { + free(buffer); + buffer = NULL; + return -3; + } + + *inbuffer = buffer; + + //! size is optional input + if (size) { + *size = filesize; + } + + return filesize; } static void InstallMain(void *data_elf); @@ -49,7 +74,7 @@ static unsigned int get_section(void *data, const char *name, unsigned int *size uint32_t load_loader_elf_from_sd(unsigned char *baseAddress, const char *relativePath) { char *elf_data = NULL; uint32_t fileSize = 0; - if (LoadFileToMem(relativePath, &elf_data, &fileSize) != 0) { + if (LoadFileToMem(relativePath, &elf_data, &fileSize) < 0) { return 0; } @@ -62,7 +87,7 @@ uint32_t load_loader_elf_from_sd(unsigned char *baseAddress, const char *relativ uint32_t res = ehdr->e_entry; - MEMFreeToDefaultHeap((void *) elf_data); + free((void *) elf_data); return res; } diff --git a/src/utils/ElfUtils.h b/src/utils/ElfUtils.h index 0dbe83f..b5cc87c 100644 --- a/src/utils/ElfUtils.h +++ b/src/utils/ElfUtils.h @@ -2,5 +2,5 @@ #include -extern "C" int32_t LoadFileToMem(const char *relativefilepath, char **fileOut, uint32_t *sizeOut); -extern "C" uint32_t load_loader_elf_from_sd(unsigned char *baseAddress, const char *relativePath); +extern "C" int32_t LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_t *size); +extern "C" uint32_t load_loader_elf_from_sd(unsigned char *baseAddress, const char *relativePath); \ No newline at end of file