/**
 * Try undo the harm done by the init function.
 *
 * This may leave the system in an unstable state since we might have been
 * hijacking memory below 1MB that is in use by the kernel.
 */
void vmmR0TripleFaultHackTerm(void)
{
    /*
     * Restore overwritten memory.
     */
    if (   g_pvSavedLowCore
        && g_pbLowCore)
        memcpy(g_pbLowCore, g_pvSavedLowCore, PAGE_SIZE);

    if (g_pbPage0)
    {
        g_pbPage0[0x467+0] = RT_BYTE1(g_u32SavedVector);
        g_pbPage0[0x467+1] = RT_BYTE2(g_u32SavedVector);
        g_pbPage0[0x467+2] = RT_BYTE3(g_u32SavedVector);
        g_pbPage0[0x467+3] = RT_BYTE4(g_u32SavedVector);

        g_pbPage0[0x472+0] = RT_BYTE1(g_u16SavedCadIndicator);
        g_pbPage0[0x472+1] = RT_BYTE2(g_u16SavedCadIndicator);
    }

    /*
     * Fix the CMOS.
     */
    if (g_pvSavedLowCore)
    {
        uint32_t fSaved = ASMIntDisableFlags();

        ASMOutU8(0x70, 0x0f);
        ASMOutU8(0x71, 0x0a);

        ASMOutU8(0x70, 0x00);
        ASMInU8(0x71);

        ASMReloadCR3();
        ASMWriteBackAndInvalidateCaches();

        ASMSetFlags(fSaved);
    }

    /*
     * Release resources.
     */
    RTMemFree(g_pvSavedLowCore);
    g_pvSavedLowCore = NULL;

    RTR0MemObjFree(g_hMemLowCore, true /*fFreeMappings*/);
    g_hMemLowCore   = NIL_RTR0MEMOBJ;
    g_hMapLowCore   = NIL_RTR0MEMOBJ;
    g_pbLowCore     = NULL;
    g_HCPhysLowCore = NIL_RTHCPHYS;

    RTR0MemObjFree(g_hMemPage0, true /*fFreeMappings*/);
    g_hMemPage0     = NIL_RTR0MEMOBJ;
    g_hMapPage0     = NIL_RTR0MEMOBJ;
    g_pbPage0       = NULL;
}
Exemple #2
0
/**
 * Reads a key by name from the host SMC.
 *
 * @returns success indicator.
 * @param   pszName             The key name, must be exactly 4 chars long.
 * @param   pbBuf               The output buffer.
 * @param   cbBuf               The buffer size. Max 32 bytes.
 */
static bool devR0SmcQueryHostKey(const char *pszName, uint8_t *pbBuf, size_t cbBuf)
{
    Assert(strlen(pszName) == 4);
    Assert(cbBuf <= 32);
    Assert(cbBuf > 0);

    /*
     * Issue the READ command.
     */
    uint32_t cMsSleep = 1;
    for (;;)
    {
        ASMOutU32(SMC_PORT_CMD, SMC_CMD_GET_KEY_VALUE);
        RTThreadSleep(cMsSleep);
        uint8_t bCurState = ASMInU8(SMC_PORT_CMD);
        if ((bCurState & 0xf) == 0xc)
            break;
        cMsSleep <<= 1;
        if (cMsSleep > 64)
        {
            LogRel(("devR0Smc: %s: bCurState=%#x, wanted %#x.\n", "cmd", bCurState, 0xc));
            return false;
        }
    }

    /*
     * Send it the key.
     */
    for (unsigned off = 0; off < 4; off++)
    {
        ASMOutU8(SMC_PORT_DATA, pszName[off]);
        if (!devR0SmcWaitHostState(4, "key"))
            return false;
    }

    /*
     * The desired amount of output.
     */
    ASMOutU8(SMC_PORT_DATA, (uint8_t)cbBuf);

    /*
     * Read the output.
     */
    for (size_t off = 0; off < cbBuf; off++)
    {
        if (!devR0SmcWaitHostState(5, off ? "data" : "len"))
            return false;
        pbBuf[off] = ASMInU8(SMC_PORT_DATA);
    }

    LogRel(("SMC: pbBuf=%.*s\n", cbBuf, pbBuf));
    return true;
}
/**
 * @callback_method_impl{FNBS3STRFORMATOUTPUT,
 *      Used by Bs3TestFailedV and Bs3TestSkippedV.}
 */
