diff options
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/service/err_f.cpp | 165 | 
1 files changed, 164 insertions, 1 deletions
| diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp index 8d765acb5..58c5acd1e 100644 --- a/src/core/hle/service/err_f.cpp +++ b/src/core/hle/service/err_f.cpp @@ -10,8 +10,171 @@  namespace ERR_F { +enum { +    ErrSpecifier0 = 0, +    ErrSpecifier1 = 1, +    ErrSpecifier3 = 3, +    ErrSpecifier4 = 4, +}; + +// This is used instead of ResultCode from result.h +// because we can't have non-trivial data members in unions. +union RSL { +    u32 raw; + +    BitField<0, 10, u32> description; +    BitField<10, 8, u32> module; +    BitField<21, 6, u32> summary; +    BitField<27, 5, u32> level; +}; + +union ErrInfo { +    u8 specifier; + +    struct { +        u8 specifier;                // 0x0 +        u8 rev_high;                 // 0x1 +        u16 rev_low;                 // 0x2 +        RSL result_code;             // 0x4 +        u32 address;                 // 0x8 +        INSERT_PADDING_BYTES(4);     // 0xC +        u32 pid_low;                 // 0x10 +        u32 pid_high;                // 0x14 +        u32 aid_low;                 // 0x18 +        u32 aid_high;                // 0x1C +    } errtype1; + +    struct { +        u8 specifier;                // 0x0 +        u8 rev_high;                 // 0x1 +        u16 rev_low;                 // 0x2 +        INSERT_PADDING_BYTES(0xC);   // 0x4 +        u32 pid_low;                 // 0x10 +        u32 pid_high;                // 0x14 +        u32 aid_low;                 // 0x18 +        u32 aid_high;                // 0x1C +        u8 error_type;               // 0x20 +        INSERT_PADDING_BYTES(3);     // 0x21 +        u32 fault_status_reg;        // 0x24 +        u32 fault_addr;              // 0x28 +        u32 fpexc;                   // 0x2C +        u32 finst;                   // 0x30 +        u32 finst2;                  // 0x34 +        INSERT_PADDING_BYTES(0x34);  // 0x38 +        u32 sp;                      // 0x6C +        u32 pc;                      // 0x70 +        u32 lr;                      // 0x74 +        u32 cpsr;                    // 0x78 +    } errtype3; + +    struct { +        u8 specifier;                // 0x0 +        u8 rev_high;                 // 0x1 +        u16 rev_low;                 // 0x2 +        RSL result_code;             // 0x4 +        INSERT_PADDING_BYTES(8);     // 0x8 +        u32 pid_low;                 // 0x10 +        u32 pid_high;                // 0x14 +        u32 aid_low;                 // 0x18 +        u32 aid_high;                // 0x1C +        char debug_string1[0x2E];    // 0x20 +        char debug_string2[0x2E];    // 0x4E +    } errtype4; +}; + +enum { +    PrefetchAbort = 0, +    DataAbort     = 1, +    UndefInstr    = 2, +    VectorFP      = 3 +}; + +static std::string GetErrInfo3Type(u8 type_code) { +    switch (type_code) { +    case PrefetchAbort: return "Prefetch Abort"; +    case DataAbort:     return "Data Abort"; +    case UndefInstr:    return "Undefined Instruction"; +    case VectorFP:      return "Vector Floating Point"; +    default: return "unknown"; +    } +} + +static void ThrowFatalError(Service::Interface* self) { +    u32* cmd_buff = Kernel::GetCommandBuffer(); + +    LOG_CRITICAL(Service_ERR, "Fatal error!"); +    const ErrInfo* errinfo = reinterpret_cast<ErrInfo*>(&cmd_buff[1]); + +    switch (errinfo->specifier) { +    case ErrSpecifier0: +    case ErrSpecifier1: +    { +        const auto& errtype = errinfo->errtype1; +        LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); +        LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16)); +        LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high); +        LOG_CRITICAL(Service_ERR, "ADR: 0x%08X", errtype.address); + +        LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw); +        LOG_CRITICAL(Service_ERR, "  Level: %u",   errtype.result_code.level.Value()); +        LOG_CRITICAL(Service_ERR, "  Summary: %u", errtype.result_code.summary.Value()); +        LOG_CRITICAL(Service_ERR, "  Module: %u",  errtype.result_code.module.Value()); +        LOG_CRITICAL(Service_ERR, "  Desc: %u",    errtype.result_code.description.Value()); +        break; +    } + +    case ErrSpecifier3: +    { +        const auto& errtype = errinfo->errtype3; +        LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); +        LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16)); +        LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high); +        LOG_CRITICAL(Service_ERR, "TYPE: %s", GetErrInfo3Type(errtype.error_type).c_str()); + +        LOG_CRITICAL(Service_ERR, "PC: 0x%08X", errtype.pc); +        LOG_CRITICAL(Service_ERR, "LR: 0x%08X", errtype.lr); +        LOG_CRITICAL(Service_ERR, "SP: 0x%08X", errtype.sp); +        LOG_CRITICAL(Service_ERR, "CPSR: 0x%08X", errtype.cpsr); + +        switch (errtype.error_type) { +        case PrefetchAbort: +        case DataAbort: +            LOG_CRITICAL(Service_ERR, "Fault Address: 0x%08X", errtype.fault_addr); +            LOG_CRITICAL(Service_ERR, "Fault Status Register: 0x%08X", errtype.fault_status_reg); +            break; +        case VectorFP: +            LOG_CRITICAL(Service_ERR, "FPEXC: 0x%08X", errtype.fpexc); +            LOG_CRITICAL(Service_ERR, "FINST: 0x%08X", errtype.finst); +            LOG_CRITICAL(Service_ERR, "FINST2: 0x%08X", errtype.finst2); +            break; +        } +        break; +    } + +    case ErrSpecifier4: +    { +        const auto& errtype = errinfo->errtype4; +        LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); +        LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16)); +        LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high); + +        LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw); +        LOG_CRITICAL(Service_ERR, "  Level: %u",   errtype.result_code.level.Value()); +        LOG_CRITICAL(Service_ERR, "  Summary: %u", errtype.result_code.summary.Value()); +        LOG_CRITICAL(Service_ERR, "  Module: %u",  errtype.result_code.module.Value()); +        LOG_CRITICAL(Service_ERR, "  Desc: %u",    errtype.result_code.description.Value()); + +        LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string1); +        LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string2); +        break; +    } +    } + +    cmd_buff[1] = 0; // No error +} +  const Interface::FunctionInfo FunctionTable[] = { -    {0x00010800, nullptr,               "ThrowFatalError"} +    {0x00010800, ThrowFatalError,           "ThrowFatalError"}  };  //////////////////////////////////////////////////////////////////////////////////////////////////// | 
