/* Copyright 2019-2023 Dmitry Isaenko This file is part of libKonogonka. libKonogonka is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. libKonogonka is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with libKonogonka. If not, see . */ package libKonogonka.Tools.other.System2.ini1; import libKonogonka.Converter; import libKonogonka.RainbowDump; import libKonogonka.Tools.NPDM.KernelAccessControlProvider; import libKonogonka.Tools.NSO.SegmentHeader; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; 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 dataSegmentHeader; private final byte[] reserved2; private final SegmentHeader bssSegmentHeader; private final byte[] reserved3; private final KernelAccessControlProvider kernelCapabilityData; public Kip1(byte[] kip1Bytes) throws Exception{ this.magic = new String(kip1Bytes, 0, 0x4); this.name = new String(kip1Bytes, 0x4, 0xC); 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.dataSegmentHeader = 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 String getMagic() { return magic; } public String getName() { return name; } public byte[] getProgramId() { return programId; } public int getVersion() { return version; } public byte getMainThreadPriority() { return mainThreadPriority; } public byte getMainThreadCoreNumber() { return mainThreadCoreNumber; } public byte getReserved1() { return reserved1; } public byte getFlags() { return flags; } public SegmentHeader getTextSegmentHeader() { return textSegmentHeader; } public int getThreadAffinityMask() { return threadAffinityMask; } public SegmentHeader getRoDataSegmentHeader() { return roDataSegmentHeader; } public int getMainThreadStackSize() { return mainThreadStackSize; } public SegmentHeader getDataSegmentHeader() { return dataSegmentHeader; } public byte[] getReserved2() { return reserved2; } public SegmentHeader getBssSegmentHeader() { return bssSegmentHeader; } public byte[] getReserved3() { return reserved3; } public KernelAccessControlProvider getKernelCapabilityData() { return kernelCapabilityData; } public void printDebug(){ StringBuilder mapIoOrNormalRange = new StringBuilder(); StringBuilder interruptPairs = new StringBuilder(); StringBuilder syscallMasks = new StringBuilder(); kernelCapabilityData.getMapIoOrNormalRange().forEach((bytes, aBoolean) -> { mapIoOrNormalRange.append(" "); mapIoOrNormalRange.append(Converter.byteArrToHexStringAsLE(bytes)); mapIoOrNormalRange.append(" : "); mapIoOrNormalRange.append(aBoolean); mapIoOrNormalRange.append("\n"); }); kernelCapabilityData.getInterruptPairs().forEach((aInteger, bytes) -> { interruptPairs.append(" #"); interruptPairs.append(aInteger); for (byte[] innerArray : bytes) { interruptPairs.append("\n |- "); interruptPairs.append(Converter.byteArrToHexStringAsLE(innerArray)); } interruptPairs.append("\n"); }); kernelCapabilityData.getSyscallMasks().forEach((aByte, bytes) -> { syscallMasks.append(" "); syscallMasks.append(String.format("0x%x", aByte)); syscallMasks.append(" : "); syscallMasks.append(Converter.byteArrToHexStringAsLE(bytes)); syscallMasks.append("\n"); }); log.debug(" ..:: KIP1 ::..\n" + "Magic : " + magic + "\n" + "Name : " + name + "\n" + "ProgramId : " + Converter.byteArrToHexStringAsLE(programId) + "\n" + "Version : " + RainbowDump.formatDecHexString(version) + "\n" + "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" + ".text segment header\n" + " Segment offset : " + RainbowDump.formatDecHexString(textSegmentHeader.getSegmentOffset()) + "\n" + " Memory offset : " + RainbowDump.formatDecHexString(textSegmentHeader.getMemoryOffset()) + "\n" + " Size : " + RainbowDump.formatDecHexString(textSegmentHeader.getSizeAsDecompressed()) + "\n" + "Thread affinity mask : " + RainbowDump.formatDecHexString(threadAffinityMask) + "\n" + ".ro segment header\n" + " Segment offset : " + RainbowDump.formatDecHexString(roDataSegmentHeader.getSegmentOffset()) + "\n" + " 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" + " Segment offset : " + RainbowDump.formatDecHexString(dataSegmentHeader.getSegmentOffset()) + "\n" + " Memory offset : " + RainbowDump.formatDecHexString(dataSegmentHeader.getMemoryOffset()) + "\n" + " Size : " + RainbowDump.formatDecHexString(dataSegmentHeader.getSizeAsDecompressed()) + "\n" + "Reserved 2 : " + Converter.byteArrToHexStringAsLE(reserved2) + "\n" + ".bss segment header\n" + " Segment offset : " + RainbowDump.formatDecHexString(bssSegmentHeader.getSegmentOffset()) + "\n" + " Memory offset : " + RainbowDump.formatDecHexString(bssSegmentHeader.getMemoryOffset()) + "\n" + " Size : " + RainbowDump.formatDecHexString(bssSegmentHeader.getSizeAsDecompressed()) + "\n" + "Reserved 3 : " + Converter.byteArrToHexStringAsLE(reserved3) + "\n" + "Kernel capability data\n" + " Kernel flags available? : " + kernelCapabilityData.isKernelFlagsAvailable() + "\n" + " |- CPU ID Hi : " + kernelCapabilityData.getKernelFlagCpuIdHi() + "\n" + " |- CPU ID Low : " + kernelCapabilityData.getKernelFlagCpuIdLo() + "\n" + " |- Thread priority Hi : " + kernelCapabilityData.getKernelFlagThreadPrioHi() + "\n" + " |- Thread priority Low : " + kernelCapabilityData.getKernelFlagThreadPrioLo()+ "\n" + "Map IO or Normal Range:\n" + mapIoOrNormalRange + "Interrupt pairs\n" + interruptPairs + "Map normal page : " + Converter.byteArrToHexStringAsLE(kernelCapabilityData.getMapNormalPage()) + "\n" + "Application type : " + RainbowDump.formatDecHexString(kernelCapabilityData.getApplicationType()) + "\n" + " Kernel rel. version available? : " + kernelCapabilityData.isKernelRelVersionAvailable() + "\n" + " |- Version Major : " + kernelCapabilityData.getKernelRelVersionMajor() + "\n" + " |- Version Minor : " + kernelCapabilityData.getKernelRelVersionMinor() + "\n" + "Handle table size : " + RainbowDump.formatDecHexString(kernelCapabilityData.getHandleTableSize()) + "\n" + " Debug flags available? : " + kernelCapabilityData.isDebugFlagsAvailable() + "\n" + " |- Can be debugged : " + kernelCapabilityData.isCanBeDebugged() + "\n" + " |- Can debug others : " + kernelCapabilityData.isCanDebugOthers() + "\n" + "Syscall masks\n" + syscallMasks ); } }