BS3_DECL_CALLBACK(size_t) bs3TestFailedStrOutput(char ch, void BS3_FAR *pvUser)
{
    PBS3TESTFAILEDBUF pBuf = (PBS3TESTFAILEDBUF)pvUser;

    /*
     * VMMDev first.  We postpone newline processing here so we can strip one
     * trailing newline.
     */
    if (g_fbBs3VMMDevTesting)
    {
        if (pBuf->fNewLine && ch != '\0')
            ASMOutU8(VMMDEV_TESTING_IOPORT_DATA, '\n');
        pBuf->fNewLine = ch == '\n';
        if (ch != '\n')
            ASMOutU8(VMMDEV_TESTING_IOPORT_DATA, ch);
    }

    /*
     * Console next.
     */
    if (ch != '\0')
    {
        BS3_ASSERT(pBuf->cchBuf < RT_ELEMENTS(pBuf->achBuf));
        pBuf->achBuf[pBuf->cchBuf++] = ch;

        /* Whether to flush the buffer.  We do line flushing here to avoid
           dropping too much info when the formatter crashes on bad input. */
        if (   pBuf->cchBuf < RT_ELEMENTS(pBuf->achBuf)
            && ch != '\n')
        {
            pBuf->fNewLine = false;
            return 1;
        }
        pBuf->fNewLine = '\n';
    }
    /* Try fit missing newline into the buffer. */
    else if (!pBuf->fNewLine && pBuf->cchBuf < RT_ELEMENTS(pBuf->achBuf))
    {
        pBuf->fNewLine = true;
        pBuf->achBuf[pBuf->cchBuf++] = '\n';
    }

    BS3_ASSERT(pBuf->cchBuf <= RT_ELEMENTS(pBuf->achBuf));
    Bs3PrintStrN(&pBuf->achBuf[0], pBuf->cchBuf);
    pBuf->cchBuf = 0;

    /* In case we failed to add trailing new line, print one separately.  */
    if (!pBuf->fNewLine)
        Bs3PrintChr('\n');

    return ch != '\0';
}
/**
 * R0 mode function to write byte value to parallel port control
 * register.
 * @returns VBox status code.
 * @param   pDrvIns     Driver instance.
 * @param   u64Arg      Data to be written to control register.
 */
static int drvR0HostParallelReqWriteControl(PPDMDRVINS pDrvIns, uint64_t u64Arg)
{
    PDRVHOSTPARALLEL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL);
    LogFlowFunc(("write to ctrl port=%#x val=%#x\n", pThis->u32LptAddrControl, u64Arg));
    ASMOutU8(pThis->u32LptAddrControl, (uint8_t)(u64Arg));
    return VINF_SUCCESS;
}
Exemple #5
0
static UINT32 VBoxWriteNVRAMByteArrayParam(const UINT8 *pbParam, UINT32 cbParam)
{
    UINT32 idxParam = 0;
    for (idxParam = 0; idxParam < cbParam; ++idxParam)
        ASMOutU8(EFI_VARIABLE_PARAM, pbParam[idxParam]);
    return idxParam;
}
Exemple #6
0
VOID EFIAPI
DebugAssert(IN CONST CHAR8 *FileName, IN UINTN LineNumber, IN CONST CHAR8 *Description)
{
    RTCCUINTREG SavedFlags = ASMIntDisableFlags();

    ASMOutU8(EFI_PANIC_PORT, EFI_PANIC_CMD_START_MSG);
    VBoxPanicMsgString("EFI Assertion failed!"
                       "\nFile:  ");
    VBoxPanicMsgString(FileName ? FileName : "<NULL>");
    VBoxPanicMsgString("\nLine:  ");
    VBoxPanicMsgDecimalU32((uint32_t)LineNumber);
    VBoxPanicMsgString("\nEDescription: ");
    VBoxPanicMsgString(Description ? Description : "<NULL>");
    ASMOutU8(EFI_PANIC_PORT, EFI_PANIC_CMD_END_MSG);

    ASMSetFlags(SavedFlags);
}
/**
 * R0 mode function to set the direction of parallel port -
 * operate in bidirectional mode or single direction.
 * @returns VBox status code.
 * @param   pDrvIns    Driver instance.
 * @param   u64Arg     Mode.
 */
