/* syscall8.h

Copyright (c) 2010 Hermes <www.elotrolado.net>
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are 
permitted provided that the following conditions are met:

- Redistributions of source code must retain the above copyright notice, this list of 
  conditions and the following disclaimer. 
- Redistributions in binary form must reproduce the above copyright notice, this list 
  of conditions and the following disclaimer in the documentation and/or other 
  materials provided with the distribution. 
- The names of the contributors may not be used to endorse or promote products derived 
  from this software without specific prior written permission. 

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/



#ifndef _SYS8_H_
#define _SYS8_H_

#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif


/* 

FUNCTIONS TO USE IN KERNEL AREA 0x8000000000000000 - 0x80000000007fffff

payload V3 is loaded at 0x80000000007ff000

*/

// hook_open
typedef struct
{
	uint64_t compare_addr; // kernel address to compare string
	uint64_t replace_addr; // kernel address to replace string
	int compare_len;       // len of compare string
	int replace_len;       // len of replace string

} path_open_entry;

/* NOTES about path_open_entry:

compare_addr can be a string full path for files or not. The size of the string can be len+1
replacea_ddr can replace a file, files or directories. The size of the string must be replace_string + hook_open string remnant+1 
(recommended 0x800 to work with directories)

// example 1: replacing a file

compare_addr: "/app_home/PS3_GAME/USRDIR/EBOOT.BIN" 
replace_addr: "/dev_usb000/PS3_GAME/USRDIR/EBOOT.BIN" 

compare_len= strlen(compare_addr);
replace_len= strlen(replace_addr);

// example 2: replacing files by a unique file

compare_addr: "/app_home/PS3_GAME/ICON" 
replace_addr: "/dev_usb000/PS3_GAME/ICON0.PNG" 

compare_len= strlen(compare_addr);
replace_len= strlen(replace_addr)+1;

// example 3: replacing directories

compare_addr: "/app_home/PS3_GAME" 
replace_addr: "/dev_usb000/PS3_GAME" 

compare_len= strlen(compare_addr);
replace_len= strlen(replace_addr);

*/

/*
	sys8_disable: disable syscalls 6,7, 36 and stealth syscall 8

	key: 64 bits key to enable syscalls
*/

int sys8_disable(uint64_t key);

/*
	sys8_enable: enable syscalls 6,7, 36 and 8 when 

	key: 64 bits key to enable syscalls or 0 to test

	return: 0x80010003 (<0) or current version (0x100)

*/

int sys8_enable(uint64_t key);

/*
	sys8_memcpy: 64 bits address memory copy

	dst: destination addr

	src: source addr

	size: number of bytes to copy

	return: destination addr

*/

uint64_t sys8_memcpy(uint64_t dst, uint64_t src, uint64_t size);

/*
	sys8_memset: 64 bits address memory set

	dst: destination addr

	val: value to set (only the 8 bits lower)

	size: number of bytes to set

	return: destination addr

*/

uint64_t sys8_memset(uint64_t dst, uint64_t val, uint64_t size);

/*
	sys8_call: kernel 64 bits address to call

	param1: first 64 bits param (maybe IN datas addr)

	param2: second 64 bits param (maybe OUT datas addr)

	return: value returned by kernel call

*/


uint64_t  sys8_call(uint64_t addr, uint64_t param1, uint64_t param2);

/*
	sys8_alloc: kernel function to alloc memory

	size: bytes to alloc

	pool: Usually 0x27 from psjailbreak

	return: 64 bits addr allocated

*/

uint64_t  sys8_alloc(uint64_t size, uint64_t pool);

/*
	sys8_free: kernel function to free memory

	addr: 64 bits addr to free

	pool: Usually 0x27 from psjailbreak

	return: unknown 64 bits addr

*/

uint64_t  sys8_free(uint64_t addr, uint64_t pool);

/*
	sys8_panic: kernel panic function

*/

void sys8_panic(void);

/*
	sys8_perm_mode: function to changes as work 0x80000000000505d0 calls (connected with access permissions)

	mode: 0 -> PS3 perms normally, 1-> Psjailbreak by default, 2-> Special for games as F1 2010 (option by default)

	return: 0 - Ok

*/

int sys8_perm_mode(uint64_t mode);


