From e47d977779fade40b22bb95887a11546309baf54 Mon Sep 17 00:00:00 2001 From: Dmitry Isaenko Date: Fri, 6 Jan 2023 17:38:05 +0300 Subject: [PATCH] Unify export functionality --- .../java/libKonogonka/Tools/ExportAble.java | 47 ++++++++ .../NPDM/KernelAccessControlProvider.java | 2 + .../libKonogonka/Tools/PFS0/PFS0Provider.java | 41 +------ .../Tools/RomFs/RomFsProvider.java | 38 +------ .../libKonogonka/Tools/XCI/HFS0Provider.java | 40 +------ .../Tools/other/System2/System2Provider.java | 76 ++++--------- .../other/System2/ini1/Ini1Provider.java | 85 ++------------- .../Tools/other/System2/ini1/Kip1.java | 101 +++++++++++------- .../RomFsDecrypted/Package2UnpackedTest.java | 7 +- 9 files changed, 159 insertions(+), 278 deletions(-) create mode 100644 src/main/java/libKonogonka/Tools/ExportAble.java diff --git a/src/main/java/libKonogonka/Tools/ExportAble.java b/src/main/java/libKonogonka/Tools/ExportAble.java new file mode 100644 index 0000000..0cd209e --- /dev/null +++ b/src/main/java/libKonogonka/Tools/ExportAble.java @@ -0,0 +1,47 @@ +package libKonogonka.Tools; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class ExportAble { + + protected BufferedInputStream stream; + + protected boolean export(String saveTo, String fileName, long skip, long size) throws Exception{ + if (skip != stream.skip(skip)) + throw new Exception("Can't seek to start position: "+skip); + + File location = new File(saveTo); + location.mkdirs(); + + try (BufferedOutputStream extractedFileBOS = new BufferedOutputStream( + Files.newOutputStream(Paths.get(saveTo+File.separator+fileName)))){ + + int blockSize = 0x200; + if (size < 0x200) + blockSize = (int) size; + + long i = 0; + byte[] block = new byte[blockSize]; + + int actuallyRead; + while (true) { + if ((actuallyRead = stream.read(block)) != blockSize) + throw new Exception("Read failure. Block Size: "+blockSize+", actuallyRead: "+actuallyRead); + extractedFileBOS.write(block); + i += blockSize; + if ((i + blockSize) > size) { + blockSize = (int) (size - i); + if (blockSize == 0) + break; + block = new byte[blockSize]; + } + } + } + stream.close(); + return true; + } +} diff --git a/src/main/java/libKonogonka/Tools/NPDM/KernelAccessControlProvider.java b/src/main/java/libKonogonka/Tools/NPDM/KernelAccessControlProvider.java index ecd4688..4244d23 100644 --- a/src/main/java/libKonogonka/Tools/NPDM/KernelAccessControlProvider.java +++ b/src/main/java/libKonogonka/Tools/NPDM/KernelAccessControlProvider.java @@ -203,6 +203,8 @@ public class KernelAccessControlProvider { canDebugOthers = (block >> 18 & 1) != 0; log.trace("DEBUGFLAGS "+canBeDebugged+" "+canDebugOthers); break; + case 0x20: + break; default: log.warn("INVALID ind:0b"+Integer.toBinaryString(block)); } diff --git a/src/main/java/libKonogonka/Tools/PFS0/PFS0Provider.java b/src/main/java/libKonogonka/Tools/PFS0/PFS0Provider.java index fbe47c3..60d3a6f 100644 --- a/src/main/java/libKonogonka/Tools/PFS0/PFS0Provider.java +++ b/src/main/java/libKonogonka/Tools/PFS0/PFS0Provider.java @@ -19,6 +19,7 @@ package libKonogonka.Tools.PFS0; import libKonogonka.RainbowDump; +import libKonogonka.Tools.ExportAble; import libKonogonka.Tools.ISuperProvider; import libKonogonka.Tools.NCA.NCASectionTableBlock.SuperBlockPFS0; import libKonogonka.ctraes.InFileStreamProducer; @@ -30,14 +31,13 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.LinkedList; -public class PFS0Provider implements ISuperProvider { +public class PFS0Provider extends ExportAble implements ISuperProvider { private final static Logger log = LogManager.getLogger(PFS0Provider.class); private final long rawBlockDataStart; private long offsetPositionInFile; private final InFileStreamProducer producer; - private BufferedInputStream stream; private SuperBlockPFS0 superBlockPFS0; private long mediaStartOffset; @@ -108,47 +108,16 @@ public class PFS0Provider implements ISuperProvider { } @Override public boolean exportContent(String saveToLocation, int subFileNumber){ - PFS0subFile subFile = header.getPfs0subFiles()[subFileNumber]; - File location = new File(saveToLocation); - location.mkdirs(); - - try (BufferedOutputStream extractedFileBOS = new BufferedOutputStream( - Files.newOutputStream(Paths.get(saveToLocation+File.separator+subFile.getName())))){ - + try { + PFS0subFile subFile = header.getPfs0subFiles()[subFileNumber]; this.stream = producer.produce(); - - long subFileSize = subFile.getSize(); - long toSkip = subFile.getOffset() + mediaStartOffset * 0x200 + rawBlockDataStart; - if (toSkip != stream.skip(toSkip)) - throw new Exception("Unable to skip offset: "+toSkip); - - int blockSize = 0x200; - if (subFileSize < 0x200) - blockSize = (int) subFileSize; - - long i = 0; - byte[] block = new byte[blockSize]; - - int actuallyRead; - while (true) { - if ((actuallyRead = stream.read(block)) != blockSize) - throw new Exception("Read failure. Block Size: "+blockSize+", actuallyRead: "+actuallyRead); - extractedFileBOS.write(block); - i += blockSize; - if ((i + blockSize) > subFileSize) { - blockSize = (int) (subFileSize - i); - if (blockSize == 0) - break; - block = new byte[blockSize]; - } - } + return export(saveToLocation, subFile.getName(), toSkip, subFile.getSize()); } catch (Exception e){ log.error("File export failure", e); return false; } - return true; } @Override diff --git a/src/main/java/libKonogonka/Tools/RomFs/RomFsProvider.java b/src/main/java/libKonogonka/Tools/RomFs/RomFsProvider.java index 7a01fca..8ce3107 100644 --- a/src/main/java/libKonogonka/Tools/RomFs/RomFsProvider.java +++ b/src/main/java/libKonogonka/Tools/RomFs/RomFsProvider.java @@ -18,7 +18,7 @@ */ package libKonogonka.Tools.RomFs; -import libKonogonka.Tools.PFS0.PFS0subFile; +import libKonogonka.Tools.ExportAble; import libKonogonka.Tools.RomFs.view.DirectoryMetaTablePlainView; import libKonogonka.Tools.RomFs.view.FileMetaTablePlainView; import libKonogonka.ctraes.InFileStreamProducer; @@ -26,9 +26,8 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.*; -import java.nio.file.Files; -public class RomFsProvider{ +public class RomFsProvider extends ExportAble { private final static Logger log = LogManager.getLogger(RomFsProvider.class); private final InFileStreamProducer producer; @@ -99,36 +98,9 @@ public class RomFsProvider{ } private void exportSingleFile(FileSystemEntry entry, String saveToLocation) throws Exception { - File contentFile = new File(saveToLocation + entry.getName()); - try(BufferedOutputStream extractedFileBOS = new BufferedOutputStream(Files.newOutputStream(contentFile.toPath())); - BufferedInputStream stream = producer.produce()) { - long skipBytes = entry.getOffset() + mediaStartOffset * 0x200 + level6Header.getFileDataOffset() + level6Offset; - - if (skipBytes != stream.skip(skipBytes)) - throw new Exception("Can't skip"); - - int blockSize = 0x200; - if (entry.getSize() < 0x200) - blockSize = (int) entry.getSize(); - - long i = 0; - byte[] block = new byte[blockSize]; - - int actuallyRead; - - while (true) { - if ((actuallyRead = stream.read(block)) != blockSize) - throw new Exception("Read failure. Block Size: "+blockSize+", actuallyRead: "+actuallyRead); - extractedFileBOS.write(block); - i += blockSize; - if ((i + blockSize) >= entry.getSize()) { - blockSize = (int) (entry.getSize() - i); - if (blockSize == 0) - break; - block = new byte[blockSize]; - } - } - } + stream = producer.produce(); + long skipBytes = entry.getOffset() + mediaStartOffset * 0x200 + level6Header.getFileDataOffset() + level6Offset; + export(saveToLocation, entry.getName(), skipBytes, entry.getSize()); } public InFileStreamProducer getStreamProducer(FileSystemEntry entry) throws Exception{ diff --git a/src/main/java/libKonogonka/Tools/XCI/HFS0Provider.java b/src/main/java/libKonogonka/Tools/XCI/HFS0Provider.java index 3898bff..26ca5ee 100644 --- a/src/main/java/libKonogonka/Tools/XCI/HFS0Provider.java +++ b/src/main/java/libKonogonka/Tools/XCI/HFS0Provider.java @@ -18,6 +18,7 @@ */ package libKonogonka.Tools.XCI; +import libKonogonka.Tools.ExportAble; import libKonogonka.Tools.ISuperProvider; import libKonogonka.ctraes.InFileStreamProducer; import org.apache.logging.log4j.LogManager; @@ -34,7 +35,7 @@ import static libKonogonka.Converter.*; /** * HFS0 * */ -public class HFS0Provider implements ISuperProvider { +public class HFS0Provider extends ExportAble implements ISuperProvider { private final static Logger log = LogManager.getLogger(HFS0Provider.class); private final String magic; @@ -140,41 +141,8 @@ public class HFS0Provider implements ISuperProvider { @Override public boolean exportContent(String saveToLocation, int subFileNumber) throws Exception { HFS0File subFile = hfs0Files[subFileNumber]; - File location = new File(saveToLocation); - location.mkdirs(); - - try (BufferedOutputStream extractedFileBOS = new BufferedOutputStream( - Files.newOutputStream(Paths.get(saveToLocation+File.separator+subFile.getName()))); - BufferedInputStream stream = getStreamProducer(subFileNumber).produce()){ - - long subFileSize = subFile.getSize(); - - int blockSize = 0x200; - if (subFileSize < 0x200) - blockSize = (int) subFileSize; - - long i = 0; - byte[] block = new byte[blockSize]; - - int actuallyRead; - while (true) { - if ((actuallyRead = stream.read(block)) != blockSize) - throw new Exception("Read failure. Block Size: "+blockSize+", actuallyRead: "+actuallyRead); - extractedFileBOS.write(block); - i += blockSize; - if ((i + blockSize) > subFileSize) { - blockSize = (int) (subFileSize - i); - if (blockSize == 0) - break; - block = new byte[blockSize]; - } - } - } - catch (Exception e){ - log.error("File export failure", e); - return false; - } - return true; + stream = getStreamProducer(subFileNumber).produce(); + return export(saveToLocation, subFile.getName(), 0, subFile.getSize()); } @Override public InFileStreamProducer getStreamProducer(String subFileName) throws FileNotFoundException{ diff --git a/src/main/java/libKonogonka/Tools/other/System2/System2Provider.java b/src/main/java/libKonogonka/Tools/other/System2/System2Provider.java index bbf0708..3c5eb64 100644 --- a/src/main/java/libKonogonka/Tools/other/System2/System2Provider.java +++ b/src/main/java/libKonogonka/Tools/other/System2/System2Provider.java @@ -19,21 +19,21 @@ package libKonogonka.Tools.other.System2; import libKonogonka.KeyChainHolder; +import libKonogonka.Tools.ExportAble; import libKonogonka.Tools.other.System2.ini1.Ini1Provider; +import libKonogonka.ctraesclassic.AesCtrClassicBufferedInputStream; +import libKonogonka.ctraesclassic.AesCtrDecryptClassic; import libKonogonka.ctraesclassic.AesCtrStream; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import javax.crypto.CipherInputStream; import java.io.*; import java.nio.ByteBuffer; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; -public class System2Provider { - private final static Logger log = LogManager.getLogger(System2Provider.class); - +public class System2Provider extends ExportAble { private byte[] rsa2048signature; private System2Header header; private KernelMap kernelMap; @@ -46,20 +46,20 @@ public class System2Provider { this.pathToFile = pathToFile; this.keyChainHolder = keyChainHolder; - try (BufferedInputStream stream = new BufferedInputStream(Files.newInputStream(Paths.get(pathToFile)))) { - readSignatures(stream); - readHeader(stream); - findIni1KernelMap(); - } + this.stream = new BufferedInputStream(Files.newInputStream(Paths.get(pathToFile))); + readSignatures(); + readHeader(); + findIni1KernelMap(); + this.stream.close(); } - private void readSignatures(BufferedInputStream stream) throws Exception{ + private void readSignatures() throws Exception{ rsa2048signature = new byte[0x100]; if (0x100 != stream.read(rsa2048signature)) throw new Exception("Unable to read System2 RSA-2048 signature bytes"); } - private void readHeader(BufferedInputStream stream) throws Exception{ + private void readHeader() throws Exception{ byte[] headerBytes = new byte[0x100]; if (0x100 != stream.read(headerBytes)) throw new Exception("Unable to read System2 header bytes"); @@ -74,11 +74,11 @@ public class System2Provider { throw new Exception("Unable to skip offset: " + toSkip); ByteBuffer byteBuffer = ByteBuffer.allocate(0x1000); - try (CipherInputStream stream = AesCtrStream.getStream(header.getKey(), header.getSection0Ctr(), fis);) { + try (CipherInputStream cipherInputStream = AesCtrStream.getStream(header.getKey(), header.getSection0Ctr(), fis);) { for (int j = 0; j < 8; j++) { byte[] block = new byte[0x200]; int actuallyRead; - if ((actuallyRead = stream.read(block)) != 0x200) + if ((actuallyRead = cipherInputStream.read(block)) != 0x200) throw new Exception("Read failure " + actuallyRead); byteBuffer.put(block); } @@ -95,47 +95,15 @@ public class System2Provider { } public boolean exportKernel(String saveTo) throws Exception{ - File location = new File(saveTo); - location.mkdirs(); + Path filePath = Paths.get(pathToFile); + AesCtrDecryptClassic decryptor = new AesCtrDecryptClassic(header.getKey(), header.getSection0Ctr()); + stream = new AesCtrClassicBufferedInputStream(decryptor, + 0x200, + Files.size(filePath), // size of system2 + Files.newInputStream(filePath), + Files.size(filePath)); - InputStream fis = Files.newInputStream(Paths.get(pathToFile)); - // Encrypted section comes next - long toSkip = 0x200; - if (toSkip != fis.skip(toSkip)) - throw new Exception("Unable to skip offset: "+toSkip); - - try (CipherInputStream stream = AesCtrStream.getStream(header.getKey(), header.getSection0Ctr(), fis); - BufferedOutputStream extractedFileBOS = new BufferedOutputStream( - Files.newOutputStream(Paths.get(saveTo+File.separator+"Kernel.bin")))){ - - long kernelSize = header.getSection0size(); - - int blockSize = 0x200; - if (kernelSize < 0x200) - blockSize = (int) kernelSize; - - long i = 0; - byte[] block = new byte[blockSize]; - - int actuallyRead; - while (true) { - if ((actuallyRead = stream.read(block)) != blockSize) - throw new Exception("Read failure. Block Size: "+blockSize+", actuallyRead: "+actuallyRead); - extractedFileBOS.write(block); - i += blockSize; - if ((i + blockSize) > kernelSize) { - blockSize = (int) (kernelSize - i); - if (blockSize == 0) - break; - block = new byte[blockSize]; - } - } - } - catch (Exception e){ - log.error("File export failure", e); - return false; - } - return true; + return export(saveTo, "Kernel.bin", 0x200, header.getSection0size()); } public byte[] getRsa2048signature() { return rsa2048signature; } diff --git a/src/main/java/libKonogonka/Tools/other/System2/ini1/Ini1Provider.java b/src/main/java/libKonogonka/Tools/other/System2/ini1/Ini1Provider.java index 31241a2..7474e8b 100644 --- a/src/main/java/libKonogonka/Tools/other/System2/ini1/Ini1Provider.java +++ b/src/main/java/libKonogonka/Tools/other/System2/ini1/Ini1Provider.java @@ -18,6 +18,7 @@ */ package libKonogonka.Tools.other.System2.ini1; +import libKonogonka.Tools.ExportAble; import libKonogonka.Tools.other.System2.KernelMap; import libKonogonka.Tools.other.System2.System2Header; import libKonogonka.ctraesclassic.AesCtrClassicBufferedInputStream; @@ -25,25 +26,19 @@ import libKonogonka.ctraesclassic.AesCtrDecryptClassic; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import java.io.BufferedOutputStream; -import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; -public class Ini1Provider { - private final static Logger log = LogManager.getLogger(Ini1Provider.class); - +public class Ini1Provider extends ExportAble { private final System2Header system2Header; private final String pathToFile; private final KernelMap kernelMap; private Ini1Header ini1Header; private List kip1List; - private AesCtrClassicBufferedInputStream stream; - public Ini1Provider(System2Header system2Header, String pathToFile, KernelMap kernelMap) throws Exception{ this.system2Header = system2Header; this.pathToFile = pathToFile; @@ -100,80 +95,14 @@ public class Ini1Provider { public boolean exportIni1(String saveTo) throws Exception{ makeStream(); - File location = new File(saveTo); - location.mkdirs(); - - try (BufferedOutputStream extractedFileBOS = new BufferedOutputStream( - Files.newOutputStream(Paths.get(saveTo+File.separator+"INI1.bin")))){ - - long iniSize = ini1Header.getSize(); - - int blockSize = 0x200; - if (iniSize < 0x200) - blockSize = (int) iniSize; - - long i = 0; - byte[] block = new byte[blockSize]; - - int actuallyRead; - while (true) { - if ((actuallyRead = stream.read(block)) != blockSize) - throw new Exception("Read failure. Block Size: "+blockSize+", actuallyRead: "+actuallyRead); - extractedFileBOS.write(block); - i += blockSize; - if ((i + blockSize) > iniSize) { - blockSize = (int) (iniSize - i); - if (blockSize == 0) - break; - block = new byte[blockSize]; - } - } - } - catch (Exception e){ - log.error("File export failure", e); - return false; - } - return true; + return export(saveTo, "INI1.bin", 0, ini1Header.getSize()); } public boolean exportKip1(String saveTo, Kip1 kip1) throws Exception{ makeStream(); - long startOffset = 0x10 + kip1.getStartOffset(); - if (startOffset != stream.skip(startOffset)) - throw new Exception("Can't seek to start position of KIP1: "+startOffset); - File location = new File(saveTo); - location.mkdirs(); - - try (BufferedOutputStream extractedFileBOS = new BufferedOutputStream( - Files.newOutputStream(Paths.get(saveTo+File.separator+kip1.getName()+".kip1")))){ - - long size = kip1.getEndOffset()-kip1.getStartOffset(); - - int blockSize = 0x200; - if (size < 0x200) - blockSize = (int) size; - - long i = 0; - byte[] block = new byte[blockSize]; - - int actuallyRead; - while (true) { - if ((actuallyRead = stream.read(block)) != blockSize) - throw new Exception("Read failure. Block Size: "+blockSize+", actuallyRead: "+actuallyRead); - extractedFileBOS.write(block); - i += blockSize; - if ((i + blockSize) > size) { - blockSize = (int) (size - i); - if (blockSize == 0) - break; - block = new byte[blockSize]; - } - } - } - catch (Exception e){ - log.error("File export failure", e); - return false; - } - return true; + return export(saveTo, + kip1.getName()+".kip1", + 0x10 + kip1.getStartOffset(), + kip1.getEndOffset()-kip1.getStartOffset()); } } diff --git a/src/main/java/libKonogonka/Tools/other/System2/ini1/Kip1.java b/src/main/java/libKonogonka/Tools/other/System2/ini1/Kip1.java index 2bb0b2f..8ae867e 100644 --- a/src/main/java/libKonogonka/Tools/other/System2/ini1/Kip1.java +++ b/src/main/java/libKonogonka/Tools/other/System2/ini1/Kip1.java @@ -25,55 +25,70 @@ import libKonogonka.Tools.NSO.SegmentHeader; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.Arrays; public class Kip1 { private final static Logger log = LogManager.getLogger(Kip1.class); - private final String magic; - private final String name; - private final byte[] programId; - private final int version; - private final byte mainThreadPriority; - private final byte mainThreadCoreNumber; - private final byte reserved1; - private final byte flags; // bit0=TextCompress, bit1=RoCompress, bit2=DataCompress, bit3=Is64BitInstruction, bit4=ProcessAddressSpace64Bit, bit5=[2.0.0+] UseSecureMemory - private final SegmentHeader textSegmentHeader; - private final int threadAffinityMask; - private final SegmentHeader roDataSegmentHeader; - private final int mainThreadStackSize ; - private final SegmentHeader rwDataSegmentHeader; - private final byte[] reserved2; - private final SegmentHeader bssSegmentHeader; - private final byte[] reserved3; - private final KernelAccessControlProvider kernelCapabilityData; + private String magic; + private String name; + private byte[] programId; + private int version; + private byte mainThreadPriority; + private byte mainThreadCoreNumber; + private byte reserved1; + private byte flags; + private SegmentHeader textSegmentHeader; + private int threadAffinityMask; + private SegmentHeader roDataSegmentHeader; + private int mainThreadStackSize ; + private SegmentHeader rwDataSegmentHeader; + private byte[] reserved2; + private SegmentHeader bssSegmentHeader; + private byte[] reserved3; + private KernelAccessControlProvider kernelCapabilityData; - private final long startOffset; - private final long endOffset; + private long startOffset; + private long endOffset; - public Kip1(byte[] kip1Bytes, long kip1StartOffset) throws Exception{ - this.magic = new String(kip1Bytes, 0, 0x4); - this.name = new String(kip1Bytes, 0x4, 0xC).trim(); - this.programId = Arrays.copyOfRange(kip1Bytes, 0x10, 0x18); - this.version = Converter.getLEint(kip1Bytes, 0x18); - this.mainThreadPriority = kip1Bytes[0x1c]; - this.mainThreadCoreNumber = kip1Bytes[0x1d]; - this.reserved1 = kip1Bytes[0x1e]; - this.flags = kip1Bytes[0x1f]; - this.textSegmentHeader = new SegmentHeader(kip1Bytes, 0x20); - this.threadAffinityMask = Converter.getLEint(kip1Bytes, 0x2c); - this.roDataSegmentHeader = new SegmentHeader(kip1Bytes, 0x30); - this.mainThreadStackSize = Converter.getLEint(kip1Bytes, 0x3c); - this.rwDataSegmentHeader = new SegmentHeader(kip1Bytes, 0x40); - this.reserved2 = Arrays.copyOfRange(kip1Bytes, 0x4c, 0x50); - this.bssSegmentHeader = new SegmentHeader(kip1Bytes, 0x50); - this.reserved3 = Arrays.copyOfRange(kip1Bytes, 0x5c, 0x80); - this.kernelCapabilityData = new KernelAccessControlProvider(Arrays.copyOfRange(kip1Bytes, 0x80, 0x100)); + public Kip1(String fileLocation) throws Exception{ + try (BufferedInputStream stream = new BufferedInputStream(Files.newInputStream(Paths.get(fileLocation)));) { + byte[] kip1HeaderBytes = new byte[0x100]; + if (0x100 != stream.read(kip1HeaderBytes)) + throw new Exception("Unable to read KIP1 file header"); + makeHeader(kip1HeaderBytes, 0); + } + } + + public Kip1(byte[] kip1HeaderBytes, long kip1StartOffset) throws Exception{ + makeHeader(kip1HeaderBytes, kip1StartOffset); + } + + private void makeHeader(byte[] kip1HeaderBytes, long kip1StartOffset) throws Exception{ + this.magic = new String(kip1HeaderBytes, 0, 0x4); + this.name = new String(kip1HeaderBytes, 0x4, 0xC).trim(); + this.programId = Arrays.copyOfRange(kip1HeaderBytes, 0x10, 0x18); + this.version = Converter.getLEint(kip1HeaderBytes, 0x18); + this.mainThreadPriority = kip1HeaderBytes[0x1c]; + this.mainThreadCoreNumber = kip1HeaderBytes[0x1d]; + this.reserved1 = kip1HeaderBytes[0x1e]; + this.flags = kip1HeaderBytes[0x1f]; + this.textSegmentHeader = new SegmentHeader(kip1HeaderBytes, 0x20); + this.threadAffinityMask = Converter.getLEint(kip1HeaderBytes, 0x2c); + this.roDataSegmentHeader = new SegmentHeader(kip1HeaderBytes, 0x30); + this.mainThreadStackSize = Converter.getLEint(kip1HeaderBytes, 0x3c); + this.rwDataSegmentHeader = new SegmentHeader(kip1HeaderBytes, 0x40); + this.reserved2 = Arrays.copyOfRange(kip1HeaderBytes, 0x4c, 0x50); + this.bssSegmentHeader = new SegmentHeader(kip1HeaderBytes, 0x50); + this.reserved3 = Arrays.copyOfRange(kip1HeaderBytes, 0x5c, 0x80); + this.kernelCapabilityData = new KernelAccessControlProvider(Arrays.copyOfRange(kip1HeaderBytes, 0x80, 0x100)); this.startOffset = kip1StartOffset; this.endOffset = 0x100 + kip1StartOffset + textSegmentHeader.getSizeAsDecompressed() + roDataSegmentHeader.getSizeAsDecompressed() + rwDataSegmentHeader.getSizeAsDecompressed() + bssSegmentHeader.getSizeAsDecompressed(); - } public String getMagic() { return magic; } @@ -134,7 +149,13 @@ public class Kip1 { "Main thread priority : " + String.format("0x%x", mainThreadPriority) + "\n" + "Main thread core number : " + String.format("0x%x", mainThreadCoreNumber) + "\n" + "Reserved 1 : " + String.format("0x%x", reserved1) + "\n" + - "Flags : " + flags + "\n" + + "Flags : " + Converter.intToBinaryString(flags) + "\n" + + " 0| .text compress : " + ((flags & 1) == 1 ? "YES" : "NO") + "\n" + + " 1| .ro compress : " + ((flags >> 1 & 1) == 1 ? "YES" : "NO") + "\n" + + " 2| .rw compress : " + ((flags >> 2 & 1) == 1 ? "YES" : "NO") + "\n" + + " 3| Is 64-bit instruction : " + ((flags >> 3 & 1) == 1 ? "YES" : "NO") + "\n" + + " 4| Process addr. space 64-bit : " + ((flags >> 4 & 1) == 1 ? "YES" : "NO") + "\n" + + " 5| Use secure memory : " + ((flags >> 5 & 1) == 1 ? "YES" : "NO") + "\n" + ".text segment header\n" + " Segment offset : " + RainbowDump.formatDecHexString(textSegmentHeader.getSegmentOffset()) + "\n" + " Memory offset : " + RainbowDump.formatDecHexString(textSegmentHeader.getMemoryOffset()) + "\n" + @@ -145,7 +166,7 @@ public class Kip1 { " Memory offset : " + RainbowDump.formatDecHexString(roDataSegmentHeader.getMemoryOffset()) + "\n" + " Size : " + RainbowDump.formatDecHexString(roDataSegmentHeader.getSizeAsDecompressed()) + "\n" + "Main thread stack size : " + RainbowDump.formatDecHexString(mainThreadStackSize) + "\n" + - ".data segment header\n" + + ".rw segment header\n" + " Segment offset : " + RainbowDump.formatDecHexString(rwDataSegmentHeader.getSegmentOffset()) + "\n" + " Memory offset : " + RainbowDump.formatDecHexString(rwDataSegmentHeader.getMemoryOffset()) + "\n" + " Size : " + RainbowDump.formatDecHexString(rwDataSegmentHeader.getSizeAsDecompressed()) + "\n" + diff --git a/src/test/java/libKonogonka/RomFsDecrypted/Package2UnpackedTest.java b/src/test/java/libKonogonka/RomFsDecrypted/Package2UnpackedTest.java index 15cd531..7a29ffb 100644 --- a/src/test/java/libKonogonka/RomFsDecrypted/Package2UnpackedTest.java +++ b/src/test/java/libKonogonka/RomFsDecrypted/Package2UnpackedTest.java @@ -103,7 +103,6 @@ public class Package2UnpackedTest { ini1Provider.getIni1Header().printDebug(); for (Kip1 kip1 : ini1Provider.getKip1List()) kip1.printDebug(); - boolean exported = provider.exportKernel("/home/loper/Projects/libKonogonka/FilesForTests/own/"); System.out.println("Exported = "+exported); @@ -115,4 +114,10 @@ public class Package2UnpackedTest { System.out.println("Exported KIP1s "+ kip1.getName() +" = " + exported + String.format(" Size 0x%x", Files.size(Paths.get("/home/loper/Projects/libKonogonka/FilesForTests/own/KIP1s/"+kip1.getName()+".kip1")))); } } + @DisplayName("KIP1 read reference") + @Test + void checkReference() throws Exception{ + Kip1 kip1 = new Kip1("/home/loper/Projects/libKonogonka/FilesForTests/"); + kip1.printDebug(); + } }