static int drvR0HostParallelReqSetPortDir(PPDMDRVINS pDrvIns, uint64_t u64Arg)
{
    PDRVHOSTPARALLEL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL);
    uint8_t u8ReadControlVal;
    uint8_t u8WriteControlVal;

    if (u64Arg)
    {
       u8ReadControlVal = ASMInU8(pThis->u32LptAddrControl);
       u8WriteControlVal = u8ReadControlVal | LPT_CONTROL_ENABLE_BIDIRECT; /* enable input direction */
       ASMOutU8(pThis->u32LptAddrControl, u8WriteControlVal);
    }
    else
    {
        u8ReadControlVal = ASMInU8(pThis->u32LptAddrControl);
        u8WriteControlVal = u8ReadControlVal & ~LPT_CONTROL_ENABLE_BIDIRECT; /* disable input direction */
        ASMOutU8(pThis->u32LptAddrControl, u8WriteControlVal);
    }
    return VINF_SUCCESS;
}
RTDECL(void) RTLogWriteUser(const char *pch, size_t cb)
{
#ifdef IN_GUEST_R3
    VbglR3WriteLog(pch, cb);
#else  /* !IN_GUEST_R3 */
    const uint8_t *pau8 = (const uint8_t *)pch;
    if (cb > 1)
        ASMOutStrU8(RTLOG_DEBUG_PORT, pau8, cb);
    else if (cb)
        ASMOutU8(RTLOG_DEBUG_PORT, *pau8);
#endif /* !IN_GUEST_R3 */
}
BS3_DECL_NEAR_CALLBACK(void) BS3_CMN_NM(bs3PitIrqHandler)(PBS3TRAPFRAME pTrapFrame)
{
    uint16_t cMsIntercal = g_cBs3PitIntervalMs;
    if (cMsIntercal)
    {
        g_cBs3PitMs += cMsIntercal;
        g_cBs3PitNs += g_cBs3PitIntervalNs;
        g_cBs3PitTicks++;
    }
    NOREF(pTrapFrame);
    ASMOutU8(0x20, 0x20); /** @todo function! */
}
Exemple #10
0
VOID EFIAPI
DebugAssert(IN CONST CHAR8 *FileName, IN UINTN LineNumber, IN CONST CHAR8 *Description)
{
    RTCCUINTREG SavedFlags = ASMIntDisableFlags();

    VBoxPrintString("EFI Assertion failed! File=");
    VBoxPrintString(FileName ? FileName : "<NULL>");
    VBoxPrintString(" line=0x");
    VBoxPrintHex(LineNumber, sizeof(LineNumber));
    VBoxPrintString("\nDescription: ");
    VBoxPrintString(Description ? Description : "<NULL>");

    ASMOutU8(EFI_PANIC_PORT, 2); /** @todo fix this. */

    ASMSetFlags(SavedFlags);
}
/**
 * Prints a char.
 * @returns 1.
 * @param   ch              The char to print.
 */
DECLINLINE(int) vboxPrintHexDumpChar(int ch)
{
    ASMOutU8(EFI_DEBUG_PORT, (uint8_t)ch);
    return 1;
}
/**
 * Initalizes the triple fault / boot hack.
 *
 * Always call vmmR0TripleFaultHackTerm to clean up, even when this call fails.
 *
 * @returns VBox status code.
 */
