Perfect homebrew loading

This commit is contained in:
TheFloW 2016-01-24 21:39:19 +01:00
parent b9f5332652
commit cfc42c15ff
14 changed files with 164 additions and 30 deletions

View File

@ -11,7 +11,8 @@ OBJS += $(FEXCSRCS:.c=.o) $(FEXCPPSRCS:.cpp=.o)
RESOURCES_PNG = resources/battery.png resources/battery_bar_green.png resources/battery_bar_red.png
RESOURCES_TXT = resources/english_us_translation.txt
OBJS += $(RESOURCES_PNG:.png=.o) $(RESOURCES_TXT:.txt=.o)
PAYLOAD_BIN = payload/payload.bin
OBJS += $(RESOURCES_PNG:.png=.o) $(RESOURCES_TXT:.txt=.o) $(PAYLOAD_BIN:.bin=.o)
#stubs.o include this crashes fex!!!
@ -52,6 +53,8 @@ $(TARGET).elf: $(OBJS)
$(PREFIX)-ld -r -b binary -o $@ $^
%.o: %.txt
$(PREFIX)-ld -r -b binary -o $@ $^
%.o: %.bin
$(PREFIX)-ld -r -b binary -o $@ $^
clean:
@rm -rf $(TARGET).velf $(TARGET).elf $(OBJS)

View File

