SceError

From Vita Development Wiki
Jump to navigation Jump to search

Module

Version World Privilege
1.69-3.60 Non-secure Kernel

Libraries

Known NIDs

Version Name World Visibility NID
1.69 SceErrorForDriver Non-secure Kernel 0xBA576248
1.69-3.60 SceError Non-secure User 0x5CD2CAD1

Types

typedef struct SceErrorDefaultFormat {
	int data1;
	int data2;
} SceErrorDefaultFormat;

typedef struct SceErrorStrings {
	char s[0x10];
} SceErrorStrings;

typedef struct SceErrorHistoryPostInfo { // size is 0x180
	char error_message[0x100];
	char data_0x100[0x40]; // unknown
	int error_code_hex;
	int data_0x174;
	SceUInt version;	// from SceKernelFwInfo
	int data_0x17C;
	char titleid[0xC];
	int data_0x15C;		// from SceKernelFwInfo->unk_24
	char data_0x160[0x20];
} SceErrorHistoryPostInfo;

typedef struct SceErrorHistoryInfo {
	int data_0x00;
	int data_0x04;
	SceInt64 time;
	SceErrorStrings error_code;
	char data_0x20[0x10];
	SceErrorHistoryPostInfo post;
} SceErrorHistoryInfo;

typedef struct SceErrorSequenceInfo { // size is 0x20
	int data[8];
} SceErrorSequenceInfo;

SceErrorForDriver

SceError

_sceErrorHistoryUpdateSequenceInfo

Version NID
1.69-3.60 0x6FBE4BDC
int _sceErrorHistoryUpdateSequenceInfo(const SceErrorSequenceInfo *info, int a2);

_sceErrorHistoryPostError

Version NID
1.69-3.60 0x70F9D872
int _sceErrorHistoryPostError(const SceErrorHistoryPostInfo *info);

_sceErrorGetExternalString

Version NID
1.69-3.60 0x85747003
int _sceErrorGetExternalString(SceErrorStrings *error_strings, int error_code);

_sceErrorHistorySetDefaultFormat

Version NID
1.69-3.60 0xB94DAA2F
//src_user is of size 0x08
int _sceErrorHistorySetDefaultFormat(void* src_user);

_sceErrorHistoryClearError

Version NID
1.69-3.60 0xC88F479E
//argument can be only 0, or SCE_ERROR_ERRNO_EINVAL error will be returned
int _sceErrorHistoryClearError(int zero);

_sceErrorHistoryGetError

Version NID
1.69-3.60 0xF16DF981
//dest_user is of size 0x1B0
int _sceErrorHistoryGetError (int unk0, void* dest_user);

Error table translation

In various places PSVita may display errors translated into their string representation. The code below also does this, provided you feed it with a copy of os0:kd/error_table.bin.

#include <stdlib.h>
#include <stdio.h>

#ifdef _MSC_VER
#define snprintf _snprintf
#endif

int read_error_table(const char *path, void *buf) {
  unsigned int v6; // r1@6
  unsigned int v7; // r1@10

  FILE *f = fopen(path, "rb");
  if ( f ) {
    if ( fread(buf, 1, 8, f) == 8 ) {
      v6 = *((short *)buf + 2);
      if ( v6 <= 0x20 )
      {
        if ( fread(*((int *)buf + 2), 1, 8 * v6, f) == 8 * v6
          && fread((char *)buf + 12, 1, 4, f) == 4 ) {
          v7 = *((short *)buf + 7);
          if ( v7 <= 0x36B0 ) {
            if ( fread(*((int *)buf + 4), 1, 4 * v7, f) == 4 * v7 ) {
              fclose(f);
              return 0;
            }
          }
          else
            fprintf(stderr, "[SceError] error_table_num = %d\n", v7);
        }
      }
      else
        fprintf(stderr, "[SceError] facility_group_num = %d\n", v6);
    }
    fclose(f);
  }
  *(int *)buf = 0;
  *((int *)buf + 1) = 0;
  *((int *)buf + 2) = 0;
  *((int *)buf + 3) = 0;
  *((int *)buf + 4) = 0;
  *((int *)buf + 5) = 0;
  return 0;
}

#define _WORD short
#define _DWORD int
#define _BYTE char