int vmmR0TripleFaultHackInit(void)
{
    /*
     * Map the first page.
     */
    int rc = RTR0MemObjEnterPhys(&g_hMemPage0, 0, PAGE_SIZE, RTMEM_CACHE_POLICY_DONT_CARE);
    AssertRCReturn(rc, rc);
    rc = RTR0MemObjMapKernel(&g_hMapPage0, g_hMemPage0, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
    AssertRCReturn(rc, rc);
    g_pbPage0 = (uint8_t *)RTR0MemObjAddress(g_hMapPage0);
    LogRel(("0040:0067 = %04x:%04x\n", RT_MAKE_U16(g_pbPage0[0x467+2],  g_pbPage0[0x467+3]),  RT_MAKE_U16(g_pbPage0[0x467+0],  g_pbPage0[0x467+1]) ));

    /*
     * Allocate some "low core" memory.  If that fails, just grab some memory.
     */
    //rc = RTR0MemObjAllocPhys(&g_hMemLowCore, PAGE_SIZE, _1M - 1);
    //__debugbreak();
    rc = RTR0MemObjEnterPhys(&g_hMemLowCore, 0x7000, PAGE_SIZE, RTMEM_CACHE_POLICY_DONT_CARE);
    AssertRCReturn(rc, rc);
    rc = RTR0MemObjMapKernel(&g_hMapLowCore, g_hMemLowCore, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
    AssertRCReturn(rc, rc);
    g_pbLowCore = (uint8_t *)RTR0MemObjAddress(g_hMapLowCore);
    g_HCPhysLowCore = RTR0MemObjGetPagePhysAddr(g_hMapLowCore, 0);
    LogRel(("Low core at %RHp mapped at %p\n", g_HCPhysLowCore, g_pbLowCore));

    /*
     * Save memory we'll be overwriting.
     */
    g_pvSavedLowCore = RTMemAlloc(PAGE_SIZE);
    AssertReturn(g_pvSavedLowCore, VERR_NO_MEMORY);
    memcpy(g_pvSavedLowCore, g_pbLowCore, PAGE_SIZE);

    g_u32SavedVector = RT_MAKE_U32_FROM_U8(g_pbPage0[0x467], g_pbPage0[0x467+1], g_pbPage0[0x467+2], g_pbPage0[0x467+3]);
    g_u16SavedCadIndicator = RT_MAKE_U16(g_pbPage0[0x472], g_pbPage0[0x472+1]);

    /*
     * Install the code.
     */
    size_t cbCode = (uintptr_t)&vmmR0TripleFaultHackEnd - (uintptr_t)&vmmR0TripleFaultHackStart;
    AssertLogRelReturn(cbCode <= PAGE_SIZE, VERR_OUT_OF_RANGE);
    memcpy(g_pbLowCore, &vmmR0TripleFaultHackStart, cbCode);

    g_pbPage0[0x467+0] = 0x00;
    g_pbPage0[0x467+1] = 0x70;
    g_pbPage0[0x467+2] = 0x00;
    g_pbPage0[0x467+3] = 0x00;

    g_pbPage0[0x472+0] = 0x34;
    g_pbPage0[0x472+1] = 0x12;

    /*
     * Configure the status port and cmos shutdown command.
     */
    uint32_t fSaved = ASMIntDisableFlags();

    ASMOutU8(0x70, 0x0f);
    ASMOutU8(0x71, 0x0a);

    ASMOutU8(0x70, 0x05);
    ASMInU8(0x71);

    ASMReloadCR3();
    ASMWriteBackAndInvalidateCaches();

    ASMSetFlags(fSaved);

#if 1 /* For testing & debugging. */
    vmmR0TripleFaultHackTripleFault();
#endif

    return VINF_SUCCESS;
}
/**
 * Prints a char.
 * @param   ch              The char to print.
 */
DECLINLINE(void) vboxPrintHexChar(int ch)
{
    ASMOutU8(EFI_DEBUG_PORT, (uint8_t)ch);
}