Unify export functionality
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Dmitry Isaenko 2023-01-06 17:38:05 +03:00
parent 3262fb2360
commit e47d977779
9 changed files with 159 additions and 278 deletions

View file

@ -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;
}
}

View file

@ -203,6 +203,8 @@ public class KernelAccessControlProvider {
canDebugOthers = (block >> 18 & 1) != 0; canDebugOthers = (block >> 18 & 1) != 0;
log.trace("DEBUGFLAGS "+canBeDebugged+" "+canDebugOthers); log.trace("DEBUGFLAGS "+canBeDebugged+" "+canDebugOthers);
break; break;
case 0x20:
break;
default: default:
log.warn("INVALID ind:0b"+Integer.toBinaryString(block)); log.warn("INVALID ind:0b"+Integer.toBinaryString(block));
} }

View file

@ -19,6 +19,7 @@
package libKonogonka.Tools.PFS0; package libKonogonka.Tools.PFS0;
import libKonogonka.RainbowDump; import libKonogonka.RainbowDump;
import libKonogonka.Tools.ExportAble;
import libKonogonka.Tools.ISuperProvider; import libKonogonka.Tools.ISuperProvider;
import libKonogonka.Tools.NCA.NCASectionTableBlock.SuperBlockPFS0; import libKonogonka.Tools.NCA.NCASectionTableBlock.SuperBlockPFS0;
import libKonogonka.ctraes.InFileStreamProducer; import libKonogonka.ctraes.InFileStreamProducer;
@ -30,14 +31,13 @@ import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.LinkedList; 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 static Logger log = LogManager.getLogger(PFS0Provider.class);
private final long rawBlockDataStart; private final long rawBlockDataStart;
private long offsetPositionInFile; private long offsetPositionInFile;
private final InFileStreamProducer producer; private final InFileStreamProducer producer;
private BufferedInputStream stream;
private SuperBlockPFS0 superBlockPFS0; private SuperBlockPFS0 superBlockPFS0;
private long mediaStartOffset; private long mediaStartOffset;
@ -108,47 +108,16 @@ public class PFS0Provider implements ISuperProvider {
} }
@Override @Override
public boolean exportContent(String saveToLocation, int subFileNumber){ public boolean exportContent(String saveToLocation, int subFileNumber){
try {
PFS0subFile subFile = header.getPfs0subFiles()[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())))){
this.stream = producer.produce(); this.stream = producer.produce();
long subFileSize = subFile.getSize();
long toSkip = subFile.getOffset() + mediaStartOffset * 0x200 + rawBlockDataStart; long toSkip = subFile.getOffset() + mediaStartOffset * 0x200 + rawBlockDataStart;
if (toSkip != stream.skip(toSkip)) return export(saveToLocation, subFile.getName(), toSkip, subFile.getSize());
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];
}
}
} }
catch (Exception e){ catch (Exception e){
log.error("File export failure", e); log.error("File export failure", e);
return false; return false;
} }
return true;
} }
@Override @Override

View file

