/** * 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; }
/** * 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; }
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; }
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! */ }
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); }