diff --git a/src/breakpoints/bit.h b/src/breakpoints/bit.h deleted file mode 100644 index b1facd6..0000000 --- a/src/breakpoints/bit.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef TCPGECKO_BIT_UTILITIES_H -#define TCPGECKO_BIT_UTILITIES_H - -// http://stackoverflow.com/a/47990/3764804 -inline unsigned int setBit(unsigned int value, bool bit, int bitIndex) { - return value | (bit << bitIndex); -} - -inline bool getBit(unsigned int value, int bitIndex) { - return ((value >> bitIndex) & 1) == 1; -} - -#endif \ No newline at end of file diff --git a/src/breakpoints/breakpoints.h b/src/breakpoints/breakpoints.h deleted file mode 100644 index 73f2e2b..0000000 --- a/src/breakpoints/breakpoints.h +++ /dev/null @@ -1,87 +0,0 @@ -#include "bit.h" -#include "stringify.h" - -#ifndef TCPGECKO_BREAKPOINTS_H -#define TCPGECKO_BREAKPOINTS_H - -/* Breakpoint types -#define BREAKPOINT_READ 0x01 -#define BREAKPOINT_WRITE 0x02 */ - -struct DataBreakpoint { - unsigned int value; - bool translate; - bool write; - bool read; -} __attribute__((packed)); - -// Special purpose registers -#define INSTRUCTION_ADDRESS_BREAKPOINT_REGISTER 0x3F2 -#define DATA_ADDRESS_BREAKPOINT_REGISTER 0x3F5 - -// Data address breakpoint bit indices -#define TRANSLATE_BIT_INDEX 29 -#define WRITE_BIT_INDEX 30 -#define READ_BIT_INDEX 31 - -// http://www.ds.ewi.tudelft.nl/vakken/in1006/instruction-set/mtspr.html -#define moveToSpecialPurposeRegister(specialPurposeRegister, value) \ - __asm__ __volatile__ ("mtspr %0, %1" : : "K" (specialPurposeRegister), "r" (value)) \ - -// http://elixir.free-electrons.com/linux/v2.6.24/source/include/asm-powerpc/reg.h#L713 -#define moveFromSpecialPurposeRegister(specialPurposeRegister) \ -({unsigned int value; \ -asm volatile("mfspr %0, " __stringify(specialPurposeRegister) : "=r" (value)); \ -value;}) \ - - -// https://www.ibm.com/support/knowledgecenter/en/ssw_aix_71/com.ibm.aix.alangref/idalangref_isync_ics_instrs.htm -static inline void synchronizeInstructions() { - __asm__ __volatile__ ("isync" : : : "memory"); -} - -// https://www.ibm.com/support/knowledgecenter/en/ssw_aix_61/com.ibm.aix.alangref/idalangref_eieio_instrs.htm -static inline void enforeInOrderExecutionOfIO() { - __asm__ __volatile__ ("eieio" : : : "memory"); -} - -static inline void setDataAddressBreakpointRegister(struct DataBreakpoint dataBreakpoint) { - unsigned int value = dataBreakpoint.value; - - // Breakpoint translation - value = setBit(value, dataBreakpoint.translate, TRANSLATE_BIT_INDEX); - - // Write breakpoint - value = setBit(value, dataBreakpoint.write, WRITE_BIT_INDEX); - - // Read breakpoint - value = setBit(value, dataBreakpoint.read, READ_BIT_INDEX); - - moveToSpecialPurposeRegister(DATA_ADDRESS_BREAKPOINT_REGISTER, value); - synchronizeInstructions(); -} - -static inline struct DataBreakpoint getDataAddressBreakpointRegisterContents(struct DataBreakpoint dataBreakpoint) { - unsigned int value = moveFromSpecialPurposeRegister(DATA_ADDRESS_BREAKPOINT_REGISTER); - dataBreakpoint.translate = getBit(value, TRANSLATE_BIT_INDEX); - dataBreakpoint.write = getBit(value, WRITE_BIT_INDEX); - dataBreakpoint.read = getBit(value, READ_BIT_INDEX); - value = setBit(value, 0, TRANSLATE_BIT_INDEX); - value = setBit(value, 0, WRITE_BIT_INDEX); - value = setBit(value, 0, READ_BIT_INDEX); - dataBreakpoint.value = value; - - return dataBreakpoint; -} - -// https://www.manualslib.com/manual/606065/Ibm-Powerpc-750gx.html?page=64 -static inline void setInstructionAddressBreakpointRegister(unsigned int address) { - moveToSpecialPurposeRegister(INSTRUCTION_ADDRESS_BREAKPOINT_REGISTER, address); - synchronizeInstructions(); -} - -static inline int getInstructionAddressBreakpointRegister() { - return moveFromSpecialPurposeRegister(INSTRUCTION_ADDRESS_BREAKPOINT_REGISTER); -} - -#endif \ No newline at end of file diff --git a/src/breakpoints/stringify.h b/src/breakpoints/stringify.h deleted file mode 100644 index b4dd0a7..0000000 --- a/src/breakpoints/stringify.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef TCPGECKO_STRING_H -#define TCPGECKO_STRING_H - -// http://elixir.free-electrons.com/linux/v2.6.24/source/include/linux/stringify.h#L9 -#define __stringify_1(x) #x -#define __stringify(x) __stringify_1(x) - -#endif \ No newline at end of file diff --git a/src/dynamic_libs/os_functions.c b/src/dynamic_libs/os_functions.c index a7cf516..ea07ea6 100644 --- a/src/dynamic_libs/os_functions.c +++ b/src/dynamic_libs/os_functions.c @@ -52,6 +52,20 @@ EXPORT_DECL(int, OSCreateThread, void *thread, s32(*callback)(s32, void * ), s32 priority, u32 attr); +EXPORT_DECL(void, OSEnableInterrupts, void); + +EXPORT_DECL(void, __OSClearAndEnableInterrupt, void); + +EXPORT_DECL(int, OSIsInterruptEnabled, void); + +EXPORT_DECL(int, OSIsDebuggerPresent, void); + +EXPORT_DECL(void, OSRestoreInterrupts, void); + +EXPORT_DECL(void, OSSetDABR, int, int, int, int); + +EXPORT_DECL(void, OSSetIABR, int, int); + EXPORT_DECL(int, OSGetCurrentThread, void); EXPORT_DECL(int, OSResumeThread, void *thread); @@ -103,8 +117,9 @@ EXPORT_DECL(void, __Exit, void); EXPORT_DECL(void, OSFatal, const char *msg); -EXPORT_DECL(void, OSSetExceptionCallback, u8 - exceptionType, exception_callback newCallback); +EXPORT_DECL(void, OSSetExceptionCallback, u8 exceptionType, exception_callback callback); + +EXPORT_DECL(void, __OSSetInterruptHandler, u8 exceptionType, exception_callback callback); EXPORT_DECL(void, DCFlushRange, const void *addr, u32 length); @@ -250,6 +265,7 @@ void InitOSFunctionPointers(void) { OS_FIND_EXPORT(coreinit_handle, OSFatal); OS_FIND_EXPORT(coreinit_handle, OSGetTitleID); OS_FIND_EXPORT(coreinit_handle, OSSetExceptionCallback); + OS_FIND_EXPORT(coreinit_handle, __OSSetInterruptHandler); OS_FIND_EXPORT(coreinit_handle, DCFlushRange); OS_FIND_EXPORT(coreinit_handle, ICInvalidateRange); OS_FIND_EXPORT(coreinit_handle, OSEffectiveToPhysical); @@ -279,6 +295,13 @@ void InitOSFunctionPointers(void) { //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //! Thread functions //!---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + OS_FIND_EXPORT(coreinit_handle, OSEnableInterrupts); + OS_FIND_EXPORT(coreinit_handle, __OSClearAndEnableInterrupt); + OS_FIND_EXPORT(coreinit_handle, OSIsInterruptEnabled); + OS_FIND_EXPORT(coreinit_handle, OSIsDebuggerPresent); + OS_FIND_EXPORT(coreinit_handle, OSRestoreInterrupts); + OS_FIND_EXPORT(coreinit_handle, OSSetDABR); + OS_FIND_EXPORT(coreinit_handle, OSSetIABR); OS_FIND_EXPORT(coreinit_handle, OSGetCurrentThread); OS_FIND_EXPORT(coreinit_handle, OSCreateThread); OS_FIND_EXPORT(coreinit_handle, OSResumeThread); diff --git a/src/dynamic_libs/os_functions.h b/src/dynamic_libs/os_functions.h index 2839bc8..6383b80 100644 --- a/src/dynamic_libs/os_functions.h +++ b/src/dynamic_libs/os_functions.h @@ -140,6 +140,20 @@ extern int (*OSCreateThread)(void *thread, s32 (*callback)(s32, void *), s32 argc, void *args, u32 stack, u32 stack_size, s32 priority, u32 attr); +extern void (*OSEnableInterrupts)(void); + +extern void (*__OSClearAndEnableInterrupt)(void); + +extern int (*OSIsInterruptEnabled)(void); + +extern int (*OSIsDebuggerPresent)(void); + +extern void (*OSRestoreInterrupts)(void); + +extern void (*OSSetDABR)(int, int, int, int); + +extern void (*OSSetIABR)(int, int); + extern int (*OSGetCurrentThread)(void); extern int (*OSResumeThread)(void *thread); @@ -216,7 +230,9 @@ extern int (*OSScreenEnableEx)(unsigned int bufferNum, int enable); typedef unsigned char (*exception_callback)(void *interruptedContext); -extern void (*OSSetExceptionCallback)(u8 exceptionType, exception_callback newCallback); +extern void (*OSSetExceptionCallback)(u8 exceptionType, exception_callback callback); + +extern void (*__OSSetInterruptHandler)(u8 interruptType, exception_callback callback); extern int (*OSAllocFromSystem)(unsigned int size, unsigned int align); diff --git a/src/entry.c b/src/entry.c index 28f12c8..683742c 100644 --- a/src/entry.c +++ b/src/entry.c @@ -5,25 +5,10 @@ #include "pygecko.h" #include "main.h" #include "utils/logger.h" - -#define TITLE_ID_MII_VERSE 0x000500301001600A -#define TITLE_ID_MII_MAKER 0x000500101004A000 -#define TITLE_ID_BAYONETTA_2 0x0005000010172500 -#define TITLE_ID_INTERNET_BROWSER 0x000500301001200A - -bool isRunningTitleID(unsigned long long int japaneseTitleID) { - unsigned long long int currentTitleID = (unsigned long long int) OSGetTitleID(); - return currentTitleID == japaneseTitleID // JAP - || currentTitleID == japaneseTitleID + 0x100 // USA - || currentTitleID == japaneseTitleID + 0x200; // EUR -} +#include "title.h" int __entry_menu(int argc, char **argv) { - if (OSGetTitleID != 0 - && !isRunningTitleID(TITLE_ID_MII_VERSE) - && !isRunningTitleID(TITLE_ID_MII_MAKER) - && !isRunningTitleID(TITLE_ID_BAYONETTA_2) - && !isRunningTitleID(TITLE_ID_INTERNET_BROWSER)) { + if (isRunningAllowedTitleID()) { InitOSFunctionPointers(); InitSocketFunctionPointers(); InitGX2FunctionPointers(); diff --git a/src/entry.h b/src/entry.h deleted file mode 100644 index fbeec53..0000000 --- a/src/entry.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef TCPGECKO_ENTRY_H -#define TCPGECKO_ENTRY_H - -bool isRunningTitleID(unsigned long long int japaneseTitleID); - -#endif \ No newline at end of file diff --git a/src/kernel/syscalls.h b/src/kernel/syscalls.h index 2eaefa7..283aa0d 100644 --- a/src/kernel/syscalls.h +++ b/src/kernel/syscalls.h @@ -7,19 +7,24 @@ extern "C" { #include #include "common/kernel_defs.h" +#include "../common/kernel_defs.h" void KernelSetupSyscalls(void); + void KernelRestoreInstructions(void); void SC0x25_KernelCopyData(unsigned int addr, unsigned int src, unsigned int len); -void SC0x36_KernelReadDBATs(bat_table_t * table); -void SC0x37_KernelWriteDBATs(bat_table_t * table); + +void SC0x36_KernelReadDBATs(bat_table_t *table); + +void SC0x37_KernelWriteDBATs(bat_table_t *table); uint32_t __attribute__ ((noinline)) kern_read(const void *addr); + void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value); #ifdef __cplusplus } #endif -#endif // __KERNEL_FUNCTIONS_H_ +#endif \ No newline at end of file diff --git a/src/pygecko.c b/src/pygecko.c index aea241e..dc4df3f 100644 --- a/src/pygecko.c +++ b/src/pygecko.c @@ -15,7 +15,13 @@ #include "system/exception_handler.h" #include "utils/logger.h" #include "system/memory.h" -#include "breakpoints/breakpoints.h" +#include "system/breakpoints.h" +#include "system/threads.h" +#include "utils/linked_list.h" +#include "assertions.h" +#include "kernel.h" +#include "address.h" +#include "disassembler.h" void *client; void *commandBlock; @@ -48,12 +54,11 @@ struct pygecko_bss_t { #define COMMAND_GET_CODE_HANDLER_ADDRESS 0x55 #define COMMAND_READ_THREADS 0x56 #define COMMAND_ACCOUNT_IDENTIFIER 0x57 -#define COMMAND_WRITE_SCREEN 0x58 // TODO Exception DSI +// #define COMMAND_WRITE_SCREEN 0x58 // TODO Exception DSI #define COMMAND_FOLLOW_POINTER 0x60 #define COMMAND_REMOTE_PROCEDURE_CALL 0x70 #define COMMAND_GET_SYMBOL 0x71 #define COMMAND_MEMORY_SEARCH 0x73 -// #define COMMAND_SYSTEM_CALL 0x80 #define COMMAND_EXECUTE_ASSEMBLY 0x81 #define COMMAND_PAUSE_CONSOLE 0x82 #define COMMAND_RESUME_CONSOLE 0x83 @@ -61,74 +66,23 @@ struct pygecko_bss_t { #define COMMAND_SERVER_VERSION 0x99 #define COMMAND_GET_OS_VERSION 0x9A #define COMMAND_SET_DATA_BREAKPOINT 0xA0 -#define COMMAND_GET_DATA_BREAKPOINT 0xA1 #define COMMAND_SET_INSTRUCTION_BREAKPOINT 0xA2 -#define COMMAND_GET_INSTRUCTION_BREAKPOINT 0xA3 #define COMMAND_RUN_KERNEL_COPY_SERVICE 0xCD -#define COMMAND_IOSUHAX_READ_FILE 0xD0 +#define COMMAND_IOSU_HAX_READ_FILE 0xD0 #define COMMAND_GET_VERSION_HASH 0xE0 #define CHECK_ERROR(cond) if (cond) { bss->line = __LINE__; goto error; } #define errno (*__gh_errno_ptr()) -#define MSG_DONTWAIT 32 +#define MSG_DONT_WAIT 32 #define EWOULDBLOCK 6 #define DATA_BUFFER_SIZE 0x5000 -#define WRITE_SCREEN_MESSAGE_BUFFER_SIZE 100 +// #define WRITE_SCREEN_MESSAGE_BUFFER_SIZE 100 #define SERVER_VERSION "05/24/2017" #define ONLY_ZEROS_READ 0xB0 #define NON_ZEROS_READ 0xBD #define VERSION_HASH 0x39C9444B -#define ASSERT_MINIMUM_HOLDS(actual, minimum, variableName) \ -if(actual < minimum) { \ - char buffer[100] = {0}; \ - __os_snprintf(buffer, 100, "%s: Limit exceeded (minimum: %i, actual: %i)", variableName, minimum, actual); \ - OSFatal(buffer); \ -} \ - -#define ASSERT_MAXIMUM_HOLDS(maximum, actual, variableName) \ -if(actual > maximum) { \ - char buffer[100] = {0}; \ - __os_snprintf(buffer, 100, "%s: Limit exceeded (maximum: %i, actual: %i)", variableName, maximum, actual); \ - OSFatal(buffer); \ -} \ - -#define ASSERT_FUNCTION_SUCCEEDED(returnValue, functionName) \ - if (returnValue < 0) { \ - char buffer[100] = {0}; \ - __os_snprintf(buffer, 100, "%s failed with return value: %i", functionName, returnValue); \ - OSFatal(buffer); \ - } \ - -#define ASSERT_VALID_EFFECTIVE_ADDRESS(effectiveAddress, message) \ - if(!OSIsAddressValid((void *) effectiveAddress)) { \ - char buffer[100] = {0}; \ - __os_snprintf(buffer, 100, "Address %04x invalid: %s", effectiveAddress, message); \ - OSFatal(buffer); \ - } \ - -#define ASSERT_INTEGER(actual, expected, name) \ - if(actual != expected) { \ - char buffer[50] = {0}; \ - __os_snprintf(buffer, 50, "%s assertion failed: %i == %i", name, actual, expected); \ - OSFatal(buffer); \ - } \ - -#define ASSERT_STRING(actual, expected) \ - if(strcmp(actual, expected) != 0) { \ - char buffer[50] = {0}; \ - __os_snprintf(buffer, 50, "String assertion failed: \"%s\" == \"%s\"", actual, expected); \ - OSFatal(buffer); \ - } \ - -#define ASSERT_ALLOCATED(variable, name) \ - if(variable == 0) { \ - char buffer[50] = {0}; \ - __os_snprintf(buffer, 50, "%s allocation failed", name); \ - OSFatal(buffer); \ - } \ - ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); @@ -143,75 +97,20 @@ strm, int flush )); -/*struct breakpoint { - u32 address; - u32 instruction; -}; - -// 10 general breakpoints + 2 step breakpoints -breakpoint breakpoints[12]; - -breakpoint *getBreakpoint(u32 address, int size) { - breakpoint *breakpointsList = breakpoints; - for (int breakpointIndex = 0; breakpointIndex < size; breakpointIndex++) { - if (breakpointsList[breakpointIndex].address == address) { - return &breakpointsList[breakpointIndex]; - } - } - return 0; -}*/ +// ########## Being kernel_copy.h ############ +// TODO Variable size, not hard-coded unsigned char *memcpy_buffer[DATA_BUFFER_SIZE]; void pygecko_memcpy(unsigned char *destinationBuffer, unsigned char *sourceBuffer, unsigned int length) { memcpy(memcpy_buffer, sourceBuffer, length); - SC0x25_KernelCopyData((unsigned int) OSEffectiveToPhysical(destinationBuffer), (unsigned int) &memcpy_buffer, - length); + SC0x25_KernelCopyData((unsigned int) OSEffectiveToPhysical(destinationBuffer), (unsigned int) &memcpy_buffer, length); DCFlushRange(destinationBuffer, (u32) length); } -unsigned char *kernelCopyBuffer[4]; +// ########## End kernel_copy.h ############ -void kernelCopy(unsigned char *destinationBuffer, unsigned char *sourceBuffer, unsigned int length) { - memcpy(kernelCopyBuffer, sourceBuffer, length); - unsigned int destinationAddress = (unsigned int) OSEffectiveToPhysical(destinationBuffer); - SC0x25_KernelCopyData(destinationAddress, (unsigned int) &kernelCopyBuffer, length); - DCFlushRange(destinationBuffer, (u32) length); -} - -#define KERNEL_COPY_SOURCE_ADDRESS 0x10100000 - -int kernelCopyService(int argc, void *argv) { - while (true) { - // Read the destination address from the source address - int destinationAddress = *(int *) KERNEL_COPY_SOURCE_ADDRESS; - - // Avoid crashing - if (OSIsAddressValid((const void *) destinationAddress)) { - // Perform memory copy - unsigned char *valueBuffer = (unsigned char *) (KERNEL_COPY_SOURCE_ADDRESS + 4); - kernelCopy((unsigned char *) destinationAddress, valueBuffer, 4); - - // "Consume" address and value for synchronization with the code handler for instance - *(int *) KERNEL_COPY_SOURCE_ADDRESS = 0; - *(((int *) KERNEL_COPY_SOURCE_ADDRESS) + 1) = 0; - } - } -} - -void startKernelCopyService() { - unsigned int stack = (unsigned int) memalign(0x40, 0x100); - ASSERT_ALLOCATED(stack, "Kernel copy thread stack") - stack += 0x100; - void *thread = memalign(0x40, 0x1000); - ASSERT_ALLOCATED(thread, "Kernel copy thread") - - int status = OSCreateThread(thread, kernelCopyService, 1, NULL, (u32) stack + sizeof(stack), sizeof(stack), 31, - OS_THREAD_ATTR_AFFINITY_CORE1 | OS_THREAD_ATTR_PINNED_AFFINITY | OS_THREAD_ATTR_DETACH); - ASSERT_INTEGER(status, 1, "Creating kernel copy thread") - // OSSetThreadName(thread, "Kernel Copier"); - OSResumeThread(thread); -} +// ########## Being pause.h ############ int (*AVMGetDRCScanMode)(int); @@ -255,10 +154,9 @@ bool isConsolePaused() { return value == PAUSED; } -/*Validates the address range (last address inclusive) but is SLOW on bigger ranges */ -static int validateAddressRange(int starting_address, int ending_address) { - return __OSValidateAddressSpaceRange(1, (void *) starting_address, ending_address - starting_address + 1); -} +// ########## End pause.h ############ + +// ########## Being socket_functions.h ############ static int recvwait(struct pygecko_bss_t *bss, int sock, void *buffer, int len) { int ret; @@ -288,7 +186,7 @@ static int checkbyte(int sock) { unsigned char buffer[1]; int ret; - ret = recv(sock, buffer, 1, MSG_DONTWAIT); + ret = recv(sock, buffer, 1, MSG_DONT_WAIT); if (ret < 0) return ret; if (ret == 0) return -1; return buffer[0]; @@ -315,32 +213,6 @@ static int sendByte(struct pygecko_bss_t *bss, int sock, unsigned char byte) { return sendwait(bss, sock, buffer, 1); } -/*void performSystemCall(int value) { - // TODO Exception DSI? - asm( - "li 0, %0\n" - "sc\n" - "blr\n" - : // No output - :"r"(value) // Input - :"0" // Overwritten register - ); -}*/ - -void writeScreen(char message[100], int secondsDelay) { - // TODO Does nothing then crashes (in games)? - OSScreenClearBufferEx(0, 0); - OSScreenClearBufferEx(1, 0); - - OSScreenPutFontEx(0, 14, 1, message); - OSScreenPutFontEx(1, 14, 1, message); - - sleep(secondsDelay); - - OSScreenFlipBuffersEx(0); - OSScreenFlipBuffersEx(1); -} - void receiveString(struct pygecko_bss_t *bss, int clientfd, char *stringBuffer, @@ -360,6 +232,22 @@ void receiveString(struct pygecko_bss_t *bss, } } +// ########## End socket_functions.h ############ + +/*void writeScreen(char message[100], int secondsDelay) { + // TODO Does nothing then crashes (in games)? + OSScreenClearBufferEx(0, 0); + OSScreenClearBufferEx(1, 0); + + OSScreenPutFontEx(0, 14, 1, message); + OSScreenPutFontEx(1, 14, 1, message); + + sleep(secondsDelay); + + OSScreenFlipBuffersEx(0); + OSScreenFlipBuffersEx(1); +}*/ + void considerInitializingFileSystem() { if (!client) { // Initialize the file system @@ -382,45 +270,6 @@ void considerInitializingFileSystem() { } } -char *disassemblerBuffer; -void *disassemblerBufferPointer; -#define DISASSEMBLER_BUFFER_SIZE 0x1024 - -void formatDisassembled(char *format, ...) { - if (!disassemblerBuffer) { - disassemblerBuffer = malloc(DISASSEMBLER_BUFFER_SIZE); - ASSERT_ALLOCATED(disassemblerBuffer, "Disassembler buffer") - disassemblerBufferPointer = disassemblerBuffer; - } - - va_list variableArguments; - va_start(variableArguments, format); - char *temporaryBuffer; - int printedBytesCount = vasprintf(&temporaryBuffer, format, variableArguments); - ASSERT_ALLOCATED(temporaryBuffer, "Temporary buffer") - ASSERT_MINIMUM_HOLDS(printedBytesCount, 1, "Printed bytes count") - va_end(variableArguments); - - // Do not smash the buffer - long projectedSize = (void *) disassemblerBuffer - disassemblerBufferPointer + printedBytesCount; - if (projectedSize < DISASSEMBLER_BUFFER_SIZE) { - memcpy(disassemblerBuffer, temporaryBuffer, printedBytesCount); - disassemblerBuffer += printedBytesCount; - } - - free(temporaryBuffer); -} - -bool isValidDataAddress(int address) { - return OSIsAddressValid((const void *) address) - && address >= 0x10000000 - && address < 0x50000000; -} - -int roundUpToAligned(int number) { - return (number + 3) & ~0x03; -} - #define ERROR_BUFFER_SIZE 150 void reportIllegalCommandByte(int commandByte) { @@ -431,37 +280,6 @@ void reportIllegalCommandByte(int commandByte) { OSFatal(errorBuffer); } -#define MINIMUM_KERNEL_COMPARE_LENGTH 4 -#define KERNEL_MEMORY_COMPARE_STEP_SIZE 1 - -int kernelMemoryCompare(const void *sourceBuffer, - const void *destinationBuffer, - int length) { - if (length < MINIMUM_KERNEL_COMPARE_LENGTH) { - ASSERT_MINIMUM_HOLDS(length, MINIMUM_KERNEL_COMPARE_LENGTH, "length"); - } - - bool loopEntered = false; - - while (kern_read(sourceBuffer) == kern_read(destinationBuffer)) { - loopEntered = true; - sourceBuffer = (char *) sourceBuffer + KERNEL_MEMORY_COMPARE_STEP_SIZE; - destinationBuffer = (char *) destinationBuffer + KERNEL_MEMORY_COMPARE_STEP_SIZE; - length -= KERNEL_MEMORY_COMPARE_STEP_SIZE; - - if (length <= MINIMUM_KERNEL_COMPARE_LENGTH - 1) { - break; - } - } - - if (loopEntered) { - sourceBuffer -= KERNEL_MEMORY_COMPARE_STEP_SIZE; - destinationBuffer -= KERNEL_MEMORY_COMPARE_STEP_SIZE; - } - - return kern_read(sourceBuffer) - kern_read(destinationBuffer); -} - static int processCommands(struct pygecko_bss_t *bss, int clientfd) { int ret; @@ -1043,7 +861,7 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) { break; } - case COMMAND_IOSUHAX_READ_FILE: { + case COMMAND_IOSU_HAX_READ_FILE: { log_print("COMMAND_IOSUHAX_READ_FILE"); // TODO Crashes console on this call @@ -1139,43 +957,31 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) { break; } case COMMAND_READ_THREADS: { - int OS_THREAD_SIZE = 0x6A0; + struct node *threads = getAllThreads(); + int threadCount = length(threads); + log_printf("Thread Count: %i\n", threadCount); - int currentThreadAddress = OSGetCurrentThread(); - ASSERT_VALID_EFFECTIVE_ADDRESS(currentThreadAddress, "OSGetCurrentThread") - int iterationThreadAddress = currentThreadAddress; - int temporaryThreadAddress; + // Send the thread count + log_print("Sending thread count...\n"); + ((int *) buffer)[0] = threadCount; + ret = sendwait(bss, clientfd, buffer, sizeof(int)); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (thread count)"); - // Follow "previous thread" pointers back to the beginning - while ((temporaryThreadAddress = *(int *) (iterationThreadAddress + 0x390)) != 0) { - iterationThreadAddress = temporaryThreadAddress; - ASSERT_VALID_EFFECTIVE_ADDRESS(iterationThreadAddress, "iterationThreadAddress going backwards") + // Send the thread addresses and data + struct node* currentThread = threads; + while (currentThread != NULL) { + int data = (int) currentThread->data; + log_printf("Thread data: %08x\n", data); + ((int *) buffer)[0] = (int) currentThread->data; + memcpy(buffer + sizeof(int), currentThread->data, THREAD_SIZE); + log_print("Sending node...\n"); + ret = sendwait(bss, clientfd, buffer, sizeof(int) + THREAD_SIZE); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (thread address and data)") + + currentThread = currentThread->next; } - // Send all threads by following the "next thread" pointers - while ((temporaryThreadAddress = *(int *) (iterationThreadAddress + 0x38C)) != 0) { - // Send the starting thread's address - ((int *) buffer)[0] = iterationThreadAddress; - - // Send the thread struct itself - memcpy(buffer + 4, (void *) iterationThreadAddress, OS_THREAD_SIZE); - ret = sendwait(bss, clientfd, buffer, 4 + OS_THREAD_SIZE); - CHECK_ERROR(ret < 0) - - iterationThreadAddress = temporaryThreadAddress; - ASSERT_VALID_EFFECTIVE_ADDRESS(iterationThreadAddress, "iterationThreadAddress going forwards") - } - - // The previous while would skip the last thread so send it also - ((int *) buffer)[0] = iterationThreadAddress; - memcpy(buffer + 4, (void *) iterationThreadAddress, OS_THREAD_SIZE); - ret = sendwait(bss, clientfd, buffer, 4 + OS_THREAD_SIZE); - CHECK_ERROR(ret < 0) - - // Let the client know that no more threads are coming - ((int *) buffer)[0] = 0; - ret = sendwait(bss, clientfd, buffer, 4); - CHECK_ERROR(ret < 0) + destroy(threads); break; } @@ -1212,7 +1018,7 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) { break; } - case COMMAND_WRITE_SCREEN: { + /*case COMMAND_WRITE_SCREEN: { char message[WRITE_SCREEN_MESSAGE_BUFFER_SIZE]; ret = recvwait(bss, clientfd, buffer, 4); ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (write screen seconds)") @@ -1221,7 +1027,7 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) { writeScreen(message, seconds); break; - } + }*/ case COMMAND_FOLLOW_POINTER: { ret = recvwait(bss, clientfd, buffer, 8); ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (Pointer address and offsets count)") @@ -1374,16 +1180,6 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) { break; } - /*case COMMAND_SYSTEM_CALL: { - ret = recvwait(bss, clientfd, buffer, 4); - ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (system call)") - - int value = ((int *) buffer)[0]; - - performSystemCall(value); - - break; - }*/ case COMMAND_EXECUTE_ASSEMBLY: { // Receive the assembly receiveString(bss, clientfd, (char *) buffer, DATA_BUFFER_SIZE); @@ -1441,47 +1237,30 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) { break; } case COMMAND_SET_DATA_BREAKPOINT: { - ret = recvwait(bss, clientfd, buffer, 4 + 3 * 1); + // Read the data from the client + ret = recvwait(bss, clientfd, buffer, sizeof(int) + sizeof(bool) * 2); ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (data breakpoint)"); + + // Parse the data and set the breakpoint int bufferIndex = 0; unsigned int address = ((unsigned int *) buffer)[bufferIndex]; - bufferIndex += 4; - bool translate = buffer[bufferIndex++]; - bool write = buffer[bufferIndex++]; + bufferIndex += sizeof(int); bool read = buffer[bufferIndex]; - struct DataBreakpoint dataBreakpoint; - dataBreakpoint.value = address; - dataBreakpoint.translate = translate; - dataBreakpoint.write = write; - dataBreakpoint.read = read; - setDataAddressBreakpointRegister(dataBreakpoint); - - break; - } - case COMMAND_GET_DATA_BREAKPOINT: { - struct DataBreakpoint dataBreakpoint; - getDataAddressBreakpointRegisterContents(dataBreakpoint); - int structureSize = sizeof(dataBreakpoint); - memcpy(buffer, (const void *) &dataBreakpoint, structureSize); - ret = sendwait(bss, clientfd, buffer, structureSize); - ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (data breakpoint)"); + bufferIndex += sizeof(bool); + bool write = buffer[bufferIndex]; + bufferIndex += sizeof(bool); + setDataAddressBreakPointRegister(address, read, write); break; } case COMMAND_SET_INSTRUCTION_BREAKPOINT: { - // Read the address and set the breakpoint execute + // Read the address ret = recvwait(bss, clientfd, buffer, sizeof(int)); ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (instruction breakpoint)"); - unsigned int address = ((unsigned int *) buffer)[0]; - setInstructionAddressBreakpointRegister(address); - break; - } - case COMMAND_GET_INSTRUCTION_BREAKPOINT: { - int address = getInstructionAddressBreakpointRegister(); - ((int *) buffer)[0] = address; - ret = sendwait(bss, clientfd, buffer, sizeof(int)); - ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (instruction breakpoint)"); + // Parse the address and set the breakpoint + unsigned int address = ((unsigned int *) buffer)[0]; + setInstructionAddressBreakPointRegister(address); break; } @@ -1513,7 +1292,7 @@ struct pygecko_bss_t *bss; static int runTCPGeckoServer(int argc, void *argv) { bss = argv; - setup_os_exceptions(); + // setup_os_exceptions(); socket_lib_init(); log_init(COMPUTER_IP_ADDRESS); diff --git a/src/pygecko.h b/src/pygecko.h index 1945fdd..d483633 100644 --- a/src/pygecko.h +++ b/src/pygecko.h @@ -1,15 +1,11 @@ #ifndef _PYGECKO_H_ #define _PYGECKO_H_ -#include "common/types.h" -#include "dynamic_libs/os_functions.h" - /* Main */ #ifdef __cplusplus extern "C" { #endif -//! C wrapper for our C++ functions void startTCPGecko(void); #ifdef __cplusplus diff --git a/src/system/exception_handler.c b/src/system/exception_handler.c index d5b63b2..9c7bee0 100644 --- a/src/system/exception_handler.c +++ b/src/system/exception_handler.c @@ -3,167 +3,142 @@ #include "../utils/logger.h" #include "exception_handler.h" -#define OS_EXCEPTION_MODE_GLOBAL_ALL_CORES 4 - -#define OS_EXCEPTION_DSI 2 -#define OS_EXCEPTION_ISI 3 -#define OS_EXCEPTION_PROGRAM 6 - -/* Exceptions */ -typedef struct OSContext -{ - /* OSContext identifier */ - uint32_t tag1; - uint32_t tag2; - - /* GPRs */ - uint32_t gpr[32]; - - /* Special registers */ - uint32_t cr; - uint32_t lr; - uint32_t ctr; - uint32_t xer; - - /* Initial PC and MSR */ - uint32_t srr0; - uint32_t srr1; - - /* Only valid during DSI exception */ - uint32_t exception_specific0; - uint32_t exception_specific1; - - /* There is actually a lot more here but we don't need the rest*/ -} OSContext; - -#define CPU_STACK_TRACE_DEPTH 10 -#define __stringify(rn) #rn - -#define mfspr(_rn) \ -({ register uint32_t _rval = 0; \ - asm volatile("mfspr %0," __stringify(_rn) \ - : "=r" (_rval));\ - _rval; \ -}) - -typedef struct _framerec { - struct _framerec *up; - void *lr; -} frame_rec, *frame_rec_t; - static const char *exception_names[] = { - "DSI", - "ISI", - "PROGRAM" + "DSI", + "ISI", + "PROGRAM" }; static const char exception_print_formats[18][45] = { - "Exception type %s occurred!\n", // 0 - "GPR00 %08X GPR08 %08X GPR16 %08X GPR24 %08X\n", // 1 - "GPR01 %08X GPR09 %08X GPR17 %08X GPR25 %08X\n", // 2 - "GPR02 %08X GPR10 %08X GPR18 %08X GPR26 %08X\n", // 3 - "GPR03 %08X GPR11 %08X GPR19 %08X GPR27 %08X\n", // 4 - "GPR04 %08X GPR12 %08X GPR20 %08X GPR28 %08X\n", // 5 - "GPR05 %08X GPR13 %08X GPR21 %08X GPR29 %08X\n", // 6 - "GPR06 %08X GPR14 %08X GPR22 %08X GPR30 %08X\n", // 7 - "GPR07 %08X GPR15 %08X GPR23 %08X GPR31 %08X\n", // 8 - "LR %08X SRR0 %08x SRR1 %08x\n", // 9 - "DAR %08X DSISR %08X\n", // 10 - "\nSTACK DUMP:", // 11 - " --> ", // 12 - " -->\n", // 13 - "\n", // 14 - "%p", // 15 - "\nCODE DUMP:\n", // 16 - "%p: %08X %08X %08X %08X\n", // 17 + "Exception type %s occurred!\n", // 0 + "GPR00 %08X GPR08 %08X GPR16 %08X GPR24 %08X\n", // 1 + "GPR01 %08X GPR09 %08X GPR17 %08X GPR25 %08X\n", // 2 + "GPR02 %08X GPR10 %08X GPR18 %08X GPR26 %08X\n", // 3 + "GPR03 %08X GPR11 %08X GPR19 %08X GPR27 %08X\n", // 4 + "GPR04 %08X GPR12 %08X GPR20 %08X GPR28 %08X\n", // 5 + "GPR05 %08X GPR13 %08X GPR21 %08X GPR29 %08X\n", // 6 + "GPR06 %08X GPR14 %08X GPR22 %08X GPR30 %08X\n", // 7 + "GPR07 %08X GPR15 %08X GPR23 %08X GPR31 %08X\n", // 8 + "LR %08X SRR0 %08x SRR1 %08x\n", // 9 + "DAR %08X DSISR %08X\n", // 10 + "\nSTACK DUMP:", // 11 + " --> ", // 12 + " -->\n", // 13 + "\n", // 14 + "%p", // 15 + "\nCODE DUMP:\n", // 16 + "%p: %08X %08X %08X %08X\n", // 17 }; -static unsigned char exception_cb(void * c, unsigned char exception_type) { - char buf[850]; - int pos = 0; +static unsigned char exceptionCallback(void *c, unsigned char exception_type) { + char stackTraceBuffer[850]; + int pos = 0; - OSContext *context = (OSContext *) c; - /* - * This part is mostly from libogc. Thanks to the devs over there. - */ - pos += sprintf(buf + pos, exception_print_formats[0], exception_names[exception_type]); - pos += sprintf(buf + pos, exception_print_formats[1], context->gpr[0], context->gpr[8], context->gpr[16], context->gpr[24]); - pos += sprintf(buf + pos, exception_print_formats[2], context->gpr[1], context->gpr[9], context->gpr[17], context->gpr[25]); - pos += sprintf(buf + pos, exception_print_formats[3], context->gpr[2], context->gpr[10], context->gpr[18], context->gpr[26]); - pos += sprintf(buf + pos, exception_print_formats[4], context->gpr[3], context->gpr[11], context->gpr[19], context->gpr[27]); - pos += sprintf(buf + pos, exception_print_formats[5], context->gpr[4], context->gpr[12], context->gpr[20], context->gpr[28]); - pos += sprintf(buf + pos, exception_print_formats[6], context->gpr[5], context->gpr[13], context->gpr[21], context->gpr[29]); - pos += sprintf(buf + pos, exception_print_formats[7], context->gpr[6], context->gpr[14], context->gpr[22], context->gpr[30]); - pos += sprintf(buf + pos, exception_print_formats[8], context->gpr[7], context->gpr[15], context->gpr[23], context->gpr[31]); - pos += sprintf(buf + pos, exception_print_formats[9], context->lr, context->srr0, context->srr1); + OSContext *context = (OSContext *) c; + /* + * This part is mostly from libogc. Thanks to the devs over there. + */ + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[0], exception_names[exception_type]); + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[1], context->gpr[0], context->gpr[8], + context->gpr[16], + context->gpr[24]); + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[2], context->gpr[1], context->gpr[9], + context->gpr[17], + context->gpr[25]); + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[3], context->gpr[2], context->gpr[10], + context->gpr[18], + context->gpr[26]); + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[4], context->gpr[3], context->gpr[11], + context->gpr[19], + context->gpr[27]); + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[5], context->gpr[4], context->gpr[12], + context->gpr[20], + context->gpr[28]); + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[6], context->gpr[5], context->gpr[13], + context->gpr[21], + context->gpr[29]); + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[7], context->gpr[6], context->gpr[14], + context->gpr[22], + context->gpr[30]); + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[8], context->gpr[7], context->gpr[15], + context->gpr[23], + context->gpr[31]); + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[9], context->lr, context->srr0, context->srr1); //if(exception_type == OS_EXCEPTION_DSI) { - pos += sprintf(buf + pos, exception_print_formats[10], context->exception_specific1, context->exception_specific0); // this freezes + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[10], context->exception_specific1, + context->exception_specific0); // this freezes //} - void *pc = (void*)context->srr0; - void *lr = (void*)context->lr; - void *r1 = (void*)context->gpr[1]; - register uint32_t i = 0; - register frame_rec_t l,p = (frame_rec_t)lr; + void *pc = (void *) context->srr0; + void *lr = (void *) context->lr; + void *r1 = (void *) context->gpr[1]; + register uint32_t currentStackTraceDepth = 0; + register frame_rec_t l, p = (frame_rec_t) lr; l = p; p = r1; - if(!p) - asm volatile("mr %0,%%r1" : "=r"(p)); + if (!p) + asm volatile("mr %0,%%r1" : "=r"(p)); - pos += sprintf(buf + pos, exception_print_formats[11]); + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[11]); - for(i = 0; i < CPU_STACK_TRACE_DEPTH-1 && p->up; p = p->up, i++) { - if(i % 4) - pos += sprintf(buf + pos, exception_print_formats[12]); + for (currentStackTraceDepth = 0; + currentStackTraceDepth < CPU_STACK_TRACE_DEPTH - 1 && p->up; p = p->up, currentStackTraceDepth++) { + if (currentStackTraceDepth % 4) + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[12]); else { - if(i > 0) - pos += sprintf(buf + pos, exception_print_formats[13]); + if (currentStackTraceDepth > 0) + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[13]); else - pos += sprintf(buf + pos, exception_print_formats[14]); + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[14]); } - switch(i) { + switch (currentStackTraceDepth) { case 0: - if(pc) - pos += sprintf(buf + pos, exception_print_formats[15],pc); + if (pc) + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[15], pc); break; case 1: - if(!l) - l = (frame_rec_t)mfspr(8); - pos += sprintf(buf + pos, exception_print_formats[15],(void*)l); + if (!l) + l = (frame_rec_t) mfspr(8); + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[15], (void *) l); break; default: - pos += sprintf(buf + pos, exception_print_formats[15],(void*)(p->up->lr)); + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[15], (void *) (p->up->lr)); break; } } //if(exception_type == OS_EXCEPTION_DSI) { - uint32_t *pAdd = (uint32_t*)context->srr0; - pos += sprintf(buf + pos, exception_print_formats[16]); - // TODO by Dimok: this was actually be 3 instead of 2 lines in libogc .... but there is just no more space anymore on the screen - for (i = 0; i < 8; i += 4) - pos += sprintf(buf + pos, exception_print_formats[17], &(pAdd[i]),pAdd[i], pAdd[i+1], pAdd[i+2], pAdd[i+3]); + uint32_t *pAdd = (uint32_t *) context->srr0; + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[16]); + // TODO by Dimok: this was actually be 3 instead of 2 lines in libogc .... but there is just no more space anymore on the screen + for (currentStackTraceDepth = 0; currentStackTraceDepth < 8; currentStackTraceDepth += 4) + pos += sprintf(stackTraceBuffer + pos, exception_print_formats[17], &(pAdd[currentStackTraceDepth]), + pAdd[currentStackTraceDepth], pAdd[currentStackTraceDepth + 1], pAdd[currentStackTraceDepth + 2], + pAdd[currentStackTraceDepth + 3]); //} - log_print(buf); - OSFatal(buf); - return 1; + log_print(stackTraceBuffer); + OSFatal(stackTraceBuffer); + + return 1; } -static unsigned char dsi_exception_cb(void * context) { - return exception_cb(context, 0); -} -static unsigned char isi_exception_cb(void * context) { - return exception_cb(context, 1); -} -static unsigned char program_exception_cb(void * context) { - return exception_cb(context, 2); +static unsigned char dsi_exception_cb(void *context) { + return exceptionCallback(context, 0); } -void setup_os_exceptions(void) { - OSSetExceptionCallback(OS_EXCEPTION_DSI, &dsi_exception_cb); - OSSetExceptionCallback(OS_EXCEPTION_ISI, &isi_exception_cb); - OSSetExceptionCallback(OS_EXCEPTION_PROGRAM, &program_exception_cb); +static unsigned char isi_exception_cb(void *context) { + return exceptionCallback(context, 1); +} + +static unsigned char program_exception_cb(void *context) { + return exceptionCallback(context, 2); +} + +void setup_os_exceptions() { + OSSetExceptionCallback(OS_EXCEPTION_DSI, &dsi_exception_cb); + OSSetExceptionCallback(OS_EXCEPTION_ISI, &isi_exception_cb); + OSSetExceptionCallback(OS_EXCEPTION_PROGRAM, &program_exception_cb); } \ No newline at end of file diff --git a/src/system/exception_handler.h b/src/system/exception_handler.h index 7626f92..a464522 100644 --- a/src/system/exception_handler.h +++ b/src/system/exception_handler.h @@ -5,6 +5,52 @@ extern "C" { #endif +#include "../utils/stringify.h" + +#define OS_EXCEPTION_DSI 2 +#define OS_EXCEPTION_ISI 3 +#define OS_EXCEPTION_PROGRAM 6 + +/* Exceptions */ +typedef struct OSContext { + /* OSContext identifier */ + uint32_t tag1; + uint32_t tag2; + + /* GPRs */ + uint32_t gpr[32]; + + /* Special registers */ + uint32_t cr; + uint32_t lr; + uint32_t ctr; + uint32_t xer; + + /* Initial PC and MSR */ + uint32_t srr0; + uint32_t srr1; + + /* Only valid during DSI exception */ + uint32_t exception_specific0; + uint32_t exception_specific1; + + /* There is actually a lot more here but we don't need the rest*/ +} OSContext; + +#define CPU_STACK_TRACE_DEPTH 10 + +#define mfspr(_rn) \ +({ register uint32_t _rval = 0; \ + asm volatile("mfspr %0," __stringify(_rn) \ + : "=r" (_rval));\ + _rval; \ +}) + +typedef struct _framerec { + struct _framerec *up; + void *lr; +} frame_rec, *frame_rec_t; + void setup_os_exceptions(void); #ifdef __cplusplus diff --git a/src/utils/utils.c b/src/utils/utils.c deleted file mode 100644 index 09123fe..0000000 --- a/src/utils/utils.c +++ /dev/null @@ -1,27 +0,0 @@ - - -void m_DCFlushRange(unsigned int startAddr, unsigned int size) -{ - register unsigned int addr = startAddr & ~0x1F; - register unsigned int end_addr = startAddr + size; - - while(addr < end_addr) - { - asm volatile("dcbf 0, %0" : : "r"(addr)); - addr += 0x20; - } - asm volatile("sync; eieio"); -} - - -void m_DCInvalidateRange(unsigned int startAddr, unsigned int size) -{ - register unsigned int addr = startAddr & ~0x1F; - register unsigned int end_addr = startAddr + size; - - while(addr < end_addr) - { - asm volatile("dcbi 0, %0" : : "r"(addr)); - addr += 0x20; - } -} diff --git a/tcpgecko.elf b/tcpgecko.elf index 26780d1..71a64bf 100644 Binary files a/tcpgecko.elf and b/tcpgecko.elf differ