@ -18,7 +18,7 @@
*/ */
package libKonogonka.Tools.RomFs; package libKonogonka.Tools.RomFs;
import libKonogonka.Tools.PFS0.PFS0subFile; import libKonogonka.Tools.ExportAble;
import libKonogonka.Tools.RomFs.view.DirectoryMetaTablePlainView; import libKonogonka.Tools.RomFs.view.DirectoryMetaTablePlainView;
import libKonogonka.Tools.RomFs.view.FileMetaTablePlainView; import libKonogonka.Tools.RomFs.view.FileMetaTablePlainView;
import libKonogonka.ctraes.InFileStreamProducer; import libKonogonka.ctraes.InFileStreamProducer;
@ -26,9 +26,8 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.io.*; 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 static Logger log = LogManager.getLogger(RomFsProvider.class);
private final InFileStreamProducer producer; private final InFileStreamProducer producer;
@ -99,36 +98,9 @@ public class RomFsProvider{
} }
private void exportSingleFile(FileSystemEntry entry, String saveToLocation) throws Exception { private void exportSingleFile(FileSystemEntry entry, String saveToLocation) throws Exception {
File contentFile = new File(saveToLocation + entry.getName()); stream = producer.produce();
try(BufferedOutputStream extractedFileBOS = new BufferedOutputStream(Files.newOutputStream(contentFile.toPath()));
BufferedInputStream stream = producer.produce()) {
long skipBytes = entry.getOffset() + mediaStartOffset * 0x200 + level6Header.getFileDataOffset() + level6Offset; long skipBytes = entry.getOffset() + mediaStartOffset * 0x200 + level6Header.getFileDataOffset() + level6Offset;
export(saveToLocation, entry.getName(), skipBytes, entry.getSize());
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];
}
}
}
} }
public InFileStreamProducer getStreamProducer(FileSystemEntry entry) throws Exception{ public InFileStreamProducer getStreamProducer(FileSystemEntry entry) throws Exception{

View file

@ -18,6 +18,7 @@
*/ */
package libKonogonka.Tools.XCI; package libKonogonka.Tools.XCI;
import libKonogonka.Tools.ExportAble;
import libKonogonka.Tools.ISuperProvider; import libKonogonka.Tools.ISuperProvider;
import libKonogonka.ctraes.InFileStreamProducer; import libKonogonka.ctraes.InFileStreamProducer;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
@ -34,7 +35,7 @@ import static libKonogonka.Converter.*;
/** /**
* HFS0 * HFS0
* */ * */
public class HFS0Provider implements ISuperProvider { public class HFS0Provider extends ExportAble implements ISuperProvider {
private final static Logger log = LogManager.getLogger(HFS0Provider.class); private final static Logger log = LogManager.getLogger(HFS0Provider.class);
private final String magic; private final String magic;
@ -140,41 +141,8 @@ public class HFS0Provider implements ISuperProvider {
@Override @Override
public boolean exportContent(String saveToLocation, int subFileNumber) throws Exception { public boolean exportContent(String saveToLocation, int subFileNumber) throws Exception {
HFS0File subFile = hfs0Files[subFileNumber]; HFS0File subFile = hfs0Files[subFileNumber];
File location = new File(saveToLocation); stream = getStreamProducer(subFileNumber).produce();
location.mkdirs(); return export(saveToLocation, subFile.getName(), 0, subFile.getSize());
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;
} }
@Override @Override
public InFileStreamProducer getStreamProducer(String subFileName) throws FileNotFoundException{ public InFileStreamProducer getStreamProducer(String subFileName) throws FileNotFoundException{

View file

@ -19,21 +19,21 @@
package libKonogonka.Tools.other.System2; package libKonogonka.Tools.other.System2;
import libKonogonka.KeyChainHolder; import libKonogonka.KeyChainHolder;
import libKonogonka.Tools.ExportAble;
import libKonogonka.Tools.other.System2.ini1.Ini1Provider; import libKonogonka.Tools.other.System2.ini1.Ini1Provider;
import libKonogonka.ctraesclassic.AesCtrClassicBufferedInputStream;
import libKonogonka.ctraesclassic.AesCtrDecryptClassic;
import libKonogonka.ctraesclassic.AesCtrStream; import libKonogonka.ctraesclassic.AesCtrStream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.crypto.CipherInputStream; import javax.crypto.CipherInputStream;
import java.io.*; import java.io.*;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
public class System2Provider { public class System2Provider extends ExportAble {
private final static Logger log = LogManager.getLogger(System2Provider.class);
private byte[] rsa2048signature; private byte[] rsa2048signature;
private System2Header header; private System2Header header;
private KernelMap kernelMap; private KernelMap kernelMap;
@ -46,20 +46,20 @@ public class System2Provider {
this.pathToFile = pathToFile; this.pathToFile = pathToFile;
this.keyChainHolder = keyChainHolder; this.keyChainHolder = keyChainHolder;
try (BufferedInputStream stream = new BufferedInputStream(Files.newInputStream(Paths.get(pathToFile)))) { this.stream = new BufferedInputStream(Files.newInputStream(Paths.get(pathToFile)));
readSignatures(stream); readSignatures();
readHeader(stream); readHeader();
findIni1KernelMap(); findIni1KernelMap();
} this.stream.close();
} }
private void readSignatures(BufferedInputStream stream) throws Exception{ private void readSignatures() throws Exception{
rsa2048signature = new byte[0x100]; rsa2048signature = new byte[0x100];
if (0x100 != stream.read(rsa2048signature)) if (0x100 != stream.read(rsa2048signature))
throw new Exception("Unable to read System2 RSA-2048 signature bytes"); 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]; byte[] headerBytes = new byte[0x100];
if (0x100 != stream.read(headerBytes)) if (0x100 != stream.read(headerBytes))
throw new Exception("Unable to read System2 header bytes"); throw new Exception("Unable to read System2 header bytes");
@ -74,11 +74,11 @@ public class System2Provider {
throw new Exception("Unable to skip offset: " + toSkip); throw new Exception("Unable to skip offset: " + toSkip);
ByteBuffer byteBuffer = ByteBuffer.allocate(0x1000); 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++) { for (int j = 0; j < 8; j++) {
byte[] block = new byte[0x200]; byte[] block = new byte[0x200];
int actuallyRead; int actuallyRead;
if ((actuallyRead = stream.read(block)) != 0x200) if ((actuallyRead = cipherInputStream.read(block)) != 0x200)
throw new Exception("Read failure " + actuallyRead); throw new Exception("Read failure " + actuallyRead);
byteBuffer.put(block); byteBuffer.put(block);
} }
@ -95,47 +95,15 @@ public class System2Provider {
} }
public boolean exportKernel(String saveTo) throws Exception{ public boolean exportKernel(String saveTo) throws Exception{
File location = new File(saveTo); Path filePath = Paths.get(pathToFile);
location.mkdirs(); 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)); return export(saveTo, "Kernel.bin", 0x200, header.getSection0size());
// 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;
} }
public byte[] getRsa2048signature() { return rsa2048signature; } public byte[] getRsa2048signature() { return rsa2048signature; }

View file

@ -18,6 +18,7 @@
*/ */
package libKonogonka.Tools.other.System2.ini1; package libKonogonka.Tools.other.System2.ini1;
import libKonogonka.Tools.ExportAble;
import libKonogonka.Tools.other.System2.KernelMap; import libKonogonka.Tools.other.System2.KernelMap;
import libKonogonka.Tools.other.System2.System2Header; import libKonogonka.Tools.other.System2.System2Header;
import libKonogonka.ctraesclassic.AesCtrClassicBufferedInputStream; import libKonogonka.ctraesclassic.AesCtrClassicBufferedInputStream;
@ -25,25 +26,19 @@ import libKonogonka.ctraesclassic.AesCtrDecryptClassic;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.io.BufferedOutputStream;
import java.io.File;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class Ini1Provider { public class Ini1Provider extends ExportAble {
private final static Logger log = LogManager.getLogger(Ini1Provider.class);
private final System2Header system2Header; private final System2Header system2Header;
private final String pathToFile; private final String pathToFile;
private final KernelMap kernelMap; private final KernelMap kernelMap;
private Ini1Header ini1Header; private Ini1Header ini1Header;
private List<Kip1> kip1List; private List<Kip1> kip1List;
private AesCtrClassicBufferedInputStream stream;
public Ini1Provider(System2Header system2Header, String pathToFile, KernelMap kernelMap) throws Exception{ public Ini1Provider(System2Header system2Header, String pathToFile, KernelMap kernelMap) throws Exception{
this.system2Header = system2Header; this.system2Header = system2Header;
this.pathToFile = pathToFile; this.pathToFile = pathToFile;
@ -100,80 +95,14 @@ public class Ini1Provider {
public boolean exportIni1(String saveTo) throws Exception{ public boolean exportIni1(String saveTo) throws Exception{
makeStream(); makeStream();
File location = new File(saveTo); return export(saveTo, "INI1.bin", 0, ini1Header.getSize());
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;
} }
public boolean exportKip1(String saveTo, Kip1 kip1) throws Exception{ public boolean exportKip1(String saveTo, Kip1 kip1) throws Exception{
makeStream(); makeStream();
long startOffset = 0x10 + kip1.getStartOffset(); return export(saveTo,
if (startOffset != stream.skip(startOffset)) kip1.getName()+".kip1",
throw new Exception("Can't seek to start position of KIP1: "+startOffset); 0x10 + kip1.getStartOffset(),
File location = new File(saveTo); kip1.getEndOffset()-kip1.getStartOffset());
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;
} }
} }

View file

@ -25,55 +25,70 @@ import libKonogonka.Tools.NSO.SegmentHeader;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays; import java.util.Arrays;
public class Kip1 { public class Kip1 {
private final static Logger log = LogManager.getLogger(Kip1.class); private final static Logger log = LogManager.getLogger(Kip1.class);
private final String magic; private String magic;
private final String name; private String name;
private final byte[] programId; private byte[] programId;
private final int version; private int version;
private final byte mainThreadPriority; private byte mainThreadPriority;
private final byte mainThreadCoreNumber; private byte mainThreadCoreNumber;
private final byte reserved1; private byte reserved1;
private final byte flags; // bit0=TextCompress, bit1=RoCompress, bit2=DataCompress, bit3=Is64BitInstruction, bit4=ProcessAddressSpace64Bit, bit5=[2.0.0+] UseSecureMemory private byte flags;
private final SegmentHeader textSegmentHeader; private SegmentHeader textSegmentHeader;
private final int threadAffinityMask; private int threadAffinityMask;
private final SegmentHeader roDataSegmentHeader; private SegmentHeader roDataSegmentHeader;
private final int mainThreadStackSize ; private int mainThreadStackSize ;
private final SegmentHeader rwDataSegmentHeader; private SegmentHeader rwDataSegmentHeader;
private final byte[] reserved2; private byte[] reserved2;
private final SegmentHeader bssSegmentHeader; private SegmentHeader bssSegmentHeader;
private final byte[] reserved3; private byte[] reserved3;
private final KernelAccessControlProvider kernelCapabilityData; private KernelAccessControlProvider kernelCapabilityData;
private final long startOffset; private long startOffset;
private final long endOffset; private long endOffset;
public Kip1(byte[] kip1Bytes, long kip1StartOffset) throws Exception{ public Kip1(String fileLocation) throws Exception{
this.magic = new String(kip1Bytes, 0, 0x4); try (BufferedInputStream stream = new BufferedInputStream(Files.newInputStream(Paths.get(fileLocation)));) {
this.name = new String(kip1Bytes, 0x4, 0xC).trim(); byte[] kip1HeaderBytes = new byte[0x100];
this.programId = Arrays.copyOfRange(kip1Bytes, 0x10, 0x18); if (0x100 != stream.read(kip1HeaderBytes))
this.version = Converter.getLEint(kip1Bytes, 0x18); throw new Exception("Unable to read KIP1 file header");
this.mainThreadPriority = kip1Bytes[0x1c]; makeHeader(kip1HeaderBytes, 0);
this.mainThreadCoreNumber = kip1Bytes[0x1d]; }
this.reserved1 = kip1Bytes[0x1e]; }
this.flags = kip1Bytes[0x1f];
this.textSegmentHeader = new SegmentHeader(kip1Bytes, 0x20); public Kip1(byte[] kip1HeaderBytes, long kip1StartOffset) throws Exception{
this.threadAffinityMask = Converter.getLEint(kip1Bytes, 0x2c); makeHeader(kip1HeaderBytes, kip1StartOffset);
this.roDataSegmentHeader = new SegmentHeader(kip1Bytes, 0x30); }
this.mainThreadStackSize = Converter.getLEint(kip1Bytes, 0x3c);
this.rwDataSegmentHeader = new SegmentHeader(kip1Bytes, 0x40); private void makeHeader(byte[] kip1HeaderBytes, long kip1StartOffset) throws Exception{
this.reserved2 = Arrays.copyOfRange(kip1Bytes, 0x4c, 0x50); this.magic = new String(kip1HeaderBytes, 0, 0x4);
this.bssSegmentHeader = new SegmentHeader(kip1Bytes, 0x50); this.name = new String(kip1HeaderBytes, 0x4, 0xC).trim();
this.reserved3 = Arrays.copyOfRange(kip1Bytes, 0x5c, 0x80); this.programId = Arrays.copyOfRange(kip1HeaderBytes, 0x10, 0x18);
this.kernelCapabilityData = new KernelAccessControlProvider(Arrays.copyOfRange(kip1Bytes, 0x80, 0x100)); 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.startOffset = kip1StartOffset;
this.endOffset = 0x100 + kip1StartOffset + textSegmentHeader.getSizeAsDecompressed() + roDataSegmentHeader.getSizeAsDecompressed() + this.endOffset = 0x100 + kip1StartOffset + textSegmentHeader.getSizeAsDecompressed() + roDataSegmentHeader.getSizeAsDecompressed() +
rwDataSegmentHeader.getSizeAsDecompressed() + bssSegmentHeader.getSizeAsDecompressed(); rwDataSegmentHeader.getSizeAsDecompressed() + bssSegmentHeader.getSizeAsDecompressed();
} }
public String getMagic() { return magic; } public String getMagic() { return magic; }
@ -134,7 +149,13 @@ public class Kip1 {
"Main thread priority : " + String.format("0x%x", mainThreadPriority) + "\n" + "Main thread priority : " + String.format("0x%x", mainThreadPriority) + "\n" +
"Main thread core number : " + String.format("0x%x", mainThreadCoreNumber) + "\n" + "Main thread core number : " + String.format("0x%x", mainThreadCoreNumber) + "\n" +
"Reserved 1 : " + String.format("0x%x", reserved1) + "\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" + ".text segment header\n" +
" Segment offset : " + RainbowDump.formatDecHexString(textSegmentHeader.getSegmentOffset()) + "\n" + " Segment offset : " + RainbowDump.formatDecHexString(textSegmentHeader.getSegmentOffset()) + "\n" +
" Memory offset : " + RainbowDump.formatDecHexString(textSegmentHeader.getMemoryOffset()) + "\n" + " Memory offset : " + RainbowDump.formatDecHexString(textSegmentHeader.getMemoryOffset()) + "\n" +
@ -145,7 +166,7 @@ public class Kip1 {
" Memory offset : " + RainbowDump.formatDecHexString(roDataSegmentHeader.getMemoryOffset()) + "\n" + " Memory offset : " + RainbowDump.formatDecHexString(roDataSegmentHeader.getMemoryOffset()) + "\n" +
" Size : " + RainbowDump.formatDecHexString(roDataSegmentHeader.getSizeAsDecompressed()) + "\n" + " Size : " + RainbowDump.formatDecHexString(roDataSegmentHeader.getSizeAsDecompressed()) + "\n" +
"Main thread stack size : " + RainbowDump.formatDecHexString(mainThreadStackSize) + "\n" + "Main thread stack size : " + RainbowDump.formatDecHexString(mainThreadStackSize) + "\n" +
".data segment header\n" + ".rw segment header\n" +
" Segment offset : " + RainbowDump.formatDecHexString(rwDataSegmentHeader.getSegmentOffset()) + "\n" + " Segment offset : " + RainbowDump.formatDecHexString(rwDataSegmentHeader.getSegmentOffset()) + "\n" +
" Memory offset : " + RainbowDump.formatDecHexString(rwDataSegmentHeader.getMemoryOffset()) + "\n" + " Memory offset : " + RainbowDump.formatDecHexString(rwDataSegmentHeader.getMemoryOffset()) + "\n" +
" Size : " + RainbowDump.formatDecHexString(rwDataSegmentHeader.getSizeAsDecompressed()) + "\n" + " Size : " + RainbowDump.formatDecHexString(rwDataSegmentHeader.getSizeAsDecompressed()) + "\n" +

View file

@ -103,7 +103,6 @@ public class Package2UnpackedTest {
ini1Provider.getIni1Header().printDebug(); ini1Provider.getIni1Header().printDebug();
for (Kip1 kip1 : ini1Provider.getKip1List()) for (Kip1 kip1 : ini1Provider.getKip1List())
kip1.printDebug(); kip1.printDebug();
boolean exported = provider.exportKernel("/home/loper/Projects/libKonogonka/FilesForTests/own/"); boolean exported = provider.exportKernel("/home/loper/Projects/libKonogonka/FilesForTests/own/");
System.out.println("Exported = "+exported); 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")))); 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();
}
} }