@ -37,7 +37,8 @@
int sceKernelCreateLwMutex(void *work, const char *name, SceUInt attr, int initCount, void *option);
int sceKernelDeleteLwMutex(void *work);
static int launch_counter = 0;
static void *code_memory = NULL;
static SceUID code_blockid = INVALID_UID;
static void *uvl_backup = NULL;
static uint32_t uvl_addr = 0;
@ -93,6 +94,12 @@ SceModuleInfo *getElfModuleInfo(void *buf) {
return (SceModuleInfo *)((uint32_t)buf + program[index].p_offset + offset);
}
void initCodeMemory() {
unsigned int length = MAX_CODE_SIZE;
code_memory = uvl_alloc_code_mem(&length);
code_blockid = sceKernelFindMemBlockByAddr(code_memory, 0);
}
void initHomebrewPatch() {
force_exit = 0;
exited = 0;
@ -129,8 +136,6 @@ void initHomebrewPatch() {
}
void loadHomebrew(char *file) {
debugPrintf("%d. launch\n", launch_counter++);
// Finish netdbg
netdbg_fini();
@ -147,6 +152,9 @@ void loadHomebrew(char *file) {
// Init
initVita2dLib();
initSceAppUtil();
// Init netdbg
netdbg_init();
}
void finishGxm() {
@ -744,8 +752,22 @@ int sceKernelGetMemBlockBasePatchedUVL(SceUID uid, void **basep) {
return res;
}
SceUID sceKernelFindMemBlockByAddrPatchedUVL(const void *addr, SceSize size) {
debugPrintf("%s 0x%08X\n", __FUNCTION__, code_blockid);
return code_blockid;
}
int sceKernelFreeMemBlockPatchedUVL(SceUID uid) {
debugPrintf("%s 0x%08X\n", __FUNCTION__, uid);
if (uid == code_blockid)
return 0;
return sceKernelFreeMemBlock(uid);
}
SceUID sceIoOpenPatchedUVL(const char *file, int flags, SceMode mode) {
debugPrintf("%s\n", __FUNCTION__);
debugPrintf("%s %s\n", __FUNCTION__, file);
return sceIoOpen(file, flags, mode);
}
@ -772,13 +794,15 @@ int sceIoClosePatchedUVL(SceUID fd) {
PatchValue patches_uvl[] = {
{ -1, (uint32_t)&sceKernelAllocMemBlock, sceKernelAllocMemBlockPatchedUVL },
{ -1, (uint32_t)&sceKernelGetMemBlockBase, sceKernelGetMemBlockBasePatchedUVL },
{ -1, (uint32_t)&sceKernelFindMemBlockByAddr, sceKernelFindMemBlockByAddrPatchedUVL },
{ -1, (uint32_t)&sceKernelFreeMemBlock, sceKernelFreeMemBlockPatchedUVL },
{ -1, (uint32_t)&sceKernelCreateThread, sceKernelCreateThreadPatchedUVL },
{ -1, (uint32_t)&sceKernelWaitThreadEnd, sceKernelWaitThreadEndPatchedUVL },
{ -1, (uint32_t)&sceIoOpen, sceIoOpenPatchedUVL },
{ -1, (uint32_t)&sceIoLseek, sceIoLseekPatchedUVL },
{ -1, (uint32_t)&sceIoRead, sceIoReadPatchedUVL },
{ -1, (uint32_t)&sceIoRead, sceIoReadPatchedUVL }, // COULD NOT BE PATCHED, DIFFERENT NID
{ -1, (uint32_t)&sceIoWrite, sceIoWritePatchedUVL },
{ -1, (uint32_t)&sceIoClose, sceIoClosePatchedUVL },
{ -1, (uint32_t)&sceIoClose, sceIoClosePatchedUVL }, // COULD NOT BE PATCHED, DIFFERENT NID
};
#define N_UVL_PATCHES (sizeof(patches_uvl) / sizeof(PatchValue))
@ -799,7 +823,7 @@ void PatchUVL() {
int count = 0;
uint32_t i = 0;
while (i < UVL_SIZE && count < N_UVL_PATCHES) {
while (i < MAX_UVL_SIZE && count < N_UVL_PATCHES) {
uint32_t addr = uvl_addr + i;
uint32_t value = extractStub(addr);
@ -814,6 +838,9 @@ void PatchUVL() {
i += ((j == N_UVL_PATCHES) ? 0x4 : 0x10);
}
// Make uvl_alloc_code_mem return 0
makeThumbDummyFunction0(extractFunctionStub((uint32_t)&uvl_alloc_code_mem) & ~0x1);
}
void getUVLTextAddr() {
@ -824,8 +851,8 @@ void getUVLTextAddr() {
void backupUVL() {
if (!uvl_backup) {
uvl_backup = malloc(UVL_SIZE);
memcpy(uvl_backup, (void *)uvl_addr, UVL_SIZE);
uvl_backup = malloc(MAX_UVL_SIZE);
memcpy(uvl_backup, (void *)uvl_addr, MAX_UVL_SIZE);
}
}
@ -833,10 +860,10 @@ void restoreUVL() {
if (uvl_backup) {
uvl_unlock_mem();
memcpy((void *)uvl_addr, uvl_backup, UVL_SIZE);
memcpy((void *)uvl_addr, uvl_backup, MAX_UVL_SIZE);
uvl_lock_mem();
uvl_flush_icache((void *)uvl_addr, UVL_SIZE);
uvl_flush_icache((void *)uvl_addr, MAX_UVL_SIZE);
free(uvl_backup);
uvl_backup = NULL;

View File

@ -41,7 +41,8 @@
} \
}
#define UVL_SIZE 0x100000
#define MAX_CODE_SIZE 12 * 1024 * 1024
#define MAX_UVL_SIZE 1 * 1024 * 1024
#define INVALID_UID -1
@ -63,6 +64,8 @@ typedef struct {
void *function;
} PatchValue;
void initCodeMemory();
int isValidElf(char *file);
void loadHomebrew(char *file);

7
init.c
View File

@ -19,6 +19,7 @@
#include "main.h"
#include "init.h"
#include "file.h"
#include "utils.h"
#include "module.h"
extern unsigned char _binary_resources_battery_png_start;
@ -266,9 +267,6 @@ int findScePafFunctions() {
uint32_t scePowerSetGpuClockFrequencyAddr = findModuleImportByInfo(mod_info, text_addr, "ScePower", 0x717DB06C) - text_addr;
uint32_t sceKernelOpenMemBlockAddr = findModuleImportByInfo(mod_info, text_addr, "SceSysmem", 0x8EB8DFBB) - text_addr;
uint32_t sceKernelCloseMemBlockAddr = findModuleImportByInfo(mod_info, text_addr, "SceSysmem", 0xB680E3A0) - text_addr;
uint32_t sceKernelGetSystemSwVersionAddr = findModuleImportByInfo(mod_info, text_addr, "SceModulemgr", 0x5182E212) - text_addr;
uint32_t sceKernelGetModelForCDialogAddr = findModuleImportByInfo(mod_info, text_addr, "SceSysmem", 0xA2CB322F) - text_addr;
@ -288,9 +286,6 @@ int findScePafFunctions() {
if (findModuleByName(modname, &text_addr, &text_size) == 0)
return -2;
copyStub((uint32_t)&sceKernelOpenMemBlock, (void *)text_addr + sceKernelOpenMemBlockAddr);
copyStub((uint32_t)&sceKernelCloseMemBlock, (void *)text_addr + sceKernelCloseMemBlockAddr);
copyStub((uint32_t)&sceKernelGetSystemSwVersion, (void *)text_addr + sceKernelGetSystemSwVersionAddr);
copyStub((uint32_t)&sceKernelGetModelForCDialog, (void *)text_addr + sceKernelGetModelForCDialogAddr);

43
main.c
View File

@ -18,9 +18,9 @@
/*
TODO:
- Fix VitaShell reloading.
- Nethost. Patch UVL to be able to launch from host0
- Terminate thread / free stack of previous VitaShell when reloading
- Fix gxm bug in homebrew.c
- Page skip for hex and text viewer
- Improve homebrew exiting. Compatibility list at http://wololo.net/talk/viewtopic.php?f=113&p=402975#p402975
- Add UTF8/UTF16 to vita2dlib's pgf
@ -819,7 +819,7 @@ int dialogSteps() {
args.archive_path = archive_path;
args.copy_mode = copy_mode;
SceUID thid = sceKernelCreateThread("copy_thread", (SceKernelThreadEntry)copy_thread, 0x10000100, 0x10000, 0, 0x70000, NULL);
SceUID thid = sceKernelCreateThread("copy_thread", (SceKernelThreadEntry)copy_thread, 0x40, 0x10000, 0, 0x70000, NULL);
if (thid >= 0)
sceKernelStartThread(thid, sizeof(CopyArguments), &args);
@ -846,7 +846,7 @@ int dialogSteps() {
args.cur_path = cur_path;
args.index = base_pos + rel_pos;
SceUID thid = sceKernelCreateThread("delete_thread", (SceKernelThreadEntry)delete_thread, 0x10000100, 0x10000, 0, 0x70000, NULL);
SceUID thid = sceKernelCreateThread("delete_thread", (SceKernelThreadEntry)delete_thread, 0x40, 0x10000, 0, 0x70000, NULL);
if (thid >= 0)
sceKernelStartThread(thid, sizeof(DeleteArguments), &args);
@ -1485,9 +1485,37 @@ void freePreviousVitaShell() {
sceKernelFreeMemBlock(sceKernelFindMemBlockByAddr((void *)extractFunctionStub((uint32_t)&sceKernelBacktraceSelf), 0));
}
extern unsigned char _binary_payload_payload_bin_start;
extern unsigned char _binary_payload_payload_bin_end;
extern unsigned char _binary_payload_payload_bin_size; // crashes
typedef struct {
char *path;
int (* uvl_load)(const char *path);
int (* sceKernelExitDeleteThread)(int status);
} PayloadArgs;
void payload() {
unsigned int length = 1 * 1024 * 1024;
void *addr = uvl_alloc_code_mem(&length);
int size = &_binary_payload_payload_bin_end - &_binary_payload_payload_bin_start;
uvl_unlock_mem();
memcpy(addr, &_binary_payload_payload_bin_start, size);
uvl_lock_mem();
uvl_flush_icache(addr, size);
PayloadArgs args = { (void *)uvl_load, (void *)sceKernelExitDeleteThread };
int (* executePayload)(PayloadArgs *args) = (void *)((uint32_t)addr | 0x1);
executePayload(&args);
while (1); // Should not reach this
}
int vitashell_thread(SceSize args, void *argp) {
#ifndef RELEASE
// sceIoRemove("cache0:vitashell_log.txt");
sceIoRemove("cache0:vitashell_log.txt");
#endif
// Free .text and .data segment of previous VitaShell
@ -1496,6 +1524,9 @@ int vitashell_thread(SceSize args, void *argp) {
// Init VitaShell
VitaShellInit();
// Init code memory
initCodeMemory();
// Set up nid table
// setupNidTable();
@ -1527,10 +1558,10 @@ int vitashell_thread(SceSize args, void *argp) {
int main(int argc, const char *argv[]) {
// Start app with bigger stack
SceUID thid = sceKernelCreateThread("VitaShell_main_thread", (SceKernelThreadEntry)vitashell_thread, 0x10000100, 1 * 1024 * 1024, 0, 0x70000, NULL);
SceUID thid = sceKernelCreateThread("vitashell_thread", (SceKernelThreadEntry)vitashell_thread, 0x10000100, 1 * 1024 * 1024, 0, 0x70000, NULL);
if (thid >= 0) {
sceKernelStartThread(thid, argc, argv);
sceKernelWaitThreadEnd(thid, NULL, NULL);
sceKernelWaitThreadEnd(thid, NULL, NULL); // TODO: Only first boot
}
return 0;

View File

@ -165,12 +165,25 @@ void copyStub(uint32_t address, void *function) {
uvl_unlock_mem();
uint32_t *f = (uint32_t *)address;
memcpy((void *)f, function, 0x10);
memcpy((void *)address, function, 0x10);
uvl_lock_mem();
uvl_flush_icache(f, 0x10);
uvl_flush_icache((void *)address, 0x10);
}
void makeThumbDummyFunction0(uint32_t address) {
if (!address)
return;
uvl_unlock_mem();
*(uint16_t *)(address + 0x0) = 0x2000; // movs a1, #0
*(uint16_t *)(address + 0x2) = 0x4770; // bx lr
uvl_lock_mem();
uvl_flush_icache((void *)address, 0x4);
}
uint32_t extractFunctionStub(uint32_t address) {

View File

@ -102,6 +102,7 @@ uint32_t encode_arm_inst(uint8_t type, uint16_t immed, uint16_t reg);
void makeSyscallStub(uint32_t address, uint16_t syscall);
void makeFunctionStub(uint32_t address, void *function);
void copyStub(uint32_t address, void *function);
void makeThumbDummyFunction0(uint32_t address);
uint32_t extractFunctionStub(uint32_t address);
uint32_t extractSyscallStub(uint32_t address);

21
payload/Makefile Normal file
View File

@ -0,0 +1,21 @@
TARGET = payload
OBJS = main.o
PREFIX = arm-vita-eabi
CC = $(PREFIX)-gcc
LD = $(PREFIX)-gcc
OBJCOPY = $(PREFIX)-objcopy
CFLAGS = -fPIE -fno-zero-initialized-in-bss -std=gnu99 -mcpu=cortex-a9 -mthumb-interwork -mthumb
LDFLAGS = -T linker.x -nodefaultlibs -nostdlib -pie
all: $(TARGET)
%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS) $(CFLAGS_THUMB)
$(TARGET): $(OBJS)
$(LD) -o $@ $^ $(LDFLAGS)
$(OBJCOPY) -O binary $@ $@.bin
clean:
rm -rf *~ *.elf *.bin *.s $(TARGET) $(OBJS)

12
payload/linker.x Normal file
View File

@ -0,0 +1,12 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
.text : { *(.text.start) *(.text .text.* .gnu.linkonce.t.*) *(.sceStub.text.*) }
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.data : { *(.data .data.* .gnu.linkonce.d.*) }
.bss : { *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) }
}

28
payload/main.c Normal file
View File

@ -0,0 +1,28 @@
/*
VitaShell
Copyright (C) 2015-2016, TheFloW
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/>.
*/
typedef struct {
char *path;
int (* uvl_load)(const char *path);
int (* sceKernelExitDeleteThread)(int status);
} PayloadArgs;
int __attribute__ ((section (".text.start"))) _start(PayloadArgs *args) {
args->uvl_load(args->path);
return args->sceKernelExitDeleteThread(0);
}

BIN
payload/main.o Normal file

Binary file not shown.

BIN
payload/payload Normal file

Binary file not shown.

BIN
payload/payload.bin Normal file

Binary file not shown.

View File

@ -206,8 +206,8 @@ void getTimeString(char *string, int time_format, SceRtcTime *time) {
int netdbg_init()
{
int ret = 0;
#ifdef NETDBG_ENABLE
int ret;
SceNetSockaddrIn server;
SceNetInitParam initparam;
SceUShort16 port = NETDBG_DEFAULT_PORT;
@ -262,8 +262,8 @@ error_netinit:
net_memory = NULL;
}
error_netstat:
return ret;
#endif
return ret;
}
void netdbg_fini()