misc updates; FS Access Header implementing drafts

This commit is contained in:
Dmitry Isaenko 2019-09-23 05:31:46 +03:00
parent e50281ca1f
commit 5566ff4a13
13 changed files with 475 additions and 401 deletions

View file

@ -28,9 +28,10 @@ JRE/JDK 8u60 or higher.
* [X] TIK
* [X] XML
* [X] NRO
* [ ] LogPrinter to singleton implementation.
* [ ] NPDM support
* [ ] CERT support
* [ ] CNMT support
* [ ] NSO support
* [ ] RomFS deep-dive
* [ ] 'Save to folder' option
* [ ] LogPrinter to singleton implementation.
* [X] 'Save to folder' option

View file

@ -10,6 +10,7 @@ import java.net.URL;
import java.util.ResourceBundle;
import static konogonka.LoperConverter.byteArrToHexString;
import static konogonka.LoperConverter.longToOctString;
public class FSAccessControlController implements Initializable {
@FXML
@ -168,20 +169,12 @@ public class FSAccessControlController implements Initializable {
public void populateFields(FSAccessControlProvider provider){
ACID_FSAcccessControlVersionLbl.setText(String.format("0x%02x", provider.getVersion()));
ACID_FSAcccessControlPaddingLbl.setText(byteArrToHexString(provider.getPadding()));
ACID_FSAcccessControlBitbaskLbl.setText(byteArrToHexString(provider.getPermissionsBitmask()));
StringBuilder sb = new StringBuilder(longToOctString(provider.getPermissionsBitmask()));
sb.reverse();
String mask = sb.toString();
ACID_FSAcccessControlBitbaskLbl.setText(mask);
ACID_FSAcccessControlReservedTf.setText(byteArrToHexString(provider.getReserved()));
byte[] permissionsBitmask = provider.getPermissionsBitmask();
String mask =
String.format("%8s", Integer.toBinaryString(permissionsBitmask[7] & 0xFF)).replace(' ', '0')+
String.format("%8s", Integer.toBinaryString(permissionsBitmask[6] & 0xFF)).replace(' ', '0')+
String.format("%8s", Integer.toBinaryString(permissionsBitmask[5] & 0xFF)).replace(' ', '0')+
String.format("%8s", Integer.toBinaryString(permissionsBitmask[4] & 0xFF)).replace(' ', '0')+
String.format("%8s", Integer.toBinaryString(permissionsBitmask[3] & 0xFF)).replace(' ', '0')+
String.format("%8s", Integer.toBinaryString(permissionsBitmask[2] & 0xFF)).replace(' ', '0')+
String.format("%8s", Integer.toBinaryString(permissionsBitmask[1] & 0xFF)).replace(' ', '0')+
String.format("%8s", Integer.toBinaryString(permissionsBitmask[0] & 0xFF)).replace(' ', '0');
for (int i = 0; i < 64; i++)
masksArr[i].setText(mask.substring(i, i+1));
}

View file

@ -29,10 +29,7 @@ public class KernelAccessControlController {
private Label mapNormalPageRwLbl;
@FXML
private Label interruptPairAvalLbl,
irq0Lbl,
irq1Lbl;
private VBox interruptPairsPane;
@FXML
private Label appTypeLbl,
kerRelVerLbl,
@ -54,9 +51,8 @@ public class KernelAccessControlController {
mapIoPane.getChildren().clear();
mapIoPane.getChildren().add(new Separator());
mapNormalPageRwLbl.setText("-");
interruptPairAvalLbl.setText("?");
irq0Lbl.setText("-");
irq1Lbl.setText("-");
interruptPairsPane.getChildren().clear();
interruptPairsPane.getChildren().add(new Separator());
appTypeLbl.setText("-");
kerRelVerLbl.setText("-");
handleTableSizeLbl.setText("-");
@ -115,9 +111,11 @@ public class KernelAccessControlController {
roFlagLbl.setPadding(new Insets(5.0, 5.0, 5.0, 5.0));
roFlagVal.setPadding(new Insets(5.0, 5.0, 5.0, 5.0));
mapIoPane.getChildren().add(new HBox(altStPgNnumOfPgLbl, altStPgNnumOfPgVal));
mapIoPane.getChildren().add(new HBox(roFlagLbl, roFlagVal));
mapIoPane.getChildren().add(new Separator());
mapIoPane.getChildren().addAll(
new HBox(altStPgNnumOfPgLbl, altStPgNnumOfPgVal),
new HBox(roFlagLbl, roFlagVal),
new Separator()
);
}
byte[] mapNormalPageRwBarr = kacProvider.getMapNormalPage();
if (mapNormalPageRwBarr != null){
@ -128,22 +126,34 @@ public class KernelAccessControlController {
mapNormalPageRwLbl.setText(stringBuilder.toString());
}
if (kacProvider.isInterruptPairAvailable()){
interruptPairAvalLbl.setText("(available)");
stringBuilder = new StringBuilder();
for (byte b : kacProvider.getIrq0())
stringBuilder.append(b);
stringBuilder.reverse();
irq0Lbl.setText(stringBuilder.toString());
for (Map.Entry entry : kacProvider.getInterruptPairs().entrySet()){
Label no = new Label("# "+entry.getKey());
Label irq0Lbl = new Label("irq0:");
Label irq1Lbl = new Label("irq1:");
Label irq0, irq1;
stringBuilder = new StringBuilder();
for (byte b : kacProvider.getIrq1())
for (byte b : ((byte[][]) entry.getValue())[0])
stringBuilder.append(b);
stringBuilder.reverse();
irq1Lbl.setText(stringBuilder.toString());
}
else {
interruptPairAvalLbl.setText("(not available)");
irq0 = new Label(stringBuilder.toString());
for (byte b : ((byte[][]) entry.getValue())[1])
stringBuilder.append(b);
stringBuilder.reverse();
irq1 = new Label(stringBuilder.toString());
no.setPadding(new Insets(5.0, 5.0, 5.0, 5.0));
irq0Lbl.setPadding(new Insets(5.0, 5.0, 5.0, 5.0));
irq1Lbl.setPadding(new Insets(5.0, 5.0, 5.0, 5.0));
irq0.setPadding(new Insets(5.0, 5.0, 5.0, 5.0));
irq1.setPadding(new Insets(5.0, 5.0, 5.0, 5.0));
interruptPairsPane.getChildren().addAll(
no,
new HBox(irq0Lbl, irq0),
new HBox(irq1Lbl, irq1),
new Separator()
);
}
switch (kacProvider.getApplicationType()){
case 0:

View file

@ -75,14 +75,21 @@ public class NPDMController implements ITabController {
acidKernelAccessControlOffsetLbl,
acidKernelAccessControlSizeLbl,
acidReserved2Lbl;
//ACID
@FXML
private FSAccessControlController FSAccessControlTableController;
private FSAccessControlController ACIDFSAccessControlTableController;
@FXML
private ServiceAccessControlController ServiceAccessControlTableController;
private ServiceAccessControlController ACIDServiceAccessControlTableController;
@FXML
private KernelAccessControlController KernelAccessControlTableController;
private KernelAccessControlController ACIDKernelAccessControlTableController;
// ACI0
@FXML
private ServiceAccessControlController ACI0ServiceAccessControlTableController;
@FXML
private KernelAccessControlController ACI0KernelAccessControlTableController;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) { }
@ -167,12 +174,13 @@ public class NPDMController implements ITabController {
acidKernelAccessControlOffsetLbl.setText("-");
acidKernelAccessControlSizeLbl.setText("-");
acidReserved2Lbl.setText("-");
FSAccessControlTableController.resetTab();
ServiceAccessControlTableController.resetTab();
KernelAccessControlTableController.resetTab();
// ACID
ACIDFSAccessControlTableController.resetTab();
ACIDServiceAccessControlTableController.resetTab();
ACIDKernelAccessControlTableController.resetTab();
// ACI0
ACI0ServiceAccessControlTableController.resetTab();
ACI0KernelAccessControlTableController.resetTab();
}
private void setData(NPDMProvider npdmProvider, File file) {
if (npdmProvider == null)
@ -212,6 +220,10 @@ public class NPDMController implements ITabController {
aci0KernelAccessControlOffsetLbl.setText(Integer.toString(aci0.getKernelAccessControlOffset()));
aci0KernelAccessControlSizeLbl.setText(Integer.toString(aci0.getKernelAccessControlSize()));
aci0Reserved3Lbl.setText(byteArrToHexString(aci0.getReserved3()));
ACI0ServiceAccessControlTableController.populateFields(aci0.getServiceAccessControlProvider().getCollection());
ACI0KernelAccessControlTableController.populateFields(aci0.getKernelAccessControlProvider());
// ACID
ACIDProvider acid = npdmProvider.getAcid();
acidRsa2048signatureTf.setText(byteArrToHexString(acid.getRsa2048signature()));
@ -233,8 +245,8 @@ public class NPDMController implements ITabController {
acidKernelAccessControlSizeLbl.setText(Integer.toString(acid.getKernelAccessControlSize()));
acidReserved2Lbl.setText(byteArrToHexString(acid.getReserved2()));
FSAccessControlTableController.populateFields(acid.getFsAccessControlProvider());
ServiceAccessControlTableController.populateFields(acid.getServiceAccessControlProvider().getCollection());
KernelAccessControlTableController.populateFields(acid.getKernelAccessControlProvider());
ACIDFSAccessControlTableController.populateFields(acid.getFsAccessControlProvider());
ACIDServiceAccessControlTableController.populateFields(acid.getServiceAccessControlProvider().getCollection());
ACIDKernelAccessControlTableController.populateFields(acid.getKernelAccessControlProvider());
}
}

View file

@ -30,6 +30,11 @@ public class LoperConverter {
sb.append(String.format("%02x", b));
return sb.toString();
}
public static String longToOctString(long value){
return String.format("%64s", Long.toBinaryString( value )).replace(' ', '0');
}
public static byte[] flip(byte[] bytes){
int size = bytes.length;
byte[] ret = new byte[size];

View file

@ -33,4 +33,8 @@ public class RainbowHexDump {
public static void octDumpInt(int value){
System.out.println(String.format("%32s", Integer.toBinaryString( value )).replace(' ', '0')+" | "+value);
}
public static void octDumpLong(long value){
System.out.println(String.format("%64s", Long.toBinaryString( value )).replace(' ', '0')+" | "+value);
}
}

View file

@ -1,8 +1,10 @@
package konogonka.Tools.NPDM;
import konogonka.Tools.NPDM.ACID.KernelAccessControlProvider;
import konogonka.Tools.NPDM.ACID.ServiceAccessControlProvider;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.LinkedList;
import static konogonka.LoperConverter.getLEint;
@ -19,6 +21,10 @@ public class ACI0Provider {
private int kernelAccessControlSize;
private byte[] reserved3;
private FSAccessHeaderProvider fsAccessHeaderProvider;
private ServiceAccessControlProvider serviceAccessControlProvider;
private KernelAccessControlProvider kernelAccessControlProvider;
public ACI0Provider(byte[] aci0bytes) throws Exception {
if (aci0bytes.length < 0x40)
throw new Exception("ACI0 size is too short");
@ -33,6 +39,10 @@ public class ACI0Provider {
kernelAccessControlOffset = getLEint(aci0bytes, 0x30);
kernelAccessControlSize = getLEint(aci0bytes, 0x34);
reserved3 = Arrays.copyOfRange(aci0bytes, 0x38, 0x40);
fsAccessHeaderProvider = new FSAccessHeaderProvider(Arrays.copyOfRange(aci0bytes, fsAccessHeaderOffset, fsAccessHeaderOffset+fsAccessHeaderSize));
serviceAccessControlProvider = new ServiceAccessControlProvider(Arrays.copyOfRange(aci0bytes, serviceAccessControlOffset, serviceAccessControlOffset+serviceAccessControlSize));
kernelAccessControlProvider = new KernelAccessControlProvider(Arrays.copyOfRange(aci0bytes, kernelAccessControlOffset, kernelAccessControlOffset+kernelAccessControlSize));
}
public String getMagicNum() { return magicNum; }
@ -46,4 +56,8 @@ public class ACI0Provider {
public int getKernelAccessControlOffset() { return kernelAccessControlOffset; }
public int getKernelAccessControlSize() { return kernelAccessControlSize; }
public byte[] getReserved3() { return reserved3; }
public FSAccessHeaderProvider getFsAccessHeaderProvider() { return fsAccessHeaderProvider; }
public ServiceAccessControlProvider getServiceAccessControlProvider() { return serviceAccessControlProvider; }
public KernelAccessControlProvider getKernelAccessControlProvider() { return kernelAccessControlProvider; }
}

View file

@ -1,5 +1,7 @@
package konogonka.Tools.NPDM.ACID;
import konogonka.LoperConverter;
import java.util.Arrays;
/**
@ -9,18 +11,18 @@ public class FSAccessControlProvider {
private byte version;
private byte[] padding;
private byte[] permissionsBitmask; // ??? Where each byte representing 255-long bit-bask of the thing it representing. Like 0x01 bit-mask for ApplicationInfo
private long permissionsBitmask;
private byte[] reserved;
public FSAccessControlProvider(byte[] bytes) {
version = bytes[0];
padding = Arrays.copyOfRange(bytes, 1, 0x4);
permissionsBitmask = Arrays.copyOfRange(bytes, 0x4, 0xC);
permissionsBitmask = LoperConverter.getLElong(bytes, 0x4);
reserved = Arrays.copyOfRange(bytes, 0xC, 0x2C);
}
public byte getVersion() { return version; }
public byte[] getPadding() { return padding; }
public byte[] getPermissionsBitmask() { return permissionsBitmask; }
public long getPermissionsBitmask() { return permissionsBitmask; }
public byte[] getReserved() { return reserved; }
}

View file

@ -1,9 +1,12 @@
package konogonka.Tools.NPDM.ACID;
import konogonka.LoperConverter;
import konogonka.RainbowHexDump;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
/*
NOTE: This implementation is extremely bad for using application as library. Use raw for own purposes.
@ -81,9 +84,7 @@ public class KernelAccessControlProvider {
// MapNormalPage (RW)
private byte[] mapNormalPage; // TODO: clarify is possible to have multiple
// InterruptPair
private boolean interruptPairAvailable;
private byte[] irq0,
irq1;
private LinkedHashMap<Integer, byte[][]> interruptPairs; // Number; irq0, irq2
// Application type
private int applicationType;
// KernelReleaseVersion
@ -97,12 +98,13 @@ public class KernelAccessControlProvider {
canBeDebugged,
canDebugOthers;
KernelAccessControlProvider(byte[] bytes) throws Exception{
public KernelAccessControlProvider(byte[] bytes) throws Exception{
if (bytes.length < 4)
throw new Exception("ACID-> KernelAccessControlProvider: too small size of the Kernel Access Control");
rawData = new LinkedList<Integer>();
interruptPairs = new LinkedHashMap<>();
syscallMasks = new LinkedHashMap<Byte, byte[]>();
mapIoOrNormalRange = new LinkedHashMap<byte[], Boolean>();
@ -160,14 +162,19 @@ public class KernelAccessControlProvider {
//System.out.println();
break;
case INTERRUPTPAIR:
System.out.println("INTERRUPTPAIR found (must (?) appear once, please report if it's not)");
interruptPairAvailable = true;
irq0 = new byte[10];
irq1 = new byte[10];
//System.out.println("INTERRUPTPAIR");
//RainbowHexDump.octDumpInt(block);
byte[][] pair = new byte[2][];
byte[] irq0 = new byte[10];
byte[] irq1 = new byte[10];
for (int k = 21; k >= 12; k--)
irq0[k-12] = (byte) (block >> k & 1);
for (int k = 31; k >= 22; k--)
irq1[k-22] = (byte) (block >> k & 1);
pair[0] = irq0;
pair[1] = irq1;
interruptPairs.put(interruptPairs.size(), pair);
break;
case APPLICATIONTYPE:
applicationType = block >> 14 & 0b111;
@ -193,7 +200,6 @@ public class KernelAccessControlProvider {
System.out.println("UNKNOWN\t\t"+block+" "+type);
}
}
//System.out.println();
}
private int getMinBitCnt(int value){
@ -212,9 +218,7 @@ public class KernelAccessControlProvider {
public int getKernelFlagThreadPrioLo() { return kernelFlagThreadPrioLo; }
public LinkedHashMap<byte[], Boolean> getMapIoOrNormalRange() { return mapIoOrNormalRange; }
public byte[] getMapNormalPage() { return mapNormalPage; }
public boolean isInterruptPairAvailable() { return interruptPairAvailable; }
public byte[] getIrq0() { return irq0; }
public byte[] getIrq1() { return irq1; }
public LinkedHashMap<Integer, byte[][]> getInterruptPairs() { return interruptPairs; }
public int getApplicationType() { return applicationType; }
public boolean isKernelRelVersionAvailable() { return isKernelRelVersionAvailable; }
public int getKernelRelVersionMajor() { return kernelRelVersionMajor; }

View file

@ -0,0 +1,56 @@
package konogonka.Tools.NPDM;
import konogonka.LoperConverter;
import konogonka.RainbowHexDump;
import java.util.Arrays;
/**
* For ACI0 Provider
* */
public class FSAccessHeaderProvider {
private byte version;
private byte[] padding;
private long permissionsBitmask;
private int dataSize;
private int contentOwnIdSectionSize;
private int dataNownerSizes;
private int saveDataOwnSectionSize;
private byte[] unknownData;
public FSAccessHeaderProvider(byte[] bytes) {
version = bytes[0];
padding = Arrays.copyOfRange(bytes, 1, 0x4);
permissionsBitmask = LoperConverter.getLElong(bytes, 0x4);
dataSize = LoperConverter.getLEint(bytes, 0xC);
contentOwnIdSectionSize = LoperConverter.getLEint(bytes, 0x10);
dataNownerSizes = LoperConverter.getLEint(bytes, 0x14);
saveDataOwnSectionSize = LoperConverter.getLEint(bytes, 0x18);
unknownData = Arrays.copyOfRange(bytes, 0x1C, bytes.length);
//
System.out.println("version "+version);
System.out.print("padding ");
RainbowHexDump.hexDumpUTF8(padding);
System.out.print("Permissions Bitmask ");
RainbowHexDump.octDumpLong(permissionsBitmask);
System.out.println(
"DataSize "+dataSize+"\n"+
"Content OwnId Section Size "+contentOwnIdSectionSize+"\n"+
"Data + owner "+dataNownerSizes+"\n"+
"Save Data Own Section Size "+saveDataOwnSectionSize
);
RainbowHexDump.hexDumpUTF8(Arrays.copyOfRange(bytes, 0x1C, bytes.length));
//*/
//reserved = Arrays.copyOfRange(bytes, 0xC, 0x2C);
}
public byte getVersion() { return version; }
public byte[] getPadding() { return padding; }
public long getPermissionsBitmask() { return permissionsBitmask; }
public int getDataSize() { return dataSize; }
public int getContentOwnIdSectionSize() { return contentOwnIdSectionSize; }
public int getDataNownerSizes() { return dataNownerSizes; }
public int getSaveDataOwnSectionSize() { return saveDataOwnSectionSize; }
public byte[] getUnknownData() { return unknownData; }
}

View file

@ -211,7 +211,7 @@
<children>
<HBox spacing="5.0">
<children>
<Label text="Permissions bitmask (Raw, big-endian) : ">
<Label text="Permissions bitmask (Raw) : ">
<padding>
<Insets left="5.0" right="5.0" />
</padding>

View file

@ -117,49 +117,16 @@
</font></Label>
<Label fx:id="mapNormalPageRwLbl" text="-" />
<Separator prefWidth="200.0" />
<HBox spacing="5.0">
<children>
<Label text="Interrupt pair">
<Label text="Interrupt pairs">
<font>
<Font name="System Bold" size="13.0" />
</font>
</Label>
<Label fx:id="interruptPairAvalLbl" text="?" />
</children>
</HBox>
<GridPane gridLinesVisible="true">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="50.0" minWidth="40.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="400.0" minWidth="300.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<VBox fx:id="interruptPairsPane">
<children>
<Label text="Irq0">
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</Label>
<Label text="Irq1" GridPane.rowIndex="1">
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</Label>
<Label fx:id="irq0Lbl" text="-" GridPane.columnIndex="1">
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</Label>
<Label fx:id="irq1Lbl" text="-" GridPane.columnIndex="1" GridPane.rowIndex="1">
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</Label>
</children>
</GridPane>
<Separator prefWidth="200.0" />
</children>
</VBox>
<HBox spacing="5.0">
<children>
<Label text="Application Type:">

View file

@ -441,6 +441,8 @@
</TitledPane>
<TitledPane text="ACI0">
<content>
<VBox spacing="5.0">
<children>
<GridPane gridLinesVisible="true">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="60.0" minWidth="55.0" />
@ -733,6 +735,10 @@
</Label>
</children>
</GridPane>
<fx:include fx:id="ACI0ServiceAccessControlTable" source="ServiceAccessControlTable.fxml" />
<fx:include fx:id="ACI0KernelAccessControlTable" source="KernelAccessControlTable.fxml" />
</children>
</VBox>
</content>
</TitledPane>
<TitledPane text="ACID">
@ -1173,9 +1179,9 @@
<Label text="* with the size field from 0x204" />
<Label text="** [5.0.0+] bit2-3: PoolPartition? For applets set to 0b01, for sysmodules set to 0b10. Exceptions: &quot;starter&quot; is set to 0, &quot;nvservices&quot; is set to 3" />
<Label text="*** Inside of ACID block" />
<fx:include fx:id="FSAccessControlTable" source="FSAccessControlTable.fxml" />
<fx:include fx:id="ServiceAccessControlTable" source="ServiceAccessControlTable.fxml" />
<fx:include fx:id="KernelAccessControlTable" source="KernelAccessControlTable.fxml" />
<fx:include fx:id="ACIDFSAccessControlTable" source="FSAccessControlTable.fxml" />
<fx:include fx:id="ACIDServiceAccessControlTable" source="ServiceAccessControlTable.fxml" />
<fx:include fx:id="ACIDKernelAccessControlTable" source="KernelAccessControlTable.fxml" />
</children>
</VBox>
</content>