mirror of
https://github.com/joel16/VitaShell.git
synced 2024-12-03 09:20:56 +00:00
Perfect homebrew loading
This commit is contained in:
parent
b9f5332652
commit
cfc42c15ff
5
Makefile
5
Makefile
@ -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)
|
||||
|
49
homebrew.c
49
homebrew.c
@ -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;
|
||||
|
@ -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
7
init.c
@ -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
43
main.c
@ -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;
|
||||
|
19
module.c
19
module.c
@ -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) {
|
||||
|
1
module.h
1
module.h
@ -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
21
payload/Makefile
Normal 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
12
payload/linker.x
Normal 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
28
payload/main.c
Normal 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
BIN
payload/main.o
Normal file
Binary file not shown.
BIN
payload/payload
Normal file
BIN
payload/payload
Normal file
Binary file not shown.
BIN
payload/payload.bin
Normal file
BIN
payload/payload.bin
Normal file
Binary file not shown.
4
utils.c
4
utils.c
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user