RPC File System Read File Issues

Discussion in 'Wii U - Hacking & Backup Loaders' started by BullyWiiPlaza, Nov 27, 2016.

  1. BullyWiiPlaza
    OP

    BullyWiiPlaza Nintendo Hacking <3

    Member
    1,771
    1,439
    Aug 2, 2014
    Germany
    So I've been trying to implement extracting files using RPC in Java. So far most of the code is working but it gets stuck on reading the file. It still opens the file successfully though.

    Code:
    @Test
    public void extractFile() throws IOException
    {
        String filePath = "/vol/content/some/file/that/really/exists";
    
        FileSystemStatus status;
        RemoteFileSystem fileSystem = new RemoteFileSystem();
    
        try (FileSystemClient client = new FileSystemClient();
             FileSystemCommandBlock commandBlock = new FileSystemCommandBlock();
             FileSystemHandle fileDescriptor = new FileSystemHandle();
             FileSystemPath path = new FileSystemPath(filePath);
             FileSystemAccessMode accessMode = new FileSystemAccessMode(FileAccessMode.READ);
             AllocatedMemory destinationBuffer = new AllocatedMemory(0x400 * 256, 0x40))
        {
            // Initialize the file system
            status = fileSystem.initialize();
    
            if (status != FileSystemStatus.OK)
            {
                Assert.fail("Failed initializing file system: " + status);
            }
    
            // Initialize the command block
            fileSystem.initializeCommandBlock(commandBlock);
    
            // Register the client
            status = fileSystem.addClient(client);
    
            if (status != FileSystemStatus.OK)
            {
                Assert.fail("Failed registering client: " + status);
            }
    
            // Open the file
            status = fileSystem.openFile(client,
                    commandBlock,
                    path,
                    accessMode,
                    fileDescriptor,
                    FileSystemReturnFlag.ALL);
    
            if (status != FileSystemStatus.OK)
            {
                Assert.fail("Failed opening file: " + status);
            }
    
            ByteArrayOutputStream fileBytesBuffer = new ByteArrayOutputStream();
            int bytesRead;
    
            // ########### Once it executes this, it gets stuck ############
            while ((bytesRead = fileSystem.readFile(client,
                    commandBlock,
                    destinationBuffer,
                    fileDescriptor,
                    FileSystemReturnFlag.ALL)) > 0)
            {
                MemoryReader memoryReader = new MemoryReader();
                byte[] readBytes = memoryReader.readBytes(destinationBuffer.getAddress(), bytesRead);
                fileBytesBuffer.write(readBytes);
            }
    
            status = FileSystemStatus.getStatus(bytesRead);
            System.out.println("File reading exit status: " + status);
    
            // Close the file
            status = fileSystem.closeFile(client, commandBlock, fileDescriptor, FileSystemReturnFlag.NONE);
    
            if (status != FileSystemStatus.OK)
            {
                Assert.fail("Failed closing file: " + status);
            }
    
            // Delete the client registration
            status = fileSystem.unRegisterClient(client, FileSystemReturnFlag.NONE);
    
            if (status != FileSystemStatus.OK)
            {
                Assert.fail("Failed un-registering client: " + status);
            }
    
            storeFile(filePath, fileBytesBuffer);
        }
    }
    
    private void storeFile(String filePath, ByteArrayOutputStream outputStream) throws IOException
    {
        Path targetFilePath = Paths.get(filePath);
    
        // Create parent directory (if it doesn't exist yet)
        Path parentDirectory = targetFilePath.getParent();
        Files.createDirectories(parentDirectory);
    
        // Write the bytes
        byte[] bytes = outputStream.toByteArray();
        Files.write(targetFilePath, bytes);
    }
    As comparison, here is the C code Dimok uses in ddd which is working:
    Code:
    static void DumpFile(void *client,
                         void *commandBlock,
                         SendData *sendData,
                         char *path,
                         unsigned int fileSize) {
        sendData->tag = 0x02;
        memcpy(&sendData->data[0], &fileSize, 4);
        sendData->length = snprintf((char *) sendData->data + 4, BUFFER_SIZE - 4, "%s", path) + 4 + 1;
        sendwait(iClientSocket, sendData, sizeof(SendData) + sendData->length);
    
        int ret = recvwait(iClientSocket, (char *) sendData, sizeof(SendData) + 1);
        if (ret < (int) (sizeof(SendData) + 1) || (sendData->data[0] != 1)) {
            return;
        }
    
        unsigned char *dataBuffer = (unsigned char *) memalign(0x40, BUFFER_SIZE);
        if (!dataBuffer) {
            return;
        }
    
        int fileDescriptor = 0;
        if (FSOpenFile(client, commandBlock, path, "r", &fileDescriptor, -1) != FS_STATUS_OK) {
            free(dataBuffer);
            sendData->tag = 0x04;
            sendData->length = 0;
            sendwait(iClientSocket, sendData, sizeof(SendData) + sendData->length);
            return;
        }
    
        unsigned int size = 0;
    
        // Copy rpl in memory
        while ((ret = FSReadFile(client, commandBlock, dataBuffer, 0x1, BUFFER_SIZE, fileDescriptor, 0, -1)) > 0) {
            size += ret;
    
            sendData->tag = 0x03;
            sendData->length = ret;
            memcpy(sendData->data, dataBuffer, sendData->length);
    
            if (sendwait(iClientSocket, sendData, sizeof(SendData) + sendData->length) < 0) {
                break;
            }
        }
    
        sendData->tag = 0x04;
        sendData->length = 0;
        sendwait(iClientSocket, sendData, sizeof(SendData) + sendData->length);
    
        FSCloseFile(client, commandBlock, fileDescriptor, -1);
        free(dataBuffer);
    }
    I'm passing the same parameters but it's not returning after the call:
    Code:
    public int readFile(FileSystemClient client,
                        FileSystemCommandBlock commandBlock,
                        AllocatedMemory dataBuffer,
                        FileSystemHandle fileDescriptor,
                        FileSystemReturnFlag returnFlag) throws IOException
    {
        ExportedSymbol readFile = remoteProcedureCall.getSymbol(RPL.CORE_INIT.toString(), "FSReadFile");
    
        return remoteProcedureCall.callInt(readFile,
                client.getAddress(),
                commandBlock.getAddress(),
                dataBuffer.getAddress(),
                0x1,
                0x1000,
                // dataBuffer.getSize(),
                fileDescriptor.dereference(),
                0,
                // returnFlag.getValue());
                -1);
    }
    See here for the full Java code.

    Thanks!

    @dimok
    @QuarkTheAwesome
    @Maschell
    @gudenaurock
    @timogus
    @NWPlayer123
     
  2. gudenau

    gudenau Largely ignored

    Member
    GBAtemp Patron
    gudenau is a Patron of GBAtemp and is helping us stay independent!

    Our Patreon
    3,286
    1,252
    Jul 7, 2010
    United States
    /dev/random
    I would recommend logging this in wireshark and making sure that you are sending the correct data, there could be some slight issue somewhere that you can not see. Happens to me more that it should
     
    BullyWiiPlaza likes this.
  3. BullyWiiPlaza
    OP

    BullyWiiPlaza Nintendo Hacking <3

    Member
    1,771
    1,439
    Aug 2, 2014
    Germany
    True, you have no idea how long I have been messing around with those minor details that might screw it all up. Maybe someone can implement a TCP Gecko command for this? :)
     
    Last edited by BullyWiiPlaza, Nov 27, 2016