/*
	sys8_path_table: function to add one table for path redirections in hook_open

	addr_table: kernel 64 bits addr from one path_open_entry array, starts. The last path_open_entry.compare_addr must be 0 to stop

	return: last addr_table

*/

uint64_t sys8_path_table(uint64_t addr_table);


/*

Developers notes:

To test if syscall8 is working:

	int ret= sys8_enable(0);

	if(ret<0) 
		{
		//try to put the correct key

		ret= sys8_enable(key);
		}

	if(ret<0) printf("Sorry, syscall8 unavailable\n");
	else printf("Current version %x\n", ret);

------------------------------------------------------------

To Test sys8_alloc(), sys8_free(), sys8_memcpy() and sys8_call():

	uint32_t my_fun[0x10/4]={0x38601234, 0x4e800020}; // li %r3, 0x1234, blr

	..................................................

	uint64_t memo= sys8_alloc(0x10ULL, 0x27ULL); // alloc 16 bytes

	printf("ret: %llx\n", sys8_call( memo , 0ULL, 0ULL));

	sys8_free( memo  , 0x27ULL)

------------------------------------------------------------

To test path redirections:

	// struct for 3 paths

	typedef struct
	{
		path_open_entry entries[4];

		char arena[0x2000];
	} path_open_table;

	path_open_table open_table;

	uint64_t dest_table_addr;

	..................................................

	// disable table

	printf(" last table %llx\n", sys8_path_table(0ULL));

	// calculate dest_table addr from payload start to back

	dest_table_addr= 0x80000000007FF000ULL-((sizeof(path_open_table)+15) & ~15);

	// fix the start addresses

	open_table.entries[0].compare_addr= ((uint64_t) &open_table.arena[0]) - ((uint64_t) &open_table) + dest_table_addr;
	open_table.entries[0].replace_addr= ((uint64_t) &open_table.arena[0x800])- ((uint64_t) &open_table) + dest_table_addr;

	open_table.entries[1].compare_addr= ((uint64_t) &open_table.arena[0x100]) - ((uint64_t) &open_table) + dest_table_addr;
	open_table.entries[1].replace_addr= ((uint64_t) &open_table.arena[0x1000])- ((uint64_t) &open_table) + dest_table_addr;

	open_table.entries[2].compare_addr= ((uint64_t) &open_table.arena[0x200]) - ((uint64_t) &open_table) + dest_table_addr;
	open_table.entries[2].replace_addr= ((uint64_t) &open_table.arena[0x1800])- ((uint64_t) &open_table) + dest_table_addr;

	open_table.entries[3].compare_addr= 0ULL; // the last entry always 0

	// copy the paths

	strncpy(&open_table.arena[0], "/app_home/PS3_GAME/USRDIR", 0x100);           // compare 1
	strncpy(&open_table.arena[0x800], "/dev_usb000/PS3_GAME/USRDIR", 0x800);     // replace 1: replaces all content or USRDIR

	strncpy(&open_table.arena[0x100], "/app_home/PS3_GAME/ICON0.PNG", 0x100);	 // compare 2
	strncpy(&open_table.arena[0x1000], "/dev_usb000/PS3_GAME/ICON0.PNG", 0x800); // replace 2: replace only ICON0.PNG

	strncpy(&open_table.arena[0x200], "/app_home/PS3_GAME/ICO", 0x100);          // compare 3
	strncpy(&open_table.arena[0x1800], "/dev_usb000/PS3_GAME/ICON0.PNG", 0x800); // replace 3: // replace all ICONxxxx by ICON0.PNG


    // fix the string len

	open_table.entries[0].compare_len= strlen(&open_table.arena[0]);		// 1
	open_table.entries[0].replace_len= strlen(&open_table.arena[0x800]);
	
	open_table.entries[1].compare_len= strlen(&open_table.arena[0x100]);	// 2
	open_table.entries[1].replace_len= strlen(&open_table.arena[0x1000]);

	open_table.entries[2].compare_len= strlen(&open_table.arena[0x200]);    // 3
	open_table.entries[2].replace_len= strlen(&open_table.arena[0x1800]) +1; // truncate the name because it skip  '\0'

	// copy the datas to  the destination address

	sys8_memcpy(dest_table_addr, (uint64_t) &open_table, sizeof(path_open_table));

	// set the path table
	sys8_path_table( dest_table_addr));


*/


#ifdef __cplusplus
  }
#endif

#endif
