From 40ba5db3b3c699d23cf2f740ded73d76153166fa Mon Sep 17 00:00:00 2001 From: 0verjoY <59394546+0verjoY@users.noreply.github.com> Date: Thu, 21 Jul 2022 23:29:45 +0200 Subject: [PATCH] - Added support for arguments in app launch code - Added XML stuff to parse the meta.xml file Notes: - To build.. this now requires the mxml lib --- Makefile | 2 +- data/appboot.bin | Bin 1680 -> 1816 bytes source/appboot.c | 46 ++++++++--- source/appmetadata.c | 180 ++++++++++++++++++++++++++++++++++++++++++ source/appmetadata.h | 20 +++++ source/boot/loadelf.c | 5 -- source/boot/main.c | 19 +++++ source/boot/utils.h | 8 ++ 8 files changed, 263 insertions(+), 17 deletions(-) create mode 100644 source/appmetadata.c create mode 100644 source/appmetadata.h diff --git a/Makefile b/Makefile index a76983e..442c112 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,7 @@ LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map #--------------------------------------------------------------------------------- # any extra libraries we wish to link with the project #--------------------------------------------------------------------------------- -LIBS := -ltinysmb -lpng -lfat -lwiidrc -lwiiuse -lbte -logc -lm -lz -lwiilight +LIBS := -lmxml -ltinysmb -lpng -lfat -lwiidrc -lwiiuse -lbte -logc -lm -lz -lwiilight #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing diff --git a/data/appboot.bin b/data/appboot.bin index 2b50077ca5f016cbee0cda30b462420d8019c850..d8712d215441d0e5b52d0ed2be053eb6b76d4067 100644 GIT binary patch delta 250 zcmbQhJAW5L=+3o`J`M zfu*n}Q@TQjlYzmpi9rG)#wrUE1FGThU|#EMWOKmuSu`-P)GB*d03BvHF+rTsU=oYU#yMYD0ZwB(>Hq)$ delta 145 zcmbQiH-Wc)isJtVH5^RKCNMInOn%59Q)ACvVXH8SVWK?)PeVNej|T(u*P2Y}3LQ=c z2FE4_35XcWLXa3x4TlE7NfIX32o#5^7Xh(rHJO+BHLxfG)p8^-FfdrwGbl80 XGqBWfFi*bCBsh5i3(sa1#xJY@ED|Ia diff --git a/source/appboot.c b/source/appboot.c index 3f39831..25f5c0a 100644 --- a/source/appboot.c +++ b/source/appboot.c @@ -2,18 +2,21 @@ #include #include #include +#include #include #include #include "fat.h" #include "sys.h" -#include "wpad.h" +#include "appmetadata.h" extern void __exception_closeall(); -//struct __argv arguments; -//char* m_argv[MAX_ARGV]; -//u8* m_Buffer = NULL; +struct __argv arguments; +char* m_argv[256]; + +u8* metaBuffer = NULL; +u32 metaSize = 0; u8* appBuffer = NULL; u32 appSize = 0; @@ -45,27 +48,48 @@ bool LoadApp(const char* path) { appBuffer = (u8*)0x92000000; - FILE* f = fopen(path, "rb"); + char currentPath[256]; + snprintf(currentPath, sizeof(currentPath), "%s/boot.dol", path); + + FILE* f = fopen(currentPath, "rb"); if (f == NULL) - return false; + { + snprintf(currentPath, sizeof(currentPath), "%s/boot.elf", path); + f = fopen(currentPath, "rb"); + + if (f == NULL) + return false; + } fseek(f, 0, SEEK_END); - u32 size = ftell(f); + appSize = ftell(f); rewind(f); - if (size > 0x1000000) + if (appSize > 0x1000000) { fclose(f); return false; } - u32 ret = fread(appBuffer, 1, size, f); - DCFlushRange(appBuffer, (size + 31) & (~31)); + u32 ret = fread(appBuffer, 1, appSize, f); + DCFlushRange(appBuffer, (appSize + 31) & (~31)); fclose(f); - return (ret == size); + snprintf(currentPath, sizeof(currentPath), "%s/meta.xml", path); + u16 argumentsSize = 0; + char* Arguments = LoadArguments(currentPath, &argumentsSize); + + if (Arguments) + { + *(vu32*)0x91000000 = argumentsSize; + memcpy((void*)0x91000020, Arguments, argumentsSize); + DCFlushRange((u8*)0x91000020, argumentsSize); + free(Arguments); + } + + return (ret == appSize); } u8* GetApp(u32* size) diff --git a/source/appmetadata.c b/source/appmetadata.c new file mode 100644 index 0000000..ad74a52 --- /dev/null +++ b/source/appmetadata.c @@ -0,0 +1,180 @@ +#include +#include +#include + +#include "appmetadata.h" + +static char* GetStringValue(mxml_node_t* node, const char* element) +{ + mxml_node_t* elementNode = mxmlFindElement(node, node, element, NULL, NULL, MXML_DESCEND_FIRST); + + if (elementNode) + { + mxml_node_t* current = elementNode->child; + + while (current && current->type != MXML_OPAQUE) + current = mxmlWalkNext(current, elementNode, MXML_NO_DESCEND); + + if (current->type == MXML_OPAQUE) + return current->value.opaque; + } + + return NULL; +} + +static char* GetArgumentValue(mxml_node_t* node) +{ + if (node) + { + mxml_node_t* current = node->child; + + while (current && current->type != MXML_OPAQUE) + current = mxmlWalkNext(current, node, MXML_NO_DESCEND); + + if (current->type == MXML_OPAQUE) + return current->value.opaque; + } + + return NULL; +} + +struct MetaData* LoadMetaData(const char* path) +{ + FILE* f = fopen(path, "rb"); + + if (f == NULL) + return NULL; + + mxml_node_t* meta = mxmlLoadFile(NULL, f, MXML_OPAQUE_CALLBACK); + fclose(f); + + if (!meta) + return NULL; + + mxml_node_t* app = mxmlFindElement(meta, meta, "app", NULL, NULL, MXML_DESCEND_FIRST); + + if (!app) + { + mxmlDelete(meta); + return NULL; + } + + struct MetaData* metaData = (struct MetaData*)malloc(sizeof(struct MetaData)); + if (!metaData) + { + mxmlDelete(meta); + return NULL; + } + + memset(metaData, 0, sizeof(struct MetaData)); + + metaData->name = strdup(GetStringValue(app, "name")); + metaData->coder = strdup(GetStringValue(app, "coder")); + metaData->version = strdup(GetStringValue(app, "version")); + metaData->shortDescription = strdup(GetStringValue(app, "short_description")); + metaData->longDescription = strdup(GetStringValue(app, "long_description")); + + char release[40]; + memset(release, 0, sizeof(release)); + snprintf(release, sizeof(release), "%s", GetStringValue(app, "release_date")); + + if (strlen(release) == 14) + snprintf(release, sizeof(release), "%c%c/%c%c/%c%c%c%c", release[4], release[5], release[6], release[7], release[0], release[1], release[2], release[3]); + else if (strlen(release) == 14) + snprintf(release, sizeof(release), "%c%c/%c%c%c%c", release[4], release[5], release[0], release[1], release[2], release[3]); + + metaData->releaseDate = strdup(release); + mxmlDelete(meta); + + return metaData; +} + +void FreeMetaData(struct MetaData* metaData) +{ + free(metaData->name); + free(metaData->coder); + free(metaData->version); + free(metaData->shortDescription); + free(metaData->longDescription); + free(metaData->releaseDate); + free(metaData); +} + +char* LoadArguments(const char* path, u16* length) +{ + FILE* f = fopen(path, "rb"); + + if (f == NULL) + return NULL; + + mxml_node_t* meta = mxmlLoadFile(NULL, f, MXML_OPAQUE_CALLBACK); + + fclose(f); + + if (!meta) + return NULL; + + mxml_node_t* app = mxmlFindElement(meta, meta, "app", NULL, NULL, MXML_DESCEND_FIRST); + + if (!app) + { + mxmlDelete(meta); + return NULL; + } + + app = mxmlFindElement(app, app, "arguments", NULL, NULL, MXML_DESCEND_FIRST); + + if (!app) + { + mxmlDelete(meta); + return NULL; + } + + mxml_node_t* arg; + u16 size = 0; + + for (arg = mxmlFindElement(app, app, "arg", NULL, NULL, MXML_DESCEND_FIRST); arg != NULL; arg = mxmlFindElement(arg, app, "arg", NULL, NULL, MXML_NO_DESCEND)) + { + char* current = GetArgumentValue(arg); + + if (current) + { + if (size > 0) + size++; + + size += strlen(current); + } + } + + if (size == 0 || size > 1024) + { + mxmlDelete(meta); + return NULL; + } + + size++; + char* argStr = malloc(size); + size = 0; + + for (arg = mxmlFindElement(app, app, "arg", NULL, NULL, MXML_DESCEND_FIRST); arg != NULL; arg = mxmlFindElement(arg, app, "arg", NULL, NULL, MXML_NO_DESCEND)) + { + char* current = GetArgumentValue(arg); + + if (current) + { + if (size > 0) + { + argStr[size] = 0; + size++; + } + + strcpy(argStr + size, current); + size += strlen(current); + } + } + + argStr[size] = 0; + *length = size; + + return argStr; +} \ No newline at end of file diff --git a/source/appmetadata.h b/source/appmetadata.h new file mode 100644 index 0000000..3605868 --- /dev/null +++ b/source/appmetadata.h @@ -0,0 +1,20 @@ +#ifndef __APPMETADATA_H__ +#define __APPMETADATA_H__ + +#include + +struct MetaData +{ + char* name; + char* coder; + char* version; + char* shortDescription; + char* longDescription; + char* releaseDate; +}; + +struct MetaData* LoadMetaData(const char* path); +void FreeMetaData(struct MetaData* metaData); +char* LoadArguments(const char* path, u16* length); + +#endif \ No newline at end of file diff --git a/source/boot/loadelf.c b/source/boot/loadelf.c index 4ca0dbb..d1ea085 100644 --- a/source/boot/loadelf.c +++ b/source/boot/loadelf.c @@ -19,16 +19,11 @@ bool ExecIsElf(void* address) u32 LoadElf(void* address) { - //u8* strtab = 0; - //u8* image; int i; struct Elf32_Ehdr* ehdr = (struct Elf32_Ehdr*)address; struct Elf32_Shdr* shdr = (struct Elf32_Shdr*)(address + ehdr->e_shoff + (ehdr->e_shstrndx * sizeof(struct Elf32_Shdr))); - //if (shdr->sh_type == SHT_STRTAB) - // strtab = (u8*)(addr + shdr->sh_offset); - for (i = 0; i < ehdr->e_shnum; i++) { shdr = (struct Elf32_Shdr*)(address + ehdr->e_shoff + (i * sizeof(struct Elf32_Shdr))); diff --git a/source/boot/main.c b/source/boot/main.c index 689fcd4..9fb1c9e 100644 --- a/source/boot/main.c +++ b/source/boot/main.c @@ -1,6 +1,7 @@ #include "loaddol.h" #include "loadelf.h" +#include "utils.h" typedef void (*entrypoint)(); @@ -8,6 +9,8 @@ void _main(void) { void* buffer = (void*)0x92000000; entrypoint entry; + + u32 argumentsSize = *(vu32*)0x91000000; if (ExecIsElf(buffer)) entry = (entrypoint)LoadElf(buffer); @@ -17,5 +20,21 @@ void _main(void) if (!entry) return; + if (argumentsSize > 0) + { + u32* ptr = (u32*)entry; + + if (ptr[1] == 0x5F617267) + { + struct Arguments* argv = (struct Arguments*)&ptr[2]; + + argv->magic = 0x5F617267; + argv->cmdLine = (char*)0x91000020; + argv->length = argumentsSize; + + sync_after_write(&ptr[2], 4); + } + } + entry(); } \ No newline at end of file diff --git a/source/boot/utils.h b/source/boot/utils.h index 96070ee..bc6b61c 100644 --- a/source/boot/utils.h +++ b/source/boot/utils.h @@ -29,6 +29,14 @@ typedef volatile signed long long vs64; typedef s32 size_t; typedef u32 u_int32_t; + +struct Arguments +{ + int magic; + char* cmdLine; + int length; +}; + #define NULL ((void*)0) #define true 1 #define false 0