int error_code_to_string(int error_table, char *output, unsigned int error_code) {
    signed int v4; // r7@2
    int v5; // r4@2
    int v6; // r2@4
    int v7; // r5@4
    int v8; // t1@6
    int v9; // t1@9
    int v10; // t1@10
    int v11; // r5@11
    int v12; // r12@11
    int v13; // r6@11
    int v14; // r5@12
    int v15; // t1@12
    int v16; // r5@13
    int v17; // t1@13
    signed int v18; // lr@17
    unsigned int v19; // r3@17
    int v20; // r4@17
    int v21; // r6@18
    int v22; // r5@18
    signed int v23; // r6@19
    signed int v24; // r5@23
    signed int v25; // r5@25
    signed int v26; // r7@28
    int v27; // r5@28
    signed int v28; // r7@30
    signed int v29; // r7@32
    signed int v30; // r5@35
    int v31; // r6@37
    int v32; // r3@38
    int v33; // r4@39
    int v34; // r5@40
    signed int v35; // r2@41
    signed int v36; // r6@41
    int v37; // r7@42

    if (!output)
        return 0;
    v4 = *(_WORD *)(error_table + 14);
    v5 = *(_DWORD *)(error_table + 16);
    if (!*(_WORD *)(error_table + 14))
        goto LABEL_46;
    if (*(_DWORD *)v5 == error_code) {
        v6 = 0;
        goto LABEL_17;
    }
    v6 = 0;
    v7 = ((_BYTE)v4 - 1) & 3;
    if (!(((_BYTE)v4 - 1) & 3))
        goto LABEL_11;
    v6 = 1;
    if (v4 <= 1) {
    LABEL_46:
        snprintf(output, 16, "E-%08x", error_code);
        return 0;
    }
    v8 = *(_DWORD *)(v5 + 4);
    v5 += 4;
    if (v8 != error_code) {
        if (v7 == 1
            || (v7 == 2 || (v9 = *(_DWORD *)(v5 + 4), v5 += 4, v6 = 2, v9 != error_code))
            && (v10 = *(_DWORD *)(v5 + 4), v5 += 4, ++v6, v10 != error_code)) {
        LABEL_11:
            while (1) {
                ++v6;
                v11 = v5;
                v12 = v5 + 12;
                v13 = v6;
                v5 += 16;
                if (v6 >= v4)
                    goto LABEL_46;
                v15 = *(_DWORD *)(v11 + 4);
                v14 = v11 + 4;
                if (v15 != error_code) {
                    v17 = *(_DWORD *)(v14 + 4);
                    v16 = v14 + 4;
                    ++v6;
                    if (v17 != error_code) {
                        v6 = v13 + 2;
                        if (*(_DWORD *)(v16 + 4) != error_code) {
                            v6 = v13 + 3;
                            if (*(_DWORD *)(v12 + 4) != error_code)
                                continue;
                        }
                    }
                }
                break;
            }
        }
    }
    if (*(_WORD *)(error_table + 6) < v6) {
        snprintf(output, 16, "*-%08x", error_code);
        return 0;
    }
LABEL_17:
    v18 = *(_WORD *)(error_table + 4);
    v19 = (error_code >> 16) & 0xFFF;
    v20 = *(_DWORD *)(error_table + 8);
    if (*(_WORD *)(error_table + 4)) {
        v21 = 0;
        v22 = ((_BYTE)v18 - 1) & 3;
        if (!(((_BYTE)v18 - 1) & 3)) {
        LABEL_35:
            while (1) {
                v30 = *(_WORD *)v20;
                if ((signed int)v19 >= v30 && (signed int)v19 < *(_WORD *)(v20 + 2) + v30)
                    goto LABEL_48;
                v31 = v21 + 1;
                if (v31 >= v18)
                    goto LABEL_38;
                v20 += 8;
                v26 = *(_WORD *)v20;
                v27 = v20;
                if ((signed int)v19 >= v26 && (signed int)v19 < v26 + *(_WORD *)(v20 + 2))
                    goto LABEL_48;
                v28 = *(_WORD *)(v20 + 8);
                v20 += 8;
                if ((signed int)v19 >= v28 && (signed int)v19 < v28 + *(_WORD *)(v27 + 10))
                    goto LABEL_48;
                v29 = *(_WORD *)(v27 + 16);
                v20 = v27 + 16;
                if ((signed int)v19 >= v29 && (signed int)v19 < v29 + *(_WORD *)(v27 + 18))
                    goto LABEL_48;
                v21 = v31 + 3;
                v20 = v27 + 24;
            }
        }
        v23 = *(_WORD *)v20;
        if ((signed int)v19 >= v23 && (signed int)v19 < *(_WORD *)(v20 + 2) + v23) {
        LABEL_48:
            v32 = v20 + 4;
            goto LABEL_39;
        }
        v21 = 1;
        if (v18 > 1) {
            v20 += 8;
            if (v22 == 1)
                goto LABEL_35;
            if (v22 != 2) {
                v24 = *(_WORD *)v20;
                if ((signed int)v19 >= v24 && (signed int)v19 < *(_WORD *)(v20 + 2) + v24) {
                    v32 = v20 + 4;
                    goto LABEL_39;
                }
                v21 = 2;
                v20 += 8;
            }
            v25 = *(_WORD *)v20;
            if ((signed int)v19 < v25 || (signed int)v19 >= *(_WORD *)(v20 + 2) + v25) {
                ++v21;
                v20 += 8;
                goto LABEL_35;
            }
            goto LABEL_48;
        }
    }
LABEL_38:
    v32 = error_table;
LABEL_39:
    v33 = v6 + *(_WORD *)(error_table + 12);
    if (v33) {
        v35 = v6 + *(_WORD *)(error_table + 12);
        v36 = 0;
        do {
            v37 = v35 % 10;
            v35 /= 10;
            v36 += v37;
        } while (v35);
        v34 = v36 % 10;
    }
    else
        v34 = 0;
    snprintf(output, 16, "%s-%d-%1d", v32, v33, v34);
    return 0;
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Usage: ./error error_table.bin 0xC0DE");
        return 1;
    }
    int *error_table = calloc(1, 1024 * 1024);
    error_table[2] = calloc(1, 1024 * 1024);
    error_table[4] = calloc(1, 1024 * 1024);
    read_error_table(argv[1], error_table);

    char *str = calloc(1, 500);
    error_code_to_string(error_table, str, strtoul(argv[2], NULL, 0));
    printf("%s\n", str);

    free(str);
    free(error_table[2]);
    free(error_table[4]);
    free(error_table);

    return 0;
}