diff options
Diffstat (limited to '')
313 files changed, 53159 insertions, 0 deletions
diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/Makefile.kmk b/src/VBox/ValidationKit/bootsectors/bs3kit/Makefile.kmk new file mode 100644 index 00000000..5a7b77bd --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/Makefile.kmk @@ -0,0 +1,760 @@ +# $Id: Makefile.kmk $ +## @file +# VirtualBox Validation Kit - Bootsector Kit v3 +# + +# +# Copyright (C) 2006-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <https://www.gnu.org/licenses>. +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + +SUB_DEPTH = ../../../../.. +include $(KBUILD_PATH)/subheader.kmk + + + +# Boot Sector post-link tool (used via the parent Config.kmk). +BLDPROGS += VBoxBs3Linker +VBoxBs3Linker_TEMPLATE = VBoxBldProg +VBoxBs3Linker_SOURCES = $(VBOX_PATH_BS3KIT_SRC)/VBoxBs3Linker.cpp + + +# 64-bit relocation conversion tool (used via the parent Config.kmk). +BLDPROGS += VBoxBs3ObjConverter +VBoxBs3ObjConverter_TEMPLATE = VBoxBldProg +VBoxBs3ObjConverter_DEFS = BS3KIT_BS3CLASS16CODE=$(BS3KIT_BS3CLASS16CODE) IN_RT_R3 +VBoxBs3ObjConverter_SOURCES = \ + $(VBOX_PATH_BS3KIT_SRC)/VBoxBs3ObjConverter.cpp \ + $(PATH_ROOT)/src/VBox/Runtime/common/sort/shellsort.cpp + + +# The boot sector. +MISCBINS += bs3-bootsector +bs3-bootsector_TEMPLATE = VBoxBS3KitBS +bs3-bootsector_SOURCES = bs3-bootsector.asm + + +# +# Common sources to be compiled into _p16, _p32 and _p64 versions. +# +VBOX_BS3KIT_COMMON_SOURCES = \ + bs3-cmn-A20Disable.asm \ + bs3-cmn-A20Enable.asm \ + bs3-cmn-GetCpuVendor.c \ + bs3-cmn-GetModeName.c \ + bs3-cmn-GetModeNameShortLower.c \ + bs3-cmn-KbdRead.asm \ + bs3-cmn-KbdWait.asm \ + bs3-cmn-KbdWrite.asm \ + bs3-cmn-Shutdown.asm \ + bs3-cmn-Panic.asm \ + bs3-cmn-PrintChr.asm \ + bs3-cmn-Printf.c \ + bs3-cmn-PrintU32.asm \ + bs3-cmn-PrintX32.asm \ + bs3-cmn-PrintStr.c \ + bs3-cmn-PrintStrN.asm \ + bs3-cmn-StrFormatV.c \ + bs3-cmn-StrPrintf.c \ + bs3-cmn-StrLen.c \ + bs3-cmn-StrNLen.c \ + bs3-cmn-StrCpy.c \ + bs3-cmn-MemChr.asm \ + bs3-cmn-MemCmp.asm \ + bs3-cmn-MemCpy.c \ + bs3-cmn-MemPCpy.c \ + bs3-cmn-MemMove.c \ + bs3-cmn-MemSet.asm \ + bs3-cmn-MemZero.asm \ + bs3-cmn-MemAlloc.c \ + bs3-cmn-MemAllocZ.c \ + bs3-cmn-MemFree.c \ + bs3-cmn-MemGuardedTestPage.c \ + bs3-cmn-MemPrintInfo.c \ + bs3-cmn-PagingData.c \ + bs3-cmn-PagingInitRootForPP.c \ + bs3-cmn-PagingInitRootForPAE.c \ + bs3-cmn-PagingInitRootForLM.c \ + bs3-cmn-PagingAlias.c \ + bs3-cmn-PagingProtect.c \ + bs3-cmn-PagingQueryAddressInfo.c \ + bs3-cmn-PagingSetupCanonicalTraps.c \ + bs3-cmn-pic-data.c \ + bs3-cmn-PicMaskAll.c \ + bs3-cmn-PicUpdateMask.c \ + bs3-cmn-PicSetup.c \ + bs3-cmn-pit.c \ + bs3-cmn-PitIrqHandler.c \ + bs3-cmn-RegCtxRestore.asm \ + bs3-cmn-RegCtxConvertToRingX.c \ + bs3-cmn-RegCtxConvertV86ToRm.c \ + bs3-cmn-RegCtxPrint.c \ + bs3-cmn-RegCtxGetRspSsAsCurPtr.c \ + bs3-cmn-RegCtxSave.asm \ + bs3-cmn-RegCtxSaveEx.asm \ + bs3-cmn-RegCtxSaveForMode.c \ + bs3-cmn-RegCtxSetGrpSegFromCurPtr.c \ + bs3-cmn-RegCtxSetGrpSegFromFlat.c \ + bs3-cmn-RegCtxSetRipCsFromCurPtr.c \ + bs3-cmn-RegCtxSetRipCsFromFlat.c \ + bs3-cmn-RegCtxSetRipCsFromLnkPtr.c \ + bs3-cmn-RegCtxSetGpr.c \ + bs3-cmn-RegGetCr0.asm \ + bs3-cmn-RegGetCr2.asm \ + bs3-cmn-RegGetCr3.asm \ + bs3-cmn-RegGetCr4.asm \ + bs3-cmn-RegSetCr0.asm \ + bs3-cmn-RegSetCr2.asm \ + bs3-cmn-RegSetCr3.asm \ + bs3-cmn-RegSetCr4.asm \ + bs3-cmn-RegGetDr0.asm \ + bs3-cmn-RegGetDr1.asm \ + bs3-cmn-RegGetDr2.asm \ + bs3-cmn-RegGetDr3.asm \ + bs3-cmn-RegGetDr6.asm \ + bs3-cmn-RegGetDr7.asm \ + bs3-cmn-RegGetDrX.asm \ + bs3-cmn-RegSetDr0.asm \ + bs3-cmn-RegSetDr1.asm \ + bs3-cmn-RegSetDr2.asm \ + bs3-cmn-RegSetDr3.asm \ + bs3-cmn-RegSetDr6.asm \ + bs3-cmn-RegSetDr7.asm \ + bs3-cmn-RegSetDrX.asm \ + bs3-cmn-RegGetTr.asm \ + bs3-cmn-RegSetTr.asm \ + bs3-cmn-RegGetLdtr.asm \ + bs3-cmn-RegSetLdtr.asm \ + bs3-cmn-RegGetXcr0.asm \ + bs3-cmn-RegSetXcr0.asm \ + bs3-cmn-ExtCtxInit.c \ + bs3-cmn-ExtCtxSave.asm \ + bs3-cmn-ExtCtxSaveEx.asm \ + bs3-cmn-ExtCtxRestore.asm \ + bs3-cmn-ExtCtxRestoreEx.asm \ + bs3-cmn-ExtCtxGetSize.c \ + bs3-cmn-ExtCtxAlloc.c \ + bs3-cmn-ExtCtxFree.c \ + bs3-cmn-ExtCtxCopy.c \ + bs3-cmn-ExtCtxGetFcw.c \ + bs3-cmn-ExtCtxSetFcw.c \ + bs3-cmn-ExtCtxGetFsw.c \ + bs3-cmn-ExtCtxSetFsw.c \ + bs3-cmn-ExtCtxGetAbridgedFtw.c \ + bs3-cmn-ExtCtxSetAbridgedFtw.c \ + bs3-cmn-ExtCtxGetMxCsr.c \ + bs3-cmn-ExtCtxSetMxCsr.c \ + bs3-cmn-ExtCtxGetMxCsrMask.c \ + bs3-cmn-ExtCtxSetMxCsrMask.c \ + bs3-cmn-ExtCtxGetMm.c \ + bs3-cmn-ExtCtxSetMm.c \ + bs3-cmn-ExtCtxGetXmm.c \ + bs3-cmn-ExtCtxSetXmm.c \ + bs3-cmn-ExtCtxGetYmm.c \ + bs3-cmn-ExtCtxSetYmm.c \ + bs3-cmn-SelFar32ToFlat32.c \ + bs3-cmn-SelFar32ToFlat32NoClobber.asm \ + bs3-cmn-SelProtFar32ToFlat32.c \ + bs3-cmn-SelProtModeCodeToRealMode.asm \ + bs3-cmn-SelRealModeCodeToProtMode.asm \ + bs3-cmn-SelFlatCodeToRealMode.asm \ + bs3-cmn-SelFlatCodeToProtFar16.asm \ + bs3-cmn-SelRealModeDataToProtFar16.asm \ + bs3-cmn-SelProtFar16DataToRealMode.asm \ + bs3-cmn-SelRealModeDataToFlat.asm \ + bs3-cmn-SelProtFar16DataToFlat.asm \ + bs3-cmn-SelFlatDataToProtFar16.asm \ + bs3-cmn-SelFlatDataToRealMode.asm \ + bs3-cmn-SelLnkPtrToCurPtr.c \ + bs3-cmn-SelLnkPtrToFlat.c \ + bs3-cmn-SelSetup16BitData.c \ + bs3-cmn-SelSetup16BitCode.c \ + bs3-cmn-SelSetup32BitCode.c \ + bs3-cmn-SelSetupGate.c \ + bs3-cmn-SelSetupGate64.c \ + bs3-cmn-SlabInit.c \ + bs3-cmn-SlabAlloc.c \ + bs3-cmn-SlabAllocEx.c \ + bs3-cmn-SlabFree.c \ + bs3-cmn-SlabListInit.c \ + bs3-cmn-SlabListAdd.c \ + bs3-cmn-SlabListAlloc.c \ + bs3-cmn-SlabListAllocEx.c \ + bs3-cmn-SlabListFree.c \ + bs3-cmn-SwitchHlpConvRealModeRetfPopBpDecBpAndReturn.asm \ + bs3-cmn-SwitchHlpConvProtModeRetfPopBpDecBpAndReturn.asm \ + bs3-cmn-SwitchToRing0.asm \ + bs3-cmn-SwitchToRing1.asm \ + bs3-cmn-SwitchToRing2.asm \ + bs3-cmn-SwitchToRing3.asm \ + bs3-cmn-SwitchToRingX.asm \ + bs3-cmn-SwitchTo16Bit.asm \ + bs3-cmn-SwitchTo16BitV86.asm \ + bs3-cmn-SwitchTo32Bit.asm \ + bs3-cmn-SwitchTo64Bit.asm \ + bs3-cmn-Syscall.asm \ + bs3-cmn-TestData.c \ + bs3-cmn-TestInit.c \ + bs3-cmn-TestFailed.c \ + bs3-cmn-TestNow.asm \ + bs3-cmn-TestSkipped.c \ + bs3-cmn-TestSub.c \ + bs3-cmn-TestSubDone.c \ + bs3-cmn-TestSubErrorCount.c \ + bs3-cmn-TestTerm.c \ + bs3-cmn-TestSendCmdWithStr.asm \ + bs3-cmn-TestSendCmdWithU32.asm \ + bs3-cmn-TestIsVmmDevTestingPresent.asm \ + bs3-cmn-TestCheckRegCtxEx.c \ + bs3-cmn-TestCheckExtCtx.c \ + bs3-cmn-TestQueryCfgU8.asm \ + bs3-cmn-TestQueryCfgU32.asm \ + bs3-cmn-TestHostPrintf.c \ + bs3-cmn-TestPrintf.c \ + bs3-cmn-TestValue.c \ + bs3-cmn-TrapReInit.c \ + bs3-cmn-TrapRmV86Init.c \ + bs3-cmn-TrapRmV86SetGate.c \ + bs3-cmn-Trap16Init.c \ + bs3-cmn-Trap16SetGate.c \ + bs3-cmn-Trap32Init.c \ + bs3-cmn-Trap32SetGate.c \ + bs3-cmn-Trap64Init.c \ + bs3-cmn-Trap64SetGate.c \ + bs3-cmn-TrapSetDpl.c \ + bs3-cmn-TrapDefaultHandler.c \ + bs3-cmn-TrapHandlersData.asm \ + bs3-cmn-TrapPrintFrame.c \ + bs3-cmn-TrapSetHandler.c \ + bs3-cmn-TrapSetHandlerEx.c \ + bs3-cmn-TrapSetJmp.asm \ + bs3-cmn-TrapSetJmpAndRestore.c \ + bs3-cmn-TrapSetJmpAndRestoreInRm.c \ + bs3-cmn-TrapSetJmpAndRestoreWithRm.c \ + bs3-cmn-TrapSetJmpAndRestoreWithExtCtx.c \ + bs3-cmn-TrapSetJmpAndRestoreWithExtCtxAndRm.c \ + bs3-cmn-TrapUnsetJmp.c \ + bs3-cmn-UtilSetFullGdtr.asm \ + bs3-cmn-UtilSetFullIdtr.asm \ + bs3-cmn-TestDoModesByOneHlp.asm \ + ../../../Runtime/common/asm/ASMBitFirstClear.asm \ + ../../../Runtime/common/asm/ASMBitFirstSet.asm \ + ../../../Runtime/common/asm/ASMBitNextClear.asm \ + ../../../Runtime/common/asm/ASMBitNextSet.asm \ + ../../../Runtime/common/asm/ASMBitFirstSetU16.asm \ + ../../../Runtime/common/asm/ASMBitFirstSetU32.asm \ + ../../../Runtime/common/asm/ASMBitFirstSetU64.asm \ + ../../../Runtime/common/asm/ASMBitLastSetU16.asm \ + ../../../Runtime/common/asm/ASMBitLastSetU32.asm \ + ../../../Runtime/common/asm/ASMBitLastSetU64.asm \ + ../../../Runtime/common/asm/ASMMemFirstMismatchingU8.asm \ + ../../../Runtime/common/asm/ASMSerializeInstruction-cpuid.asm \ + ../../../Runtime/common/asm/ASMSerializeInstruction-iret.asm \ + ../../../Runtime/common/asm/ASMSerializeInstruction-rdtscp.asm \ + ../../../Runtime/common/asm/ASMCpuIdExSlow.asm \ + ../../../Runtime/common/asm/ASMCpuId.asm \ + ../../../Runtime/common/asm/ASMCpuId_Idx_ECX.asm \ + ../../../Runtime/common/asm/ASMWrMsr.asm \ + ../../../Runtime/common/asm/ASMGetXcr0.asm \ + ../../../Runtime/common/asm/ASMSetXcr0.asm \ + ../../../Runtime/common/asm/ASMSetFlags.asm \ + ../../../Runtime/common/asm/ASMGetFlags.asm \ + ../../../Runtime/common/asm/ASMMultU64ByU32DivByU32.asm + +# The 16-bit BS3Kit library. +LIBRARIES += bs3kit-common-16 +bs3kit-common-16_TEMPLATE = VBoxBS3KitImg +bs3kit-common-16_INSTTYPE = none +bs3kit-common-16_DEFS = TMPL_PE16 BS3_CMN_ONLY +bs3kit-common-16_ASDEFS = RT_ASMDEFS_INC_FIRST_FILE +bs3kit-common-16_SOURCES = $(VBOX_BS3KIT_COMMON_SOURCES) \ + bs3-system-data.asm \ + bs3-rm-InitAll.c \ + bs3-rm-InitMemory.c \ + bs3-rm-InitGdt.c \ + bs3-cmn-hexdigits.c \ + bs3-cmn-CpuDetectData.c \ + bs3-cmn-PerCpuData.c \ + bs3-cmn-ConvertRMStackToP16UsingCxReturnToAx.asm \ + bs3-cmn-UInt64Div.c \ + bs3-cmn-UInt32Div.c \ + bs3-wc16-U8DR.asm \ + bs3-wc16-U8DQ.asm \ + bs3-wc16-I8DR.asm \ + bs3-wc16-I8DQ.asm \ + bs3-wc16-I8RS.asm \ + bs3-wc16-U8RS.asm \ + bs3-wc16-U8LS.asm \ + bs3-wc16-U4D.asm \ + bs3-wc16-I4D.asm \ + bs3-c16-SwitchFromV86To16BitAndCallC.asm \ + bs3-c16-Trap16Generic.asm \ + bs3-c16-TrapRmV86Generic.asm \ + bs3-c16-TrapRmV86Data.c \ + bs3-c16-CreateHybridFarRet.asm +bs3kit-common-16_bs3-cmn-UInt64Div.c_CFLAGS = -oh -d0 # -d1+ vs -d0 saves 0x6a3-0x577 = 0x12C (300)! + +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,ASMMemFirstMismatchingU8,8) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,ASMMemFirstNonZero,6) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,ASMCpuIdExSlow,32) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,ASMCpuId,20) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,ASMWrMsr,12) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,ASMSetXcr0,8) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,ASMGetXcr0,0) +-include $(PATH_SUB_CURRENT)/bs3kit-autostubs.kmk # manually generated from headers, see bottom of this file. + +# The 32-bit BS3Kit library. +LIBRARIES += bs3kit-common-32 +bs3kit-common-32_TEMPLATE = VBoxBS3KitImg32 +bs3kit-common-32_INSTTYPE = none +bs3kit-common-32_DEFS = TMPL_PE32 BS3_CMN_ONLY +bs3kit-common-32_ASDEFS = RT_ASMDEFS_INC_FIRST_FILE +bs3kit-common-32_SOURCES = $(VBOX_BS3KIT_COMMON_SOURCES) \ + bs3-cmn-PagingMapRamAbove4GForLM.c \ + bs3-cmn-SwitchHlpConvFlatRetToRetfProtMode.asm \ + bs3-cmn-UInt64Div.c \ + bs3-wc32-U8D.asm \ + bs3-wc32-I8D.asm \ + bs3-wc32-I8RS.asm \ + bs3-wc32-U8RS.asm \ + bs3-wc32-U8LS.asm \ + bs3-wc32-U8M.asm \ + bs3-c32-Trap32Generic.asm + +# The 64-bit BS3Kit library. +LIBRARIES += bs3kit-common-64 +bs3kit-common-64_TEMPLATE = VBoxBS3KitImg64 +bs3kit-common-64_INSTTYPE = none +bs3kit-common-64_DEFS = TMPL_LM64 BS3_CMN_ONLY +bs3kit-common-64_ASDEFS = RT_ASMDEFS_INC_FIRST_FILE +bs3kit-common-64_SOURCES = $(VBOX_BS3KIT_COMMON_SOURCES) \ + bs3-cmn-PagingMapRamAbove4GForLM.c \ + bs3-cmn-SwitchHlpConvFlatRetToRetfProtMode.asm \ + bs3-c64-Trap64Generic.asm \ + ../../../Runtime/common/asm/ASMGetIDTR.asm \ + ../../../Runtime/common/asm/ASMSetIDTR.asm \ + ../../../Runtime/common/asm/ASMGetGDTR.asm \ + ../../../Runtime/common/asm/ASMSetGDTR.asm + + +# +# Common sources to be compiled for each CPU mode. +# +VBOX_BS3KIT_MODE_SOURCES = \ + bs3-mode-Name.asm \ + bs3-mode-NameShortLower.asm \ + bs3-mode-SwitchToRM.asm \ + bs3-mode-SwitchToPE16.asm \ + bs3-mode-SwitchToPE16_32.asm \ + bs3-mode-SwitchToPE16_V86.asm \ + bs3-mode-SwitchToPE32.asm \ + bs3-mode-SwitchToPE32_16.asm \ + bs3-mode-SwitchToPEV86.asm \ + bs3-mode-SwitchToPP16.asm \ + bs3-mode-SwitchToPP16_32.asm \ + bs3-mode-SwitchToPP16_V86.asm \ + bs3-mode-SwitchToPP32.asm \ + bs3-mode-SwitchToPP32_16.asm \ + bs3-mode-SwitchToPPV86.asm \ + bs3-mode-SwitchToPAE16.asm \ + bs3-mode-SwitchToPAE16_32.asm \ + bs3-mode-SwitchToPAE16_V86.asm \ + bs3-mode-SwitchToPAE32.asm \ + bs3-mode-SwitchToPAE32_16.asm \ + bs3-mode-SwitchToPAEV86.asm \ + bs3-mode-SwitchToLM64.asm \ + bs3-mode-SwitchToLM32.asm \ + bs3-mode-SwitchToLM16.asm \ + bs3-mode-SwitchTo32BitAndCallC.asm \ + bs3-mode-EnteredMode.asm \ + bs3-mode-PagingGetRootForPP16.asm \ + bs3-mode-PagingGetRootForPP32.asm \ + bs3-mode-PagingGetRootForPAE16.asm \ + bs3-mode-PagingGetRootForPAE32.asm \ + bs3-mode-PagingGetRootForLM64.asm \ + bs3-mode-TrapInit.c \ + bs3-mode-TrapSystemCallHandler.asm \ + bs3-mode-TrapSetJmpAndRestoreInRmAsm.asm \ + bs3-mode-TestDoModes.c \ + bs3-mode-TestDoModesByOne.c \ + bs3-mode-TestDoModesByMax.c \ + bs3-mode-TestDoModesHlp.asm \ + bs3-mode-BiosInt15hE820.asm + +# The 16-bit real mode BS3Kit library. +LIBRARIES += bs3kit-rm +bs3kit-rm_TEMPLATE = VBoxBS3KitImg +bs3kit-rm_INSTTYPE = none +bs3kit-rm_DEFS = TMPL_MODE=BS3_MODE_RM +bs3kit-rm_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) \ + bs3-first-rm.asm \ + bs3-mode-CpuDetect.asm \ + bs3-mode-TestDoModesStub.asm \ + bs3-mode-TestDoModesByOneStub.asm \ + bs3-mode-TestDoModesByMaxStub.asm + + +# The 16-bit BS3Kit library for 16-bit protected kernel+tss. +LIBRARIES += bs3kit-pe16 +bs3kit-pe16_TEMPLATE = VBoxBS3KitImg +bs3kit-pe16_INSTTYPE = none +bs3kit-pe16_DEFS = TMPL_MODE=BS3_MODE_PE16 +bs3kit-pe16_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) \ + bs3-first-pe16.asm \ + bs3-mode-TestDoModesStub.asm \ + bs3-mode-TestDoModesByOneStub.asm \ + bs3-mode-TestDoModesByMaxStub.asm +# bs3-mode-CpuDetect.asm + +# The 32-bit BS3Kit library for 16-bit protected kernel+tss. +LIBRARIES += bs3kit-pe16_32 +bs3kit-pe16_32_TEMPLATE = VBoxBS3KitImg32 +bs3kit-pe16_32_INSTTYPE = none +bs3kit-pe16_32_DEFS = TMPL_MODE=BS3_MODE_PE16_32 +bs3kit-pe16_32_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) \ + bs3-mode-TestDoModesStub.asm \ + bs3-mode-TestDoModesByOneStub.asm \ + bs3-mode-TestDoModesByMaxStub.asm + +# The v86 BS3Kit library for 16-bit protected kernel+tss. +LIBRARIES += bs3kit-pe16_v86 +bs3kit-pe16_v86_TEMPLATE = VBoxBS3KitImg +bs3kit-pe16_v86_INSTTYPE = none +bs3kit-pe16_v86_DEFS = TMPL_MODE=BS3_MODE_PE16_V86 +bs3kit-pe16_v86_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) \ + bs3-mode-TestDoModesStub.asm \ + bs3-mode-TestDoModesByOneStub.asm \ + bs3-mode-TestDoModesByMaxStub.asm + +# The 32-bit BS3Kit library for 32-bit protected kernel+tss. +LIBRARIES += bs3kit-pe32 +bs3kit-pe32_TEMPLATE = VBoxBS3KitImg32 +bs3kit-pe32_INSTTYPE = none +bs3kit-pe32_DEFS = TMPL_MODE=BS3_MODE_PE32 +bs3kit-pe32_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) \ + bs3-first-init-all-pe32.asm + +# The 16-bit BS3Kit library for 32-bit protected kernel+tss. +LIBRARIES += bs3kit-pe32_16 +bs3kit-pe32_16_TEMPLATE = VBoxBS3KitImg +bs3kit-pe32_16_INSTTYPE = none +bs3kit-pe32_16_DEFS = TMPL_MODE=BS3_MODE_PE32_16 +bs3kit-pe32_16_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) \ + bs3-mode-TestDoModesStub.asm \ + bs3-mode-TestDoModesByOneStub.asm \ + bs3-mode-TestDoModesByMaxStub.asm + +# The v8086 BS3Kit library for 32-bit protected kernel+tss. +LIBRARIES += bs3kit-pev86 +bs3kit-pev86_TEMPLATE = VBoxBS3KitImg +bs3kit-pev86_INSTTYPE = none +bs3kit-pev86_DEFS = TMPL_MODE=BS3_MODE_PEV86 +bs3kit-pev86_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) + +# The 16-bit BS3Kit library for 16-bit paged protected kernel+tss. +LIBRARIES += bs3kit-pp16 +bs3kit-pp16_TEMPLATE = VBoxBS3KitImg +bs3kit-pp16_INSTTYPE = none +bs3kit-pp16_DEFS = TMPL_MODE=BS3_MODE_PP16 +bs3kit-pp16_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) \ + bs3-mode-CpuDetect.asm \ + bs3-mode-TestDoModesStub.asm \ + bs3-mode-TestDoModesByOneStub.asm \ + bs3-mode-TestDoModesByMaxStub.asm + +# The 32-bit BS3Kit library for 16-bit paged protected kernel+tss. +LIBRARIES += bs3kit-pp16_32 +bs3kit-pp16_32_TEMPLATE = VBoxBS3KitImg32 +bs3kit-pp16_32_INSTTYPE = none +bs3kit-pp16_32_DEFS = TMPL_MODE=BS3_MODE_PP16_32 +bs3kit-pp16_32_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) + +# The v8086 BS3Kit library for 16-bit paged protected kernel+tss. +LIBRARIES += bs3kit-pp16_v86 +bs3kit-pp16_v86_TEMPLATE = VBoxBS3KitImg +bs3kit-pp16_v86_INSTTYPE = none +bs3kit-pp16_v86_DEFS = TMPL_MODE=BS3_MODE_PP16_V86 +bs3kit-pp16_v86_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) + +# The 32-bit BS3Kit library for 32-bit paged protected kernel+tss. +LIBRARIES += bs3kit-pp32 +bs3kit-pp32_TEMPLATE = VBoxBS3KitImg32 +bs3kit-pp32_INSTTYPE = none +bs3kit-pp32_DEFS = TMPL_MODE=BS3_MODE_PP32 +bs3kit-pp32_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) \ + bs3-first-init-all-pp32.asm + +# The 16-bit BS3Kit library for 32-bit paged protected kernel+tss. +LIBRARIES += bs3kit-pp32_16 +bs3kit-pp32_16_TEMPLATE = VBoxBS3KitImg +bs3kit-pp32_16_INSTTYPE = none +bs3kit-pp32_16_DEFS = TMPL_MODE=BS3_MODE_PP32_16 +bs3kit-pp32_16_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) \ + bs3-mode-TestDoModesStub.asm \ + bs3-mode-TestDoModesByOneStub.asm \ + bs3-mode-TestDoModesByMaxStub.asm + +# The v8086 BS3Kit library for 32-bit paged protected kernel+tss. +LIBRARIES += bs3kit-ppv86 +bs3kit-ppv86_TEMPLATE = VBoxBS3KitImg +bs3kit-ppv86_INSTTYPE = none +bs3kit-ppv86_DEFS = TMPL_MODE=BS3_MODE_PPV86 +bs3kit-ppv86_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) + + +# The 16-bit BS3Kit library for 16-bit PAE paged protected kernel+tss. +LIBRARIES += bs3kit-pae16 +bs3kit-pae16_TEMPLATE = VBoxBS3KitImg +bs3kit-pae16_INSTTYPE = none +bs3kit-pae16_DEFS = TMPL_MODE=BS3_MODE_PAE16 +bs3kit-pae16_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) \ + bs3-mode-CpuDetect.asm \ + bs3-mode-TestDoModesStub.asm \ + bs3-mode-TestDoModesByOneStub.asm \ + bs3-mode-TestDoModesByMaxStub.asm + +# The 16-bit BS3Kit library for 16-bit PAE paged protected kernel+tss. +LIBRARIES += bs3kit-pae16_32 +bs3kit-pae16_32_TEMPLATE = VBoxBS3KitImg32 +bs3kit-pae16_32_INSTTYPE = none +bs3kit-pae16_32_DEFS = TMPL_MODE=BS3_MODE_PAE16_32 +bs3kit-pae16_32_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) + +# The v8086 BS3Kit library for 16-bit PAE paged protected kernel+tss. +LIBRARIES += bs3kit-pae16_v86 +bs3kit-pae16_v86_TEMPLATE = VBoxBS3KitImg +bs3kit-pae16_v86_INSTTYPE = none +bs3kit-pae16_v86_DEFS = TMPL_MODE=BS3_MODE_PAE16_V86 +bs3kit-pae16_v86_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) + +# The 32-bit BS3Kit library for 32-bit PAE paged protected kernel+tss. +LIBRARIES += bs3kit-pae32 +bs3kit-pae32_TEMPLATE = VBoxBS3KitImg32 +bs3kit-pae32_INSTTYPE = none +bs3kit-pae32_DEFS = TMPL_MODE=BS3_MODE_PAE32 +bs3kit-pae32_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) + +# The 16-bit BS3Kit library for 32-bit PAE paged protected kernel+tss. +LIBRARIES += bs3kit-pae32_16 +bs3kit-pae32_16_TEMPLATE = VBoxBS3KitImg +bs3kit-pae32_16_INSTTYPE = none +bs3kit-pae32_16_DEFS = TMPL_MODE=BS3_MODE_PAE32_16 +bs3kit-pae32_16_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) \ + bs3-mode-TestDoModesStub.asm \ + bs3-mode-TestDoModesByOneStub.asm \ + bs3-mode-TestDoModesByMaxStub.asm + +# The v8086 BS3Kit library for 32-bit PAE paged protected kernel+tss. +LIBRARIES += bs3kit-paev86 +bs3kit-paev86_TEMPLATE = VBoxBS3KitImg +bs3kit-paev86_INSTTYPE = none +bs3kit-paev86_DEFS = TMPL_MODE=BS3_MODE_PAEV86 +bs3kit-paev86_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) + + +# The 16-bit long mode BS3Kit library. +LIBRARIES += bs3kit-lm16 +bs3kit-lm16_TEMPLATE = VBoxBS3KitImg +bs3kit-lm16_INSTTYPE = none +bs3kit-lm16_DEFS = TMPL_MODE=BS3_MODE_LM16 +bs3kit-lm16_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) \ + bs3-mode-TestDoModesStub.asm \ + bs3-mode-TestDoModesByOneStub.asm \ + bs3-mode-TestDoModesByMaxStub.asm + +# The 32-bit long mode BS3Kit library. +LIBRARIES += bs3kit-lm32 +bs3kit-lm32_TEMPLATE = VBoxBS3KitImg32 +bs3kit-lm32_INSTTYPE = none +bs3kit-lm32_DEFS = TMPL_MODE=BS3_MODE_LM32 +bs3kit-lm32_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) + +# The 64-bit long mode BS3Kit library. +LIBRARIES += bs3kit-lm64 +bs3kit-lm64_TEMPLATE = VBoxBS3KitImg64 +bs3kit-lm64_INSTTYPE = none +bs3kit-lm64_DEFS = TMPL_MODE=BS3_MODE_LM64 +bs3kit-lm64_SOURCES = $(VBOX_BS3KIT_MODE_SOURCES) \ + bs3-first-init-all-lm64.asm + + +# +# shutdown example. +# +MISCBINS += bs3-shutdown +bs3-shutdown_TEMPLATE = VBoxBS3KitImg +bs3-shutdown_SOURCES = \ + bs3-first-pe16.asm \ + bs3-shutdown.c + + +# +# DOS Utilities / Testcases. +# +MISCBINS += bs3cpudt +bs3cpudt_TEMPLATE = VBoxBS3KitUtil +bs3cpudt_SOURCES = \ + bs3-first-dosexe.asm \ + bs3cpudt.c + + +# +# Rule for regenerating bs3kit-mangling-functions-undef.h. +# +bs3kit-mangling-code-undef.h: $(PATH_SUB_CURRENT)/bs3kit-mangling-code-define.h $(MAKEFILE) + $(SED) \ + -e 's/#\( *\)define \([a-zA-Z_][a-zA-Z0-9_]*\) .*$(DOLLAR)/#\1undef \2/' \ + -e 's/Function needing mangling.*$(DOLLAR)/Undefining function mangling - automatically generated by the $@ makefile rule./' \ + --output $(dir $<)bs3kit-mangling-code-undef.h \ + $< + +# +# Rule for regenerating bs3kit-mangling-functions-define.h. +# +bs3kit-mangling-code-define.h: \ + $(PATH_SUB_CURRENT)/bs3kit.h \ + $(PATH_SUB_CURRENT)/bs3-cmn-paging.h \ + $(PATH_SUB_CURRENT)/bs3-cmn-test.h \ + $(MAKEFILE) + $(APPEND) -tn "$(dir $<)$@" \ + '/* $(DOLLAR)Id: $(DOLLAR) */' \ + '/** @file' \ + ' * BS3Kit - Function needing mangling - generated by the $@ makefile rule.' \ + ' */' \ + '' \ + '/*' \ + ' * Copyright (C) 2007-$(VBOX_C_YEAR) Oracle and/or its affiliates.' \ + ' *' \ + ' * This file is part of VirtualBox base platform packages, as' \ + ' * available from https://www.virtualbox.org.' \ + ' *' \ + ' * This program is free software; you can redistribute it and/or' \ + ' * modify it under the terms of the GNU General Public License' \ + ' * as published by the Free Software Foundation, in version 3 of the' \ + ' * License.' \ + ' *' \ + ' * This program is distributed in the hope that it will be useful, but' \ + ' * WITHOUT ANY WARRANTY; without even the implied warranty of' \ + ' * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU' \ + ' * General Public License for more details.' \ + ' *' \ + ' * You should have received a copy of the GNU General Public License' \ + ' * along with this program; if not, see <https://www.gnu.org/licenses>.' \ + ' *' \ + ' * The contents of this file may alternatively be used under the terms' \ + ' * of the Common Development and Distribution License Version 1.0' \ + ' * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included' \ + ' * in the VirtualBox distribution, in which case the provisions of the' \ + ' * CDDL are applicable instead of those of the GPL.' \ + ' *' \ + ' * You may elect to license modified versions of this file under the' \ + ' * terms and conditions of either the GPL or the CDDL or both.' \ + ' *' \ + ' * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0' \ + ' */' \ + '' + $(SED) -n \ + -e 's/^ *BS3_CMN_PROTO_STUB([^,]*, *\([a-zA-Z_][a-zA-Z0-9_]*\) *,.*$(DOLLAR)/#define \1 BS3_CMN_MANGLER(\1)/p' \ + -e 's/^ *BS3_CMN_PROTO_NOSB([^,]*, *\([a-zA-Z_][a-zA-Z0-9_]*\) *,.*$(DOLLAR)/#define \1 BS3_CMN_MANGLER(\1)/p' \ + -e 's/^ *BS3_CMN_PROTO_FARSTUB([^,]*,[^,]*, *\([a-zA-Z_][a-zA-Z0-9_]*\) *,.*$(DOLLAR)/#define \1 BS3_CMN_MANGLER(\1)/p' \ + $(filter %.h,$^) | sort >> "$(dir $<)bs3kit-mangling-code-define.h" + $(APPEND) -n "$(dir $<)$@" '#ifndef BS3_CMN_ONLY' + $(SED) -n \ + -e 's/^ *BS3_MODE_PROTO_STUB([^,]*, *\([a-zA-Z_][a-zA-Z0-9_]*\) *,.*$(DOLLAR)/# define \1 BS3_MODE_MANGLER(\1)/p' \ + -e 's/^ *BS3_MODE_PROTO_NOSB([^,]*, *\([a-zA-Z_][a-zA-Z0-9_]*\) *,.*$(DOLLAR)/# define \1 BS3_MODE_MANGLER(\1)/p' \ + -e 's/^ *BS3_MODE_PROTO_FARSTUB([^,]*,[^,]*, *\([a-zA-Z_][a-zA-Z0-9_]*\) *,.*$(DOLLAR)/# define \1 BS3_MODE_MANGLER(\1)/p' \ + $(filter %.h,$^) | sort >> "$(dir $<)bs3kit-mangling-code-define.h" + $(APPEND) -n "$(dir $<)$@" '#endif /* !BS3_CMN_ONLY */' + +# +# Rule for regenerating bs3kit-autostubs.kmk. +# +bs3kit-autostubs.kmk: \ + $(PATH_SUB_CURRENT)/bs3kit.h \ + $(PATH_SUB_CURRENT)/bs3-cmn-memory.h \ + $(PATH_SUB_CURRENT)/bs3-cmn-paging.h \ + $(PATH_SUB_CURRENT)/bs3-cmn-test.h \ + $(MAKEFILE) + $(APPEND) -tn "$(dir $<)$@" \ + '# $(DOLLAR)Id: $(DOLLAR)' \ + '## @file' \ + '# BS3Kit - Automatic near/far stubs - generated by the $@ makefile rule.' \ + '#' \ + '' \ + '#' \ + '# Copyright (C) 2007-$(VBOX_C_YEAR) Oracle and/or its affiliates.' \ + '#' \ + '# This file is part of VirtualBox base platform packages, as' \ + '# available from https://www.virtualbox.org.' \ + '#' \ + '# This program is free software; you can redistribute it and/or' \ + '# modify it under the terms of the GNU General Public License' \ + '# as published by the Free Software Foundation, in version 3 of the' \ + '# License.' \ + '#' \ + '# This program is distributed in the hope that it will be useful, but' \ + '# WITHOUT ANY WARRANTY; without even the implied warranty of' \ + '# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU' \ + '# General Public License for more details.' \ + '#' \ + '# You should have received a copy of the GNU General Public License' \ + '# along with this program; if not, see <https://www.gnu.org/licenses>.' \ + '#' \ + '# The contents of this file may alternatively be used under the terms' \ + '# of the Common Development and Distribution License Version 1.0' \ + '# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included' \ + '# in the VirtualBox distribution, in which case the provisions of the' \ + '# CDDL are applicable instead of those of the GPL.' \ + '#' \ + '# You may elect to license modified versions of this file under the' \ + '# terms and conditions of either the GPL or the CDDL or both.' \ + '#' \ + '# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0' \ + '#' \ + '' + $(SED) -n \ + -e '/^ *BS3_CMN_PROTO_STUB/p' \ + -e '/^ *BS3_CMN_PROTO_FARSTUB/p' \ + -e '/^ *BS3_MODE_PROTO_STUB/p' \ + -e '/^ *BS3_MODE_PROTO_FARSTUB/p' \ + $(filter %.h,$^) \ + | sort \ + | $(SED) -n \ + -e 's/^ *BS3_CMN_PROTO_STUB([^,]*, *\([a-zA-Z_][a-zA-Z0-9_]*\) *,.*$(DOLLAR)/\$(DOLLAR)(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,\1)/p' \ + -e 's/^ *BS3_MODE_PROTO_STUB([^,]*, *\([a-zA-Z_][a-zA-Z0-9_]*\) *,.*$(DOLLAR)/\$(DOLLAR)(call BS3KIT_FN_GEN_MODE_NEARSTUB,bs3kit-common-16,\1)/p' \ + -e 's/^ *BS3_CMN_PROTO_FARSTUB( *\([^,]*\),[^,]*, *\([a-zA-Z_][a-zA-Z0-9_]*\) *,.*$(DOLLAR)/\$(DOLLAR)(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,\2,\1)/p' \ + -e 's/^ *BS3_MODE_PROTO_FARSTUB( *\([^,]*\),[^,]*, *\([a-zA-Z_][a-zA-Z0-9_]*\) *,.*$(DOLLAR)/\$(DOLLAR)(call BS3KIT_FN_GEN_MODE_FARSTUB,bs3kit-common-16,\2,\1)/p' \ + --append "$(dir $<)$@" + +bs3kit-update:: bs3kit-autostubs.kmk bs3kit-mangling-code-define.h bs3kit-mangling-code-undef.h +.NOTPARALLEL: bs3kit-autostubs.kmk bs3kit-mangling-code-define.h bs3kit-mangling-code-undef.h + + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/VBoxBs3Linker.cpp b/src/VBox/ValidationKit/bootsectors/bs3kit/VBoxBs3Linker.cpp new file mode 100644 index 00000000..0855c35f --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/VBoxBs3Linker.cpp @@ -0,0 +1,362 @@ +/* $Id: VBoxBs3Linker.cpp $ */ +/** @file + * VirtualBox Validation Kit - Boot Sector 3 "linker". + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <iprt/types.h> +#include <iprt/assert.h> + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +#pragma pack(1) +typedef struct BS3BOOTSECTOR +{ + uint8_t abJmp[3]; + char abOemId[8]; + /** @name EBPB, DOS 4.0 style. + * @{ */ + uint16_t cBytesPerSector; /**< 00bh */ + uint8_t cSectorsPerCluster; /**< 00dh */ + uint16_t cReservedSectors; /**< 00eh */ + uint8_t cFATs; /**< 010h */ + uint16_t cRootDirEntries; /**< 011h */ + uint16_t cTotalSectors; /**< 013h */ + uint8_t bMediaDescriptor; /**< 015h */ + uint16_t cSectorsPerFAT; /**< 016h */ + uint16_t cPhysSectorsPerTrack; /**< 018h */ + uint16_t cHeads; /**< 01ah */ + uint32_t cHiddentSectors; /**< 01ch */ + uint32_t cLargeTotalSectors; /**< 020h - We (ab)use this to indicate the number of sectors to load. */ + uint8_t bBootDrv; /**< 024h */ + uint8_t bFlagsEtc; /**< 025h */ + uint8_t bExtendedSignature; /**< 026h */ + uint32_t dwSerialNumber; /**< 027h */ + char abLabel[11]; /**< 02bh */ + char abFSType[8]; /**< 036h */ + /** @} */ +} BS3BOOTSECTOR; +#pragma pack() +typedef BS3BOOTSECTOR *PBS3BOOTSECTOR; + +AssertCompileMemberOffset(BS3BOOTSECTOR, cLargeTotalSectors, 0x20); +AssertCompileMemberOffset(BS3BOOTSECTOR, abLabel, 0x2b); +AssertCompileMemberOffset(BS3BOOTSECTOR, abFSType, 0x36); + +#define BS3_OEMID "BS3Kit\n\n" +#define BS3_FSTYPE "RawCode\n" +#define BS3_LABEL "VirtualBox\n" +#define BS3_MAX_SIZE UINT32_C(491520) /* 480KB */ + + +int main(int argc, char **argv) +{ + const char *pszOutput = NULL; + struct BS3LNKINPUT + { + const char *pszFile; + FILE *pFile; + uint32_t cbFile; + } *paInputs = (struct BS3LNKINPUT *)calloc(sizeof(paInputs[0]), argc); + unsigned cInputs = 0; + uint32_t cSectors = 0; + + /* + * Scan the arguments. + */ + for (int i = 1; i < argc; i++) + { + if (argv[i][0] == '-') + { + const char *pszOpt = &argv[i][1]; + if (*pszOpt == '-') + { + /* Convert long options to short ones. */ + pszOpt--; + if (!strcmp(pszOpt, "--output")) + pszOpt = "o"; + else if (!strcmp(pszOpt, "--version")) + pszOpt = "V"; + else if (!strcmp(pszOpt, "--help")) + pszOpt = "h"; + else + { + fprintf(stderr, "syntax errro: Unknown options '%s'\n", pszOpt); + free(paInputs); + return 2; + } + } + + /* Process the list of short options. */ + while (*pszOpt) + { + switch (*pszOpt++) + { + case 'o': + { + const char *pszValue = pszOpt; + pszOpt = strchr(pszOpt, '\0'); + if (*pszValue == '=') + pszValue++; + else if (!*pszValue) + { + if (i + 1 >= argc) + { + fprintf(stderr, "syntax error: The --output option expects a filename.\n"); + free(paInputs); + return 12; + } + pszValue = argv[++i]; + } + if (pszOutput) + { + fprintf(stderr, "Only one output file is allowed. You've specified '%s' and '%s'\n", + pszOutput, pszValue); + free(paInputs); + return 2; + } + pszOutput = pszValue; + pszOpt = ""; + break; + } + + case 'V': + printf("%s\n", "$Revision: 155244 $"); + free(paInputs); + return 0; + + case '?': + case 'h': + printf("usage: %s [options] -o <output> <input1> [input2 ... [inputN]]\n", + argv[0]); + free(paInputs); + return 0; + } + } + } + else + { + /* + * Add to input file collection. + */ + paInputs[cInputs].pszFile = argv[i]; +#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) + FILE *pFile = fopen(paInputs[cInputs].pszFile, "rb"); +#else + FILE *pFile = fopen(paInputs[cInputs].pszFile, "r"); +#endif + if (pFile) + { + if (fseek(pFile, 0, SEEK_END) == 0) + { + paInputs[cInputs].cbFile = (uint32_t)ftell(pFile); + if (fseek(pFile, 0, SEEK_SET) == 0) + { + if (cInputs != 0 || paInputs[cInputs].cbFile == 512) + { + cSectors += RT_ALIGN_32(paInputs[cInputs].cbFile, 512) / 512; + if (cSectors <= BS3_MAX_SIZE / 512) + { + if (cSectors > 0) + { + paInputs[cInputs].pFile = pFile; + pFile = NULL; + } + else + fprintf(stderr, "error: empty input file: '%s'\n", paInputs[cInputs].pszFile); + } + else + fprintf(stderr, "error: input is too big: %u bytes, %u sectors (max %u bytes, %u sectors)\n" + "info: detected loading '%s'\n", + cSectors * 512, cSectors, BS3_MAX_SIZE, BS3_MAX_SIZE / 512, + paInputs[cInputs].pszFile); + } + else + fprintf(stderr, "error: first input file (%s) must be exactly 512 bytes\n", paInputs[cInputs].pszFile); + } + else + fprintf(stderr, "error: seeking to start of '%s' failed\n", paInputs[cInputs].pszFile); + } + else + fprintf(stderr, "error: seeking to end of '%s' failed\n", paInputs[cInputs].pszFile); + } + else + fprintf(stderr, "error: Failed to open input file '%s' for reading\n", paInputs[cInputs].pszFile); + if (pFile) + { + free(paInputs); + return 1; + } + cInputs++; + } + } + + if (!pszOutput) + { + fprintf(stderr, "syntax error: No output file was specified (-o or --output).\n"); + free(paInputs); + return 2; + } + if (cInputs == 0) + { + fprintf(stderr, "syntax error: No input files was specified.\n"); + free(paInputs); + return 2; + } + + /* + * Do the job. + */ + /* Open the output file. */ +#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) + FILE *pOutput = fopen(pszOutput, "wb"); +#else + FILE *pOutput = fopen(pszOutput, "w"); +#endif + if (!pOutput) + { + fprintf(stderr, "error: Failed to open output file '%s' for writing\n", pszOutput); + free(paInputs); + return 1; + } + + /* Copy the input files to the output file, with sector padding applied. */ + int rcExit = 0; + size_t off = 0; + for (unsigned i = 0; i < cInputs && rcExit == 0; i++) + { + uint8_t abBuf[4096]; /* Must be multiple of 512! */ + uint32_t cbToRead = paInputs[i].cbFile; + while (cbToRead > 0) + { + /* Read a block from the input file. */ + uint32_t const cbThisRead = RT_MIN(cbToRead, sizeof(abBuf)); + size_t cbRead = fread(abBuf, sizeof(uint8_t), cbThisRead, paInputs[i].pFile); + if (cbRead != cbThisRead) + { + fprintf(stderr, "error: Error reading '%s' (got %d bytes, wanted %u).\n", + paInputs[i].pszFile, (int)cbRead, (unsigned)cbThisRead); + rcExit = 1; + break; + } + cbToRead -= cbThisRead; + + /* Padd the end of the file if necessary. */ + if ((cbRead & 0x1ff) != 0) + { + memset(&abBuf[cbRead], 0, 4096 - cbRead); + cbRead = (cbRead + 0x1ff) & ~0x1ffU; + } + + /* Patch the BPB of the first file. */ + if (off == 0) + { + PBS3BOOTSECTOR pBs = (PBS3BOOTSECTOR)&abBuf[0]; + if ( memcmp(pBs->abLabel, RT_STR_TUPLE(BS3_LABEL)) == 0 + && memcmp(pBs->abFSType, RT_STR_TUPLE(BS3_FSTYPE)) == 0 + && memcmp(pBs->abOemId, RT_STR_TUPLE(BS3_OEMID)) == 0) + pBs->cLargeTotalSectors = cSectors; + else + { + fprintf(stderr, "error: Didn't find magic strings in the first file (%s).\n", paInputs[i].pszFile); + rcExit = 1; + } + } + + /* Write the block to the output file. */ + if (fwrite(abBuf, sizeof(uint8_t), cbRead, pOutput) == cbRead) + off += cbRead; + else + { + fprintf(stderr, "error: fwrite failed\n"); + rcExit = 1; + break; + } + } + + if (ferror(paInputs[i].pFile)) + { + fprintf(stderr, "error: Error reading '%s'.\n", paInputs[i].pszFile); + rcExit = 1; + } + } + + /* Close the input files. */ + for (unsigned i = 0; i < cInputs && rcExit == 0; i++) + fclose(paInputs[i].pFile); + free(paInputs); + + /* Avoid output sizes that makes the FDC code think it's a single sided + floppy. The BIOS always report double sided floppies, and even if we + the bootsector adjust it's bMaxHeads value when getting a 20h error + we end up with a garbaged image (seems somewhere in the BIOS/FDC it is + still treated as a double sided floppy and we get half the data we want + and with gaps). + + Similarly, if the size is 320KB or 360KB the FDC detects it as a double + sided 5.25" floppy with 40 tracks, while the BIOS keeps reporting a + 1.44MB 3.5" floppy. So, just avoid those sizes too. */ + uint32_t cbOutput = ftell(pOutput); + if ( cbOutput == 512 * 8 * 40 * 1 /* 160kB 5"1/4 SS */ + || cbOutput == 512 * 9 * 40 * 1 /* 180kB 5"1/4 SS */ + || cbOutput == 512 * 8 * 40 * 2 /* 320kB 5"1/4 DS */ + || cbOutput == 512 * 9 * 40 * 2 /* 360kB 5"1/4 DS */ ) + { + static uint8_t const s_abZeroSector[512] = { 0 }; + if (fwrite(s_abZeroSector, sizeof(uint8_t), sizeof(s_abZeroSector), pOutput) != sizeof(s_abZeroSector)) + { + fprintf(stderr, "error: fwrite failed (padding)\n"); + rcExit = 1; + } + } + + /* Finally, close the output file (can fail because of buffered data). */ + if (fclose(pOutput) != 0) + { + fprintf(stderr, "error: Error closing '%s'.\n", pszOutput); + rcExit = 1; + } + + fclose(stderr); + return rcExit; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/VBoxBs3ObjConverter.cpp b/src/VBox/ValidationKit/bootsectors/bs3kit/VBoxBs3ObjConverter.cpp new file mode 100644 index 00000000..ce789b21 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/VBoxBs3ObjConverter.cpp @@ -0,0 +1,5530 @@ +/* $Id: VBoxBs3ObjConverter.cpp $ */ +/** @file + * VirtualBox Validation Kit - Boot Sector 3 object file convert. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <iprt/types.h> +#include <iprt/ctype.h> +#include <iprt/assert.h> +#include <iprt/sort.h> +#include <iprt/x86.h> + +#include <iprt/formats/elf64.h> +#include <iprt/formats/elf-amd64.h> +#include <iprt/formats/pecoff.h> +#include <iprt/formats/omf.h> +#include <iprt/formats/codeview.h> + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +#if ARCH_BITS == 64 && !defined(RT_OS_WINDOWS) && !defined(RT_OS_DARWIN) +# define ELF_FMT_X64 "lx" +# define ELF_FMT_D64 "ld" +#else +# define ELF_FMT_X64 "llx" +# define ELF_FMT_D64 "lld" +#endif + +/** Compares an OMF string with a constant string. */ +#define IS_OMF_STR_EQUAL_EX(a_cch1, a_pch1, a_szConst2) \ + ( (a_cch1) == sizeof(a_szConst2) - 1 && memcmp(a_pch1, a_szConst2, sizeof(a_szConst2) - 1) == 0 ) + +/** Compares an OMF string with a constant string. */ +#define IS_OMF_STR_EQUAL(a_pchZeroPrefixed, a_szConst2) \ + IS_OMF_STR_EQUAL_EX((uint8_t)((a_pchZeroPrefixed)[0]), &((a_pchZeroPrefixed)[1]), a_szConst2) + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +/** Verbosity level. */ +static unsigned g_cVerbose = 0; +/** Indicates that it's output from the 16-bit watcom C or C++ compiler. + * We will do some massaging for fixup records when this is used. */ +static bool g_f16BitWatcomC = false; + + +/* + * Minimal assertion support. + */ + +RTDECL(bool) RTAssertShouldPanic(void) +{ + return true; +} + + +RTDECL(void) RTAssertMsg1Weak(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction) +{ + fprintf(stderr, + "VBoxBs3ObjConverter: assertion failed in %s (%s:%u)!\n" + "VBoxBs3ObjConverter: %s\n", + pszFunction, pszFile, uLine, pszExpr); +} + + +/** + * Opens a file for binary reading or writing. + * + * @returns File stream handle. + * @param pszFile The name of the file. + * @param fWrite Whether to open for writing or reading. + */ +static FILE *openfile(const char *pszFile, bool fWrite) +{ +#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) + FILE *pFile = fopen(pszFile, fWrite ? "wb" : "rb"); +#else + FILE *pFile = fopen(pszFile, fWrite ? "w" : "r"); +#endif + if (!pFile) + fprintf(stderr, "error: Failed to open '%s' for %s: %s (%d)\n", + pszFile, fWrite ? "writing" : "reading", strerror(errno), errno); + return pFile; +} + + +/** + * Read the given file into memory. + * + * @returns true on success, false on failure. + * @param pszFile The file to read. + * @param ppvFile Where to return the memory. + * @param pcbFile Where to return the size. + */ +static bool readfile(const char *pszFile, void **ppvFile, size_t *pcbFile) +{ + FILE *pFile = openfile(pszFile, false); + if (pFile) + { + /* + * Figure the size. + */ + if (fseek(pFile, 0, SEEK_END) == 0) + { + long cbFile = ftell(pFile); + if (cbFile > 0) + { + if (fseek(pFile, SEEK_SET, 0) == 0) + { + /* + * Allocate and read content. + */ + void *pvFile = malloc((size_t)cbFile); + if (pvFile) + { + if (fread(pvFile, cbFile, 1, pFile) == 1) + { + *ppvFile = pvFile; + *pcbFile = (size_t)cbFile; + fclose(pFile); + return true; + } + free(pvFile); + fprintf(stderr, "error: fread failed in '%s': %s (%d)\n", pszFile, strerror(errno), errno); + } + else + fprintf(stderr, "error: failed to allocate %ld bytes of memory for '%s'\n", cbFile, pszFile); + } + else + fprintf(stderr, "error: fseek #2 failed in '%s': %s (%d)\n", pszFile, strerror(errno), errno); + } + else + fprintf(stderr, "error: ftell failed in '%s': %s (%d)\n", pszFile, strerror(errno), errno); + } + else + fprintf(stderr, "error: fseek #1 failed in '%s': %s (%d)\n", pszFile, strerror(errno), errno); + fclose(pFile); + } + return false; +} + + +/** + * Write the given file into memory. + * + * @returns true on success, false on failure. + * @param pszFile The file to write. + * @param pvFile Where to return the memory. + * @param cbFile Where to return the size. + */ +static bool writefile(const char *pszFile, void const *pvFile, size_t cbFile) +{ + remove(pszFile); + + FILE *pFile = openfile(pszFile, true); + if (pFile) + { + if (fwrite(pvFile, cbFile, 1, pFile) == 1) + { + fclose(pFile); + return true; + } + fprintf(stderr, "error: fwrite failed in '%s': %s (%d)\n", pszFile, strerror(errno), errno); + fclose(pFile); + } + return false; +} + + +/** + * Reports an error and returns false. + * + * @returns false + * @param pszFile The filename. + * @param pszFormat The message format string. + * @param ... Format arguments. + */ +static bool error(const char *pszFile, const char *pszFormat, ...) +{ + fflush(stdout); + fprintf(stderr, "error: %s: ", pszFile); + va_list va; + va_start(va, pszFormat); + vfprintf(stderr, pszFormat, va); + va_end(va); + return false; +} + + + +/********************************************************************************************************************************* +* Common OMF Writer * +*********************************************************************************************************************************/ + +/** Entry for each segment/section in the source format for mapping it to a + * segment defintion. */ +typedef struct OMFTOSEGDEF +{ + /** The segment defintion index of the section, UINT16_MAX if not translated. */ + uint16_t iSegDef; + /** The group index for this segment, UINT16_MAX if not applicable. */ + uint16_t iGrpDef; + /** The class name table entry, UINT16_MAX if not applicable. */ + uint16_t iClassNm; + /** The group name for this segment, UINT16_MAX if not applicable. */ + uint16_t iGrpNm; + /** The group name for this segment, UINT16_MAX if not applicable. */ + uint16_t iSegNm; + /** The number of public definitions for this segment. */ + uint32_t cPubDefs; + /** The segment name (OMF). */ + char *pszName; +} OMFTOSEGDEF; +/** Pointer to a segment/section to segdef mapping. */ +typedef OMFTOSEGDEF *POMFTOSEGDEF; + +/** Symbol table translation type. */ +typedef enum OMFSYMTYPE +{ + /** Invalid symbol table entry (aux sym). */ + OMFSYMTYPE_INVALID = 0, + /** Ignored. */ + OMFSYMTYPE_IGNORED, + /** A public defintion. */ + OMFSYMTYPE_PUBDEF, + /** An external definition. */ + OMFSYMTYPE_EXTDEF, + /** A segment reference for fixups. */ + OMFSYMTYPE_SEGDEF, + /** Internal symbol that may be used for fixups. */ + OMFSYMTYPE_INTERNAL +} OMFSYMTYPE; + +/** Symbol table translation. */ +typedef struct OMFSYMBOL +{ + /** What this source symbol table entry should be translated into. */ + OMFSYMTYPE enmType; + /** The OMF table index. UINT16_MAX if not applicable. */ + uint16_t idx; + /** The OMF segment definition index. */ + uint16_t idxSegDef; + /** The OMF group definition index. */ + uint16_t idxGrpDef; +} OMFSYMBOL; +/** Pointer to an source symbol table translation entry. */ +typedef OMFSYMBOL *POMFSYMBOL; + +/** OMF Writer LNAME lookup record. */ +typedef struct OMFWRLNAME +{ + /** Pointer to the next entry with the name hash. */ + struct OMFWRLNAME *pNext; + /** The LNAMES index number. */ + uint16_t idxName; + /** The name length. */ + uint8_t cchName; + /** The name (variable size). */ + char szName[1]; +} OMFWRLNAME; +/** Pointer to the a OMF writer LNAME lookup record. */ +typedef OMFWRLNAME *POMFWRLNAME; + +/** + * OMF converter & writer instance. + */ +typedef struct OMFWRITER +{ + /** The source file name (for bitching). */ + const char *pszSrc; + /** The destination output file. */ + FILE *pDst; + + /** Pointer to the table mapping from source segments/section to segdefs. */ + POMFTOSEGDEF paSegments; + /** Number of source segments/sections. */ + uint32_t cSegments; + + /** Number of entries in the source symbol table. */ + uint32_t cSymbols; + /** Pointer to the table mapping from source symbols to OMF stuff. */ + POMFSYMBOL paSymbols; + + /** LEDATA segment offset. */ + uint32_t offSeg; + /** Start of the current LEDATA record. */ + uint32_t offSegRec; + /** The LEDATA end segment offset. */ + uint32_t offSegEnd; + /** The current LEDATA segment. */ + uint16_t idx; + + /** The index of the next list of names entry. */ + uint16_t idxNextName; + + /** The current record size. */ + uint16_t cbRec; + /** The current record type */ + uint8_t bType; + /** The record data buffer (too large, but whatever). */ + uint8_t abData[_1K + 64]; + + /** Current FIXUPP entry. */ + uint8_t iFixupp; + /** FIXUPP records being prepared for LEDATA currently stashed in abData. + * We may have to adjust addend values in the LEDATA when converting to OMF + * fixups. */ + struct + { + uint16_t cbRec; + uint8_t abData[_1K + 64]; + uint8_t abAlign[2]; /**< Alignment padding. */ + } aFixupps[3]; + + /** The index of the FLAT group. */ + uint16_t idxGrpFlat; + /** The EXTDEF index of the __ImageBase symbol. */ + uint16_t idxExtImageBase; + + /** LNAME lookup hash table. To avoid too many duplicates. */ + POMFWRLNAME apNameLookup[63]; +} OMFWRITE; +/** Pointer to an OMF writer. */ +typedef OMFWRITE *POMFWRITER; + + +/** + * Creates an OMF writer instance. + */ +static POMFWRITER omfWriter_Create(const char *pszSrc, uint32_t cSegments, uint32_t cSymbols, FILE *pDst) +{ + POMFWRITER pThis = (POMFWRITER)calloc(sizeof(OMFWRITER), 1); + if (pThis) + { + pThis->pszSrc = pszSrc; + pThis->idxNextName = 1; /* We start counting at 1. */ + pThis->cSegments = cSegments; + pThis->paSegments = (POMFTOSEGDEF)calloc(sizeof(OMFTOSEGDEF), cSegments); + if (pThis->paSegments) + { + pThis->cSymbols = cSymbols; + pThis->paSymbols = (POMFSYMBOL)calloc(sizeof(OMFSYMBOL), cSymbols); + if (pThis->paSymbols) + { + pThis->pDst = pDst; + return pThis; + } + free(pThis->paSegments); + } + free(pThis); + } + error(pszSrc, "Out of memory!\n"); + return NULL; +} + +/** + * Destroys the given OMF writer instance. + * @param pThis OMF writer instance. + */ +static void omfWriter_Destroy(POMFWRITER pThis) +{ + free(pThis->paSymbols); + + for (uint32_t i = 0; i < pThis->cSegments; i++) + if (pThis->paSegments[i].pszName) + free(pThis->paSegments[i].pszName); + + free(pThis->paSegments); + + uint32_t i = RT_ELEMENTS(pThis->apNameLookup); + while (i-- > 0) + { + POMFWRLNAME pNext = pThis->apNameLookup[i]; + pThis->apNameLookup[i] = NULL; + while (pNext) + { + POMFWRLNAME pFree = pNext; + pNext = pNext->pNext; + free(pFree); + } + } + + free(pThis); +} + +static bool omfWriter_RecBegin(POMFWRITER pThis, uint8_t bType) +{ + pThis->bType = bType; + pThis->cbRec = 0; + return true; +} + +static bool omfWriter_RecAddU8(POMFWRITER pThis, uint8_t b) +{ + if (pThis->cbRec < OMF_MAX_RECORD_PAYLOAD) + { + pThis->abData[pThis->cbRec++] = b; + return true; + } + return error(pThis->pszSrc, "Exceeded max OMF record length (bType=%#x)!\n", pThis->bType); +} + +static bool omfWriter_RecAddU16(POMFWRITER pThis, uint16_t u16) +{ + if (pThis->cbRec + 2U <= OMF_MAX_RECORD_PAYLOAD) + { + pThis->abData[pThis->cbRec++] = (uint8_t)u16; + pThis->abData[pThis->cbRec++] = (uint8_t)(u16 >> 8); + return true; + } + return error(pThis->pszSrc, "Exceeded max OMF record length (bType=%#x)!\n", pThis->bType); +} + +static bool omfWriter_RecAddU32(POMFWRITER pThis, uint32_t u32) +{ + if (pThis->cbRec + 4U <= OMF_MAX_RECORD_PAYLOAD) + { + pThis->abData[pThis->cbRec++] = (uint8_t)u32; + pThis->abData[pThis->cbRec++] = (uint8_t)(u32 >> 8); + pThis->abData[pThis->cbRec++] = (uint8_t)(u32 >> 16); + pThis->abData[pThis->cbRec++] = (uint8_t)(u32 >> 24); + return true; + } + return error(pThis->pszSrc, "Exceeded max OMF record length (bType=%#x)!\n", pThis->bType); +} + +static bool omfWriter_RecAddIdx(POMFWRITER pThis, uint16_t idx) +{ + if (idx < 128) + return omfWriter_RecAddU8(pThis, (uint8_t)idx); + if (idx < _32K) + return omfWriter_RecAddU8(pThis, (uint8_t)(idx >> 8) | 0x80) + && omfWriter_RecAddU8(pThis, (uint8_t)idx); + return error(pThis->pszSrc, "Index out of range %#x\n", idx); +} + +static bool omfWriter_RecAddBytes(POMFWRITER pThis, const void *pvData, size_t cbData) +{ + const uint16_t cbNasmHack = OMF_MAX_RECORD_PAYLOAD + 1; + if (cbData + pThis->cbRec <= cbNasmHack) + { + memcpy(&pThis->abData[pThis->cbRec], pvData, cbData); + pThis->cbRec += (uint16_t)cbData; + return true; + } + return error(pThis->pszSrc, "Exceeded max OMF record length (bType=%#x, cbData=%#x, cbRec=%#x, max=%#x)!\n", + pThis->bType, (unsigned)cbData, pThis->cbRec, OMF_MAX_RECORD_PAYLOAD); +} + +static bool omfWriter_RecAddStringNEx(POMFWRITER pThis, const char *pchString, size_t cchString, bool fPrependUnderscore) +{ + if (cchString < 256) + { + return omfWriter_RecAddU8(pThis, (uint8_t)cchString + fPrependUnderscore) + && (!fPrependUnderscore || omfWriter_RecAddU8(pThis, '_')) + && omfWriter_RecAddBytes(pThis, pchString, cchString); + } + return error(pThis->pszSrc, "String too long (%u bytes): '%*.*s'\n", + (unsigned)cchString, (int)cchString, (int)cchString, pchString); +} + +static bool omfWriter_RecAddStringN(POMFWRITER pThis, const char *pchString, size_t cchString) +{ + return omfWriter_RecAddStringNEx(pThis, pchString, cchString, false /*fPrependUnderscore*/); +} + +static bool omfWriter_RecAddString(POMFWRITER pThis, const char *pszString) +{ + return omfWriter_RecAddStringNEx(pThis, pszString, strlen(pszString), false /*fPrependUnderscore*/); +} + +static bool omfWriter_RecEnd(POMFWRITER pThis, bool fAddCrc) +{ + if ( !fAddCrc + || omfWriter_RecAddU8(pThis, 0)) + { + OMFRECHDR RecHdr = { pThis->bType, RT_H2LE_U16(pThis->cbRec) }; + if ( fwrite(&RecHdr, sizeof(RecHdr), 1, pThis->pDst) == 1 + && fwrite(pThis->abData, pThis->cbRec, 1, pThis->pDst) == 1) + { + pThis->bType = 0; + pThis->cbRec = 0; + return true; + } + return error(pThis->pszSrc, "Write error\n"); + } + return false; +} + +static bool omfWriter_RecEndWithCrc(POMFWRITER pThis) +{ + return omfWriter_RecEnd(pThis, true /*fAddCrc*/); +} + + +static bool omfWriter_BeginModule(POMFWRITER pThis, const char *pszFile) +{ + return omfWriter_RecBegin(pThis, OMF_THEADR) + && omfWriter_RecAddString(pThis, pszFile) + && omfWriter_RecEndWithCrc(pThis); +} + + +/** + * Simple stupid string hashing function (for LNAMES) + * @returns 8-bit hash. + * @param pchName The string. + * @param cchName The string length. + */ +DECLINLINE(uint8_t) omfWriter_HashStrU8(const char *pchName, size_t cchName) +{ + if (cchName) + return (uint8_t)(cchName + pchName[cchName >> 1]); + return 0; +} + +/** + * Looks up a LNAME. + * + * @returns Index (0..32K) if found, UINT16_MAX if not found. + * @param pThis The OMF writer. + * @param pchName The name to look up. + * @param cchName The length of the name. + */ +static uint16_t omfWriter_LNamesLookupN(POMFWRITER pThis, const char *pchName, size_t cchName) +{ + uint8_t uHash = omfWriter_HashStrU8(pchName, cchName); + uHash %= RT_ELEMENTS(pThis->apNameLookup); + + POMFWRLNAME pCur = pThis->apNameLookup[uHash]; + while (pCur) + { + if ( pCur->cchName == cchName + && memcmp(pCur->szName, pchName, cchName) == 0) + return pCur->idxName; + pCur = pCur->pNext; + } + + return UINT16_MAX; +} + +/** + * Add a LNAME lookup record. + * + * @returns success indicator. + * @param pThis The OMF writer. + * @param pchName The name to look up. + * @param cchName The length of the name. + * @param idxName The name index. + */ +static bool omfWriter_LNamesAddLookup(POMFWRITER pThis, const char *pchName, size_t cchName, uint16_t idxName) +{ + POMFWRLNAME pCur = (POMFWRLNAME)malloc(sizeof(*pCur) + cchName); + if (!pCur) + return error("???", "Out of memory!\n"); + + pCur->idxName = idxName; + pCur->cchName = (uint8_t)cchName; + memcpy(pCur->szName, pchName, cchName); + pCur->szName[cchName] = '\0'; + + uint8_t uHash = omfWriter_HashStrU8(pchName, cchName); + uHash %= RT_ELEMENTS(pThis->apNameLookup); + pCur->pNext = pThis->apNameLookup[uHash]; + pThis->apNameLookup[uHash] = pCur; + + return true; +} + + +static bool omfWriter_LNamesAddN(POMFWRITER pThis, const char *pchName, size_t cchName, uint16_t *pidxName) +{ + /* See if we've already got that name in the list. */ + uint16_t idxName; + if (pidxName) /* If pidxName is NULL, we assume the caller might just be passing stuff thru. */ + { + idxName = omfWriter_LNamesLookupN(pThis, pchName, cchName); + if (idxName != UINT16_MAX) + { + *pidxName = idxName; + return true; + } + } + + /* split? */ + if (pThis->cbRec + 1 /*len*/ + cchName + 1 /*crc*/ > OMF_MAX_RECORD_PAYLOAD) + { + if (pThis->cbRec == 0) + return error(pThis->pszSrc, "Too long LNAME '%*.*s'\n", (int)cchName, (int)cchName, pchName); + if ( !omfWriter_RecEndWithCrc(pThis) + || !omfWriter_RecBegin(pThis, OMF_LNAMES)) + return false; + } + + idxName = pThis->idxNextName++; + if (pidxName) + *pidxName = idxName; + return omfWriter_RecAddStringN(pThis, pchName, cchName) + && omfWriter_LNamesAddLookup(pThis, pchName, cchName, idxName); +} + +static bool omfWriter_LNamesAdd(POMFWRITER pThis, const char *pszName, uint16_t *pidxName) +{ + return omfWriter_LNamesAddN(pThis, pszName, strlen(pszName), pidxName); +} + +static bool omfWriter_LNamesBegin(POMFWRITER pThis, bool fAddZeroEntry) +{ + /* First entry is an empty string. */ + return omfWriter_RecBegin(pThis, OMF_LNAMES) + && ( pThis->idxNextName > 1 + || !fAddZeroEntry + || omfWriter_LNamesAddN(pThis, "", 0, NULL)); +} + +static bool omfWriter_LNamesEnd(POMFWRITER pThis) +{ + return omfWriter_RecEndWithCrc(pThis); +} + + +static bool omfWriter_SegDef(POMFWRITER pThis, uint8_t bSegAttr, uint32_t cbSeg, uint16_t idxSegName, uint16_t idxSegClass, + uint16_t idxOverlay = 1 /* NULL entry */) +{ + return omfWriter_RecBegin(pThis, OMF_SEGDEF32) + && omfWriter_RecAddU8(pThis, bSegAttr) + && omfWriter_RecAddU32(pThis, cbSeg) + && omfWriter_RecAddIdx(pThis, idxSegName) + && omfWriter_RecAddIdx(pThis, idxSegClass) + && omfWriter_RecAddIdx(pThis, idxOverlay) + && omfWriter_RecEndWithCrc(pThis); +} + +static bool omfWriter_SegDef16(POMFWRITER pThis, uint8_t bSegAttr, uint32_t cbSeg, uint16_t idxSegName, uint16_t idxSegClass, + uint16_t idxOverlay = 1 /* NULL entry */) +{ + Assert(cbSeg <= UINT16_MAX); + return omfWriter_RecBegin(pThis, OMF_SEGDEF16) + && omfWriter_RecAddU8(pThis, bSegAttr) + && omfWriter_RecAddU16(pThis, cbSeg) + && omfWriter_RecAddIdx(pThis, idxSegName) + && omfWriter_RecAddIdx(pThis, idxSegClass) + && omfWriter_RecAddIdx(pThis, idxOverlay) + && omfWriter_RecEndWithCrc(pThis); +} + +static bool omfWriter_GrpDefBegin(POMFWRITER pThis, uint16_t idxGrpName) +{ + return omfWriter_RecBegin(pThis, OMF_GRPDEF) + && omfWriter_RecAddIdx(pThis, idxGrpName); +} + +static bool omfWriter_GrpDefAddSegDef(POMFWRITER pThis, uint16_t idxSegDef) +{ + return omfWriter_RecAddU8(pThis, 0xff) + && omfWriter_RecAddIdx(pThis, idxSegDef); +} + +static bool omfWriter_GrpDefEnd(POMFWRITER pThis) +{ + return omfWriter_RecEndWithCrc(pThis); +} + + +static bool omfWriter_PubDefBegin(POMFWRITER pThis, uint16_t idxGrpDef, uint16_t idxSegDef) +{ + return omfWriter_RecBegin(pThis, OMF_PUBDEF32) + && omfWriter_RecAddIdx(pThis, idxGrpDef) + && omfWriter_RecAddIdx(pThis, idxSegDef) + && ( idxSegDef != 0 + || omfWriter_RecAddU16(pThis, 0)); + +} + +static bool omfWriter_PubDefAddN(POMFWRITER pThis, uint32_t uValue, const char *pchString, size_t cchString, + bool fPrependUnderscore) +{ + /* Split? */ + if (pThis->cbRec + 1 + cchString + 4 + 1 + 1 + fPrependUnderscore > OMF_MAX_RECORD_PAYLOAD) + { + if (cchString >= 256) + return error(pThis->pszSrc, "PUBDEF string too long %u ('%s')\n", + (unsigned)cchString, (int)cchString, (int)cchString, pchString); + if (!omfWriter_RecEndWithCrc(pThis)) + return false; + + /* Figure out the initial data length. */ + pThis->cbRec = 1 + ((pThis->abData[0] & 0x80) != 0); + if (pThis->abData[pThis->cbRec] != 0) + pThis->cbRec += 1 + ((pThis->abData[pThis->cbRec] & 0x80) != 0); + else + pThis->cbRec += 3; + pThis->bType = OMF_PUBDEF32; + } + + return omfWriter_RecAddStringNEx(pThis, pchString, cchString, fPrependUnderscore) + && omfWriter_RecAddU32(pThis, uValue) + && omfWriter_RecAddIdx(pThis, 0); /* type */ +} + +static bool omfWriter_PubDefAdd(POMFWRITER pThis, uint32_t uValue, const char *pszString, bool fPrependUnderscore) +{ + return omfWriter_PubDefAddN(pThis, uValue, pszString, strlen(pszString), fPrependUnderscore); +} + +static bool omfWriter_PubDefEnd(POMFWRITER pThis) +{ + return omfWriter_RecEndWithCrc(pThis); +} + +/** + * EXTDEF - Begin record. + */ +static bool omfWriter_ExtDefBegin(POMFWRITER pThis) +{ + return omfWriter_RecBegin(pThis, OMF_EXTDEF); + +} + +/** + * EXTDEF - Add an entry, split record if necessary. + */ +static bool omfWriter_ExtDefAddN(POMFWRITER pThis, const char *pchString, size_t cchString, uint16_t idxType, + bool fPrependUnderscore) +{ + /* Split? */ + if (pThis->cbRec + 1 + cchString + 1 + 1 + fPrependUnderscore > OMF_MAX_RECORD_PAYLOAD) + { + if (cchString >= 256) + return error(pThis->pszSrc, "EXTDEF string too long %u ('%s')\n", + (unsigned)cchString, (int)cchString, (int)cchString, pchString); + if ( !omfWriter_RecEndWithCrc(pThis) + || !omfWriter_RecBegin(pThis, OMF_EXTDEF)) + return false; + } + + return omfWriter_RecAddStringNEx(pThis, pchString, cchString, fPrependUnderscore) + && omfWriter_RecAddIdx(pThis, idxType); /* type */ +} + +/** + * EXTDEF - Add an entry, split record if necessary. + */ +static bool omfWriter_ExtDefAdd(POMFWRITER pThis, const char *pszString, bool fPrependUnderscore) +{ + return omfWriter_ExtDefAddN(pThis, pszString, strlen(pszString), 0, fPrependUnderscore); +} + +/** + * EXTDEF - End of record. + */ +static bool omfWriter_ExtDefEnd(POMFWRITER pThis) +{ + return omfWriter_RecEndWithCrc(pThis); +} + +/** + * COMENT/LINK_PASS_SEP - Add a link pass separator comment. + */ +static bool omfWriter_LinkPassSeparator(POMFWRITER pThis) +{ + return omfWriter_RecBegin(pThis, OMF_COMENT) + && omfWriter_RecAddU8(pThis, OMF_CTYP_NO_LIST) + && omfWriter_RecAddU8(pThis, OMF_CCLS_LINK_PASS_SEP) + && omfWriter_RecAddU8(pThis, 1) + && omfWriter_RecEndWithCrc(pThis); +} + + +/** + * LEDATA + FIXUPP - Begin records. + */ +static bool omfWriter_LEDataBegin(POMFWRITER pThis, uint16_t idxSeg, uint32_t offSeg) +{ + if ( omfWriter_RecBegin(pThis, OMF_LEDATA32) + && omfWriter_RecAddIdx(pThis, idxSeg) + && omfWriter_RecAddU32(pThis, offSeg)) + { + pThis->idx = idxSeg; + pThis->offSeg = offSeg; + pThis->offSegRec = offSeg; + pThis->offSegEnd = offSeg + OMF_MAX_RECORD_PAYLOAD - 1 /*CRC*/ - pThis->cbRec; + pThis->offSegEnd &= ~(uint32_t)7; /* qword align. */ + + /* Reset the associated FIXUPP records. */ + pThis->iFixupp = 0; + for (unsigned i = 0; i < RT_ELEMENTS(pThis->aFixupps); i++) + pThis->aFixupps[i].cbRec = 0; + return true; + } + return false; +} + +/** + * LEDATA + FIXUPP - Begin records. + */ +static bool omfWriter_LEDataBeginEx(POMFWRITER pThis, uint16_t idxSeg, uint32_t offSeg, + uint32_t cbData, uint32_t cbRawData, void const *pbRawData, uint8_t **ppbData) +{ + if ( omfWriter_RecBegin(pThis, OMF_LEDATA32) + && omfWriter_RecAddIdx(pThis, idxSeg) + && omfWriter_RecAddU32(pThis, offSeg)) + { + if ( cbData <= _1K + && pThis->cbRec + cbData + 1 <= OMF_MAX_RECORD_PAYLOAD) + { + uint8_t *pbDst = &pThis->abData[pThis->cbRec]; + if (ppbData) + *ppbData = pbDst; + + if (cbRawData) + memcpy(pbDst, pbRawData, RT_MIN(cbData, cbRawData)); + if (cbData > cbRawData) + memset(&pbDst[cbRawData], 0, cbData - cbRawData); + + pThis->cbRec += cbData; + pThis->idx = idxSeg; + pThis->offSegRec = offSeg; + pThis->offSeg = offSeg + cbData; + pThis->offSegEnd = offSeg + cbData; + + /* Reset the associated FIXUPP records. */ + pThis->iFixupp = 0; + for (unsigned i = 0; i < RT_ELEMENTS(pThis->aFixupps); i++) + pThis->aFixupps[i].cbRec = 0; + return true; + } + error(pThis->pszSrc, "Too much data for LEDATA record! (%#x)\n", (unsigned)cbData); + } + return false; +} + +/** + * LEDATA + FIXUPP - Add FIXUPP subrecord bytes, split if necessary. + */ +static bool omfWriter_LEDataAddFixuppBytes(POMFWRITER pThis, void *pvSubRec, size_t cbSubRec) +{ + /* Split? */ + unsigned iFixupp = pThis->iFixupp; + if (pThis->aFixupps[iFixupp].cbRec + cbSubRec >= OMF_MAX_RECORD_PAYLOAD) + { + if (g_cVerbose >= 2) + printf("debug: FIXUPP split\n"); + iFixupp++; + if (iFixupp >= RT_ELEMENTS(pThis->aFixupps)) + return error(pThis->pszSrc, "Out of FIXUPP records\n"); + pThis->iFixupp = iFixupp; + pThis->aFixupps[iFixupp].cbRec = 0; /* paranoia */ + } + + /* Append the sub-record data. */ + memcpy(&pThis->aFixupps[iFixupp].abData[pThis->aFixupps[iFixupp].cbRec], pvSubRec, cbSubRec); + pThis->aFixupps[iFixupp].cbRec += (uint16_t)cbSubRec; + return true; +} + +/** + * LEDATA + FIXUPP - Add fixup, split if necessary. + */ +static bool omfWriter_LEDataAddFixup(POMFWRITER pThis, uint16_t offDataRec, bool fSelfRel, uint8_t bLocation, + uint8_t bFrame, uint16_t idxFrame, + uint8_t bTarget, uint16_t idxTarget, bool fTargetDisp, uint32_t offTargetDisp) +{ + if (g_cVerbose >= 2) + printf("debug: FIXUP[%#x]: off=%#x frame=%u:%#x target=%u:%#x disp=%d:%#x\n", pThis->aFixupps[pThis->iFixupp].cbRec, + offDataRec, bFrame, idxFrame, bTarget, idxTarget, fTargetDisp, offTargetDisp); + + if ( offDataRec >= _1K + || bFrame >= 6 + || bTarget > 6 + || idxFrame >= _32K + || idxTarget >= _32K + || fTargetDisp != (bTarget <= OMF_FIX_T_FRAME_NO) ) + return error(pThis->pszSrc, + "Internal error: offDataRec=%#x bFrame=%u idxFrame=%#x bTarget=%u idxTarget=%#x fTargetDisp=%d offTargetDisp=%#x\n", + offDataRec, bFrame, idxFrame, bTarget, idxTarget, fTargetDisp, offTargetDisp); + + + /* + * Encode the FIXUP subrecord. + */ + uint8_t abFixup[16]; + uint8_t off = 0; + /* Location */ + abFixup[off++] = (offDataRec >> 8) | (bLocation << 2) | ((uint8_t)!fSelfRel << 6) | 0x80; + abFixup[off++] = (uint8_t)offDataRec; + /* Fix Data */ + abFixup[off++] = 0x00 /*F=0*/ | (bFrame << 4) | 0x00 /*T=0*/ | bTarget; + /* Frame Datum */ + if (bFrame <= OMF_FIX_F_FRAME_NO) + { + if (idxFrame >= 128) + abFixup[off++] = (uint8_t)(idxFrame >> 8) | 0x80; + abFixup[off++] = (uint8_t)idxFrame; + } + /* Target Datum */ + if (idxTarget >= 128) + abFixup[off++] = (uint8_t)(idxTarget >> 8) | 0x80; + abFixup[off++] = (uint8_t)idxTarget; + /* Target Displacement */ + if (fTargetDisp) + { + abFixup[off++] = RT_BYTE1(offTargetDisp); + abFixup[off++] = RT_BYTE2(offTargetDisp); + abFixup[off++] = RT_BYTE3(offTargetDisp); + abFixup[off++] = RT_BYTE4(offTargetDisp); + } + + return omfWriter_LEDataAddFixuppBytes(pThis, abFixup, off); +} + +/** + * LEDATA + FIXUPP - Add simple fixup, split if necessary. + */ +static bool omfWriter_LEDataAddFixupNoDisp(POMFWRITER pThis, uint16_t offDataRec, uint8_t bLocation, + uint8_t bFrame, uint16_t idxFrame, uint8_t bTarget, uint16_t idxTarget) +{ + return omfWriter_LEDataAddFixup(pThis, offDataRec, false /*fSelfRel*/, bLocation, bFrame, idxFrame, bTarget, idxTarget, + false /*fTargetDisp*/, 0 /*offTargetDisp*/); +} + + +/** + * LEDATA + FIXUPP - End of records. + */ +static bool omfWriter_LEDataEnd(POMFWRITER pThis) +{ + if (omfWriter_RecEndWithCrc(pThis)) + { + for (unsigned iFixupp = 0; iFixupp <= pThis->iFixupp; iFixupp++) + { + uint16_t const cbRec = pThis->aFixupps[iFixupp].cbRec; + if (!cbRec) + break; + if (g_cVerbose >= 3) + printf("debug: FIXUPP32 #%u cbRec=%#x\n", iFixupp, cbRec); + if ( !omfWriter_RecBegin(pThis, OMF_FIXUPP32) + || !omfWriter_RecAddBytes(pThis, pThis->aFixupps[iFixupp].abData, cbRec) + || !omfWriter_RecEndWithCrc(pThis)) + return false; + } + pThis->iFixupp = 0; + return true; + } + return false; +} + +/** + * LEDATA + FIXUPP - Splits the LEDATA record. + */ +static bool omfWriter_LEDataSplit(POMFWRITER pThis) +{ + return omfWriter_LEDataEnd(pThis) + && omfWriter_LEDataBegin(pThis, pThis->idx, pThis->offSeg); +} + +/** + * LEDATA + FIXUPP - Returns available space in current LEDATA record. + */ +static uint32_t omfWriter_LEDataAvailable(POMFWRITER pThis) +{ + if (pThis->offSeg < pThis->offSegEnd) + return pThis->offSegEnd - pThis->offSeg; + return 0; +} + +/** + * LEDATA + FIXUPP - Splits LEDATA record if less than @a cb bytes available. + */ +static bool omfWriter_LEDataEnsureSpace(POMFWRITER pThis, uint32_t cb) +{ + if ( omfWriter_LEDataAvailable(pThis) >= cb + || omfWriter_LEDataSplit(pThis)) + return true; + return false; +} + +/** + * LEDATA + FIXUPP - Adds data to the LEDATA record, splitting it if needed. + */ +static bool omfWriter_LEDataAddBytes(POMFWRITER pThis, void const *pvData, size_t cbData) +{ + while (cbData > 0) + { + uint32_t cbAvail = omfWriter_LEDataAvailable(pThis); + if (cbAvail >= cbData) + { + if (omfWriter_RecAddBytes(pThis, pvData, cbData)) + { + pThis->offSeg += (uint32_t)cbData; + break; + } + return false; + } + if (!omfWriter_RecAddBytes(pThis, pvData, cbAvail)) + return false; + pThis->offSeg += cbAvail; + pvData = (uint8_t const *)pvData + cbAvail; + cbData -= cbAvail; + if (!omfWriter_LEDataSplit(pThis)) + return false; + } + return true; +} + +/** + * LEDATA + FIXUPP - Adds a U32 to the LEDATA record, splitting if needed. + */ +static bool omfWriter_LEDataAddU32(POMFWRITER pThis, uint32_t u32) +{ + if ( omfWriter_LEDataEnsureSpace(pThis, 4) + && omfWriter_RecAddU32(pThis, u32)) + { + pThis->offSeg += 4; + return true; + } + return false; +} + +/** + * LEDATA + FIXUPP - Adds a U16 to the LEDATA record, splitting if needed. + */ +static bool omfWriter_LEDataAddU16(POMFWRITER pThis, uint16_t u16) +{ + if ( omfWriter_LEDataEnsureSpace(pThis, 2) + && omfWriter_RecAddU16(pThis, u16)) + { + pThis->offSeg += 2; + return true; + } + return false; +} + +#if 0 /* unused */ +/** + * LEDATA + FIXUPP - Adds a byte to the LEDATA record, splitting if needed. + */ +static bool omfWriter_LEDataAddU8(POMFWRITER pThis, uint8_t b) +{ + if ( omfWriter_LEDataEnsureSpace(pThis, 1) + && omfWriter_RecAddU8(pThis, b)) + { + pThis->offSeg += 1; + return true; + } + return false; +} +#endif + +/** + * MODEND - End of module, simple variant. + */ +static bool omfWriter_EndModule(POMFWRITER pThis) +{ + return omfWriter_RecBegin(pThis, OMF_MODEND32) + && omfWriter_RecAddU8(pThis, 0) + && omfWriter_RecEndWithCrc(pThis); +} + + + + +/********************************************************************************************************************************* +* ELF64/AMD64 -> ELF64/i386 Converter * +*********************************************************************************************************************************/ + +/** AMD64 relocation type names for ELF. */ +static const char * const g_apszElfAmd64RelTypes[] = +{ + "R_X86_64_NONE", + "R_X86_64_64", + "R_X86_64_PC32", + "R_X86_64_GOT32", + "R_X86_64_PLT32", + "R_X86_64_COPY", + "R_X86_64_GLOB_DAT", + "R_X86_64_JMP_SLOT", + "R_X86_64_RELATIVE", + "R_X86_64_GOTPCREL", + "R_X86_64_32", + "R_X86_64_32S", + "R_X86_64_16", + "R_X86_64_PC16", + "R_X86_64_8", + "R_X86_64_PC8", + "R_X86_64_DTPMOD64", + "R_X86_64_DTPOFF64", + "R_X86_64_TPOFF64", + "R_X86_64_TLSGD", + "R_X86_64_TLSLD", + "R_X86_64_DTPOFF32", + "R_X86_64_GOTTPOFF", + "R_X86_64_TPOFF32", +}; + +/** AMD64 relocation type sizes for ELF. */ +static uint8_t const g_acbElfAmd64RelTypes[] = +{ + 0, /* R_X86_64_NONE */ + 8, /* R_X86_64_64 */ + 4, /* R_X86_64_PC32 */ + 4, /* R_X86_64_GOT32 */ + 4, /* R_X86_64_PLT32 */ + 0, /* R_X86_64_COPY */ + 0, /* R_X86_64_GLOB_DAT */ + 0, /* R_X86_64_JMP_SLOT */ + 0, /* R_X86_64_RELATIVE */ + 0, /* R_X86_64_GOTPCREL */ + 4, /* R_X86_64_32 */ + 4, /* R_X86_64_32S */ + 2, /* R_X86_64_16 */ + 2, /* R_X86_64_PC16 */ + 1, /* R_X86_64_8 */ + 1, /* R_X86_64_PC8 */ + 0, /* R_X86_64_DTPMOD64 */ + 0, /* R_X86_64_DTPOFF64 */ + 0, /* R_X86_64_TPOFF64 */ + 0, /* R_X86_64_TLSGD */ + 0, /* R_X86_64_TLSLD */ + 0, /* R_X86_64_DTPOFF32 */ + 0, /* R_X86_64_GOTTPOFF */ + 0, /* R_X86_64_TPOFF32 */ +}; + +/** Macro for getting the size of a AMD64 ELF relocation. */ +#define ELF_AMD64_RELOC_SIZE(a_Type) ( (a_Type) < RT_ELEMENTS(g_acbElfAmd64RelTypes) ? g_acbElfAmd64RelTypes[(a_Type)] : 1) + + +typedef struct ELFDETAILS +{ + /** The ELF header. */ + Elf64_Ehdr const *pEhdr; + /** The section header table. */ + Elf64_Shdr const *paShdrs; + /** The string table for the section names. */ + const char *pchShStrTab; + + /** The symbol table section number. UINT16_MAX if not found. */ + uint16_t iSymSh; + /** The string table section number. UINT16_MAX if not found. */ + uint16_t iStrSh; + + /** The symbol table. */ + Elf64_Sym const *paSymbols; + /** The number of symbols in the symbol table. */ + uint32_t cSymbols; + + /** Pointer to the (symbol) string table if found. */ + const char *pchStrTab; + /** The string table size. */ + size_t cbStrTab; + +} ELFDETAILS; +typedef ELFDETAILS *PELFDETAILS; +typedef ELFDETAILS const *PCELFDETAILS; + + +static bool validateElf(const char *pszFile, uint8_t const *pbFile, size_t cbFile, PELFDETAILS pElfStuff) +{ + /* + * Initialize the ELF details structure. + */ + memset(pElfStuff, 0, sizeof(*pElfStuff)); + pElfStuff->iSymSh = UINT16_MAX; + pElfStuff->iStrSh = UINT16_MAX; + + /* + * Validate the header and our other expectations. + */ + Elf64_Ehdr const *pEhdr = (Elf64_Ehdr const *)pbFile; + pElfStuff->pEhdr = pEhdr; + if ( pEhdr->e_ident[EI_CLASS] != ELFCLASS64 + || pEhdr->e_ident[EI_DATA] != ELFDATA2LSB + || pEhdr->e_ehsize != sizeof(Elf64_Ehdr) + || pEhdr->e_shentsize != sizeof(Elf64_Shdr) + || pEhdr->e_version != EV_CURRENT ) + return error(pszFile, "Unsupported ELF config\n"); + if (pEhdr->e_type != ET_REL) + return error(pszFile, "Expected relocatable ELF file (e_type=%d)\n", pEhdr->e_type); + if (pEhdr->e_machine != EM_X86_64) + return error(pszFile, "Expected relocatable ELF file (e_type=%d)\n", pEhdr->e_machine); + if (pEhdr->e_phnum != 0) + return error(pszFile, "Expected e_phnum to be zero not %u\n", pEhdr->e_phnum); + if (pEhdr->e_shnum < 2) + return error(pszFile, "Expected e_shnum to be two or higher\n"); + if (pEhdr->e_shstrndx >= pEhdr->e_shnum || pEhdr->e_shstrndx == 0) + return error(pszFile, "Bad e_shstrndx=%u (e_shnum=%u)\n", pEhdr->e_shstrndx, pEhdr->e_shnum); + if ( pEhdr->e_shoff >= cbFile + || pEhdr->e_shoff + pEhdr->e_shnum * sizeof(Elf64_Shdr) > cbFile) + return error(pszFile, "Section table is outside the file (e_shoff=%#llx, e_shnum=%u, cbFile=%#llx)\n", + pEhdr->e_shstrndx, pEhdr->e_shnum, (uint64_t)cbFile); + + /* + * Locate the section name string table. + * We assume it's okay as we only reference it in verbose mode. + */ + Elf64_Shdr const *paShdrs = (Elf64_Shdr const *)&pbFile[pEhdr->e_shoff]; + pElfStuff->paShdrs = paShdrs; + + Elf64_Xword const cbShStrTab = paShdrs[pEhdr->e_shstrndx].sh_size; + if ( paShdrs[pEhdr->e_shstrndx].sh_offset > cbFile + || cbShStrTab > cbFile + || paShdrs[pEhdr->e_shstrndx].sh_offset + cbShStrTab > cbFile) + return error(pszFile, + "Section string table is outside the file (sh_offset=%#" ELF_FMT_X64 " sh_size=%#" ELF_FMT_X64 " cbFile=%#" ELF_FMT_X64 ")\n", + paShdrs[pEhdr->e_shstrndx].sh_offset, paShdrs[pEhdr->e_shstrndx].sh_size, (Elf64_Xword)cbFile); + const char *pchShStrTab = (const char *)&pbFile[paShdrs[pEhdr->e_shstrndx].sh_offset]; + pElfStuff->pchShStrTab = pchShStrTab; + + /* + * Work the section table. + */ + bool fRet = true; + for (uint32_t i = 1; i < pEhdr->e_shnum; i++) + { + if (paShdrs[i].sh_name >= cbShStrTab) + return error(pszFile, "Invalid sh_name value (%#x) for section #%u\n", paShdrs[i].sh_name, i); + const char *pszShNm = &pchShStrTab[paShdrs[i].sh_name]; + + if ( paShdrs[i].sh_offset > cbFile + || paShdrs[i].sh_size > cbFile + || paShdrs[i].sh_offset + paShdrs[i].sh_size > cbFile) + return error(pszFile, "Section #%u '%s' has data outside the file: %#" ELF_FMT_X64 " LB %#" ELF_FMT_X64 " (cbFile=%#" ELF_FMT_X64 ")\n", + i, pszShNm, paShdrs[i].sh_offset, paShdrs[i].sh_size, (Elf64_Xword)cbFile); + if (g_cVerbose) + printf("shdr[%u]: name=%#x '%s' type=%#x flags=%#" ELF_FMT_X64 " addr=%#" ELF_FMT_X64 " off=%#" ELF_FMT_X64 " size=%#" ELF_FMT_X64 "\n" + " link=%u info=%#x align=%#" ELF_FMT_X64 " entsize=%#" ELF_FMT_X64 "\n", + i, paShdrs[i].sh_name, pszShNm, paShdrs[i].sh_type, paShdrs[i].sh_flags, + paShdrs[i].sh_addr, paShdrs[i].sh_offset, paShdrs[i].sh_size, + paShdrs[i].sh_link, paShdrs[i].sh_info, paShdrs[i].sh_addralign, paShdrs[i].sh_entsize); + + if (paShdrs[i].sh_link >= pEhdr->e_shnum) + return error(pszFile, "Section #%u '%s' links to a section outside the section table: %#x, max %#x\n", + i, pszShNm, paShdrs[i].sh_link, pEhdr->e_shnum); + if (!RT_IS_POWER_OF_TWO(paShdrs[i].sh_addralign)) + return error(pszFile, "Section #%u '%s' alignment value is not a power of two: %#" ELF_FMT_X64 "\n", + i, pszShNm, paShdrs[i].sh_addralign); + if (!RT_IS_POWER_OF_TWO(paShdrs[i].sh_addralign)) + return error(pszFile, "Section #%u '%s' alignment value is not a power of two: %#" ELF_FMT_X64 "\n", + i, pszShNm, paShdrs[i].sh_addralign); + if (paShdrs[i].sh_addr != 0) + return error(pszFile, "Section #%u '%s' has non-zero address: %#" ELF_FMT_X64 "\n", i, pszShNm, paShdrs[i].sh_addr); + + if (paShdrs[i].sh_type == SHT_RELA) + { + if (paShdrs[i].sh_entsize != sizeof(Elf64_Rela)) + return error(pszFile, "Expected sh_entsize to be %u not %u for section #%u (%s)\n", (unsigned)sizeof(Elf64_Rela), + paShdrs[i].sh_entsize, i, pszShNm); + uint32_t const cRelocs = paShdrs[i].sh_size / sizeof(Elf64_Rela); + if (cRelocs * sizeof(Elf64_Rela) != paShdrs[i].sh_size) + return error(pszFile, "Uneven relocation entry count in #%u (%s): sh_size=%#" ELF_FMT_X64 "\n", + i, pszShNm, paShdrs[i].sh_size); + if ( paShdrs[i].sh_offset > cbFile + || paShdrs[i].sh_size >= cbFile + || paShdrs[i].sh_offset + paShdrs[i].sh_size > cbFile) + return error(pszFile, "The content of section #%u '%s' is outside the file (%#" ELF_FMT_X64 " LB %#" ELF_FMT_X64 ", cbFile=%#lx)\n", + i, pszShNm, paShdrs[i].sh_offset, paShdrs[i].sh_size, (unsigned long)cbFile); + if (paShdrs[i].sh_info != i - 1) + return error(pszFile, "Expected relocation section #%u (%s) to link to previous section: sh_info=%#u\n", + i, pszShNm, (unsigned)paShdrs[i].sh_link); + if (paShdrs[paShdrs[i].sh_link].sh_type != SHT_SYMTAB) + return error(pszFile, "Expected relocation section #%u (%s) to link to symbol table: sh_link=%#u -> sh_type=%#x\n", + i, pszShNm, (unsigned)paShdrs[i].sh_link, (unsigned)paShdrs[paShdrs[i].sh_link].sh_type); + uint32_t cSymbols = paShdrs[paShdrs[i].sh_link].sh_size / paShdrs[paShdrs[i].sh_link].sh_entsize; + + Elf64_Rela const *paRelocs = (Elf64_Rela *)&pbFile[paShdrs[i].sh_offset]; + for (uint32_t j = 0; j < cRelocs; j++) + { + uint8_t const bType = ELF64_R_TYPE(paRelocs[j].r_info); + if (RT_UNLIKELY(bType >= R_X86_64_COUNT)) + fRet = error(pszFile, + "%#018" ELF_FMT_X64 " %#018" ELF_FMT_X64 ": unknown fix up %#x (%+" ELF_FMT_D64 ")\n", + paRelocs[j].r_offset, paRelocs[j].r_info, bType, paRelocs[j].r_addend); + if (RT_UNLIKELY( paRelocs[j].r_offset > paShdrs[i - 1].sh_size + || paRelocs[j].r_offset + ELF_AMD64_RELOC_SIZE(ELF64_R_TYPE(paRelocs[j].r_info)) + > paShdrs[i - 1].sh_size)) + fRet = error(pszFile, + "%#018" ELF_FMT_X64 " %#018" ELF_FMT_X64 ": out of bounds (sh_size %" ELF_FMT_X64 ")\n", + paRelocs[j].r_offset, paRelocs[j].r_info, paShdrs[i - 1].sh_size); + + uint32_t const iSymbol = ELF64_R_SYM(paRelocs[j].r_info); + if (RT_UNLIKELY(iSymbol >= cSymbols)) + fRet = error(pszFile, + "%#018" ELF_FMT_X64 " %#018" ELF_FMT_X64 ": symbol index (%#x) out of bounds (%#x)\n", + paRelocs[j].r_offset, paRelocs[j].r_info, iSymbol, cSymbols); + } + } + else if (paShdrs[i].sh_type == SHT_REL) + fRet = error(pszFile, "Section #%u '%s': Unexpected SHT_REL section\n", i, pszShNm); + else if (paShdrs[i].sh_type == SHT_SYMTAB) + { + if (paShdrs[i].sh_entsize != sizeof(Elf64_Sym)) + fRet = error(pszFile, "Section #%u '%s': Unsupported symbol table entry size in : #%u (expected #%u)\n", + i, pszShNm, paShdrs[i].sh_entsize, sizeof(Elf64_Sym)); + Elf64_Xword const cSymbols = paShdrs[i].sh_size / paShdrs[i].sh_entsize; + if (cSymbols * paShdrs[i].sh_entsize != paShdrs[i].sh_size) + fRet = error(pszFile, "Section #%u '%s': Size not a multiple of entry size: %#" ELF_FMT_X64 " %% %#" ELF_FMT_X64 " = %#" ELF_FMT_X64 "\n", + i, pszShNm, paShdrs[i].sh_size, paShdrs[i].sh_entsize, paShdrs[i].sh_size % paShdrs[i].sh_entsize); + if (cSymbols > UINT32_MAX) + fRet = error(pszFile, "Section #%u '%s': too many symbols: %" ELF_FMT_X64 "\n", + i, pszShNm, paShdrs[i].sh_size, cSymbols); + + if (pElfStuff->iSymSh == UINT16_MAX) + { + pElfStuff->iSymSh = (uint16_t)i; + pElfStuff->paSymbols = (Elf64_Sym const *)&pbFile[paShdrs[i].sh_offset]; + pElfStuff->cSymbols = cSymbols; + + if (paShdrs[i].sh_link != 0) + { + /* Note! The symbol string table section header may not have been validated yet! */ + Elf64_Shdr const *pStrTabShdr = &paShdrs[paShdrs[i].sh_link]; + pElfStuff->iStrSh = paShdrs[i].sh_link; + pElfStuff->pchStrTab = (const char *)&pbFile[pStrTabShdr->sh_offset]; + pElfStuff->cbStrTab = (size_t)pStrTabShdr->sh_size; + } + else + fRet = error(pszFile, "Section #%u '%s': String table link is out of bounds (%#x)\n", + i, pszShNm, paShdrs[i].sh_link); + } + else + fRet = error(pszFile, "Section #%u '%s': Found additonal symbol table, previous in #%u\n", + i, pszShNm, pElfStuff->iSymSh); + } + } + return fRet; +} + + +static bool convertElfSectionsToSegDefsAndGrpDefs(POMFWRITER pThis, PCELFDETAILS pElfStuff) +{ + /* + * Do the list of names pass. + */ + uint16_t idxGrpFlat, idxGrpData; + uint16_t idxClassCode, idxClassData, idxClassDwarf; + if ( !omfWriter_LNamesBegin(pThis, true /*fAddZeroEntry*/) + || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("FLAT"), &idxGrpFlat) + || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("BS3DATA64_GROUP"), &idxGrpData) + || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("BS3CLASS64CODE"), &idxClassCode) + || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("FAR_DATA"), &idxClassData) + || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("DWARF"), &idxClassDwarf) + ) + return false; + + bool fHaveData = false; + Elf64_Shdr const *pShdr = &pElfStuff->paShdrs[1]; + Elf64_Half const cSections = pElfStuff->pEhdr->e_shnum; + for (Elf64_Half i = 1; i < cSections; i++, pShdr++) + { + const char *pszName = &pElfStuff->pchShStrTab[pShdr->sh_name]; + if (*pszName == '\0') + return error(pThis->pszSrc, "Section #%u has an empty name!\n", i); + + switch (pShdr->sh_type) + { + case SHT_PROGBITS: + case SHT_NOBITS: + /* We drop a few sections we don't want:. */ + if ( strcmp(pszName, ".comment") != 0 /* compiler info */ + && strcmp(pszName, ".note.GNU-stack") != 0 /* some empty section for hinting the linker/whatever */ + && strcmp(pszName, ".eh_frame") != 0 /* unwind / exception info */ + ) + { + pThis->paSegments[i].iSegDef = UINT16_MAX; + pThis->paSegments[i].iGrpDef = UINT16_MAX; + + /* Translate the name and determine group and class. + Note! We currently strip sub-sections. */ + if ( strcmp(pszName, ".text") == 0 + || strncmp(pszName, RT_STR_TUPLE(".text.")) == 0) + { + pszName = "BS3TEXT64"; + pThis->paSegments[i].iGrpNm = idxGrpFlat; + pThis->paSegments[i].iClassNm = idxClassCode; + } + else if ( strcmp(pszName, ".data") == 0 + || strncmp(pszName, RT_STR_TUPLE(".data.")) == 0) + { + pszName = "BS3DATA64"; + pThis->paSegments[i].iGrpNm = idxGrpData; + pThis->paSegments[i].iClassNm = idxClassData; + } + else if (strcmp(pszName, ".bss") == 0) + { + pszName = "BS3BSS64"; + pThis->paSegments[i].iGrpNm = idxGrpData; + pThis->paSegments[i].iClassNm = idxClassData; + } + else if ( strcmp(pszName, ".rodata") == 0 + || strncmp(pszName, RT_STR_TUPLE(".rodata.")) == 0) + { + pszName = "BS3DATA64CONST"; + pThis->paSegments[i].iGrpNm = idxGrpData; + pThis->paSegments[i].iClassNm = idxClassData; + } + else if (strncmp(pszName, RT_STR_TUPLE(".debug_")) == 0) + { + pThis->paSegments[i].iGrpNm = UINT16_MAX; + pThis->paSegments[i].iClassNm = idxClassDwarf; + } + else + { + pThis->paSegments[i].iGrpNm = idxGrpData; + pThis->paSegments[i].iClassNm = idxClassData; + error(pThis->pszSrc, "Unknown data (?) segment: '%s'\n", pszName); + } + + /* Save the name. */ + pThis->paSegments[i].pszName = strdup(pszName); + if (!pThis->paSegments[i].pszName) + return error(pThis->pszSrc, "Out of memory!\n"); + + /* Add the section name. */ + if (!omfWriter_LNamesAdd(pThis, pThis->paSegments[i].pszName, &pThis->paSegments[i].iSegNm)) + return false; + + fHaveData |= pThis->paSegments[i].iGrpNm == idxGrpData; + break; + } + RT_FALL_THRU(); + + default: + pThis->paSegments[i].iSegDef = UINT16_MAX; + pThis->paSegments[i].iGrpDef = UINT16_MAX; + pThis->paSegments[i].iSegNm = UINT16_MAX; + pThis->paSegments[i].iGrpNm = UINT16_MAX; + pThis->paSegments[i].iClassNm = UINT16_MAX; + pThis->paSegments[i].pszName = NULL; + break; + } + } + + if (!omfWriter_LNamesEnd(pThis)) + return false; + + /* + * Emit segment definitions. + */ + uint16_t iSegDef = 1; /* Start counting at 1. */ + pShdr = &pElfStuff->paShdrs[1]; + for (Elf64_Half i = 1; i < cSections; i++, pShdr++) + { + if (pThis->paSegments[i].iSegNm == UINT16_MAX) + continue; + + uint8_t bSegAttr = 0; + + /* The A field. */ + switch (pShdr->sh_addralign) + { + case 0: + case 1: + bSegAttr |= 1 << 5; + break; + case 2: + bSegAttr |= 2 << 5; + break; + case 4: + bSegAttr |= 5 << 5; + break; + case 8: + case 16: + bSegAttr |= 3 << 5; + break; + case 32: + case 64: + case 128: + case 256: + bSegAttr |= 4 << 5; + break; + default: + bSegAttr |= 6 << 5; /* page aligned, pharlabs extension. */ + break; + } + + /* The C field. */ + bSegAttr |= 2 << 2; /* public */ + + /* The B field. We don't have 4GB segments, so leave it as zero. */ + + /* The D field shall be set as we're doing USE32. */ + bSegAttr |= 1; + + + /* Done. */ + if (!omfWriter_SegDef(pThis, bSegAttr, (uint32_t)pShdr->sh_size, + pThis->paSegments[i].iSegNm, + pThis->paSegments[i].iClassNm)) + return false; + pThis->paSegments[i].iSegDef = iSegDef++; + } + + /* + * Flat group definition (#1) - special, no members. + */ + uint16_t iGrpDef = 1; + if ( !omfWriter_GrpDefBegin(pThis, idxGrpFlat) + || !omfWriter_GrpDefEnd(pThis)) + return false; + for (uint16_t i = 0; i < cSections; i++) + if (pThis->paSegments[i].iGrpNm == idxGrpFlat) + pThis->paSegments[i].iGrpDef = iGrpDef; + pThis->idxGrpFlat = iGrpDef++; + + /* + * Data group definition (#2). + */ + /** @todo do we need to consider missing segments and ordering? */ + uint16_t cGrpNms = 0; + uint16_t aiGrpNms[2] = { 0, 0 }; /* Shut up, GCC. */ + if (fHaveData) + aiGrpNms[cGrpNms++] = idxGrpData; + for (uint32_t iGrpNm = 0; iGrpNm < cGrpNms; iGrpNm++) + { + if (!omfWriter_GrpDefBegin(pThis, aiGrpNms[iGrpNm])) + return false; + for (uint16_t i = 0; i < cSections; i++) + if (pThis->paSegments[i].iGrpNm == aiGrpNms[iGrpNm]) + { + pThis->paSegments[i].iGrpDef = iGrpDef; + if (!omfWriter_GrpDefAddSegDef(pThis, pThis->paSegments[i].iSegDef)) + return false; + } + if (!omfWriter_GrpDefEnd(pThis)) + return false; + iGrpDef++; + } + + return true; +} + +static bool convertElfSymbolsToPubDefsAndExtDefs(POMFWRITER pThis, PCELFDETAILS pElfStuff) +{ + if (!pElfStuff->cSymbols) + return true; + + /* + * Process the symbols the first. + */ + uint32_t cAbsSyms = 0; + uint32_t cExtSyms = 0; + uint32_t cPubSyms = 0; + for (uint32_t iSeg = 0; iSeg < pThis->cSegments; iSeg++) + pThis->paSegments[iSeg].cPubDefs = 0; + + uint32_t const cSections = pElfStuff->pEhdr->e_shnum; + uint32_t const cSymbols = pElfStuff->cSymbols; + Elf64_Sym const * const paSymbols = pElfStuff->paSymbols; + for (uint32_t iSym = 0; iSym < cSymbols; iSym++) + { + const uint8_t bBind = ELF64_ST_BIND(paSymbols[iSym].st_info); + const uint8_t bType = ELF64_ST_TYPE(paSymbols[iSym].st_info); + const char *pszSymName = &pElfStuff->pchStrTab[paSymbols[iSym].st_name]; + if ( *pszSymName == '\0' + && bType == STT_SECTION + && paSymbols[iSym].st_shndx < cSections) + pszSymName = &pElfStuff->pchShStrTab[pElfStuff->paShdrs[paSymbols[iSym].st_shndx].sh_name]; + + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_IGNORED; + pThis->paSymbols[iSym].idx = UINT16_MAX; + pThis->paSymbols[iSym].idxSegDef = UINT16_MAX; + pThis->paSymbols[iSym].idxGrpDef = UINT16_MAX; + + uint32_t const idxSection = paSymbols[iSym].st_shndx; + if (idxSection == SHN_UNDEF) + { + if (bBind == STB_GLOBAL) + { + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_EXTDEF; + cExtSyms++; + if (*pszSymName == '\0') + return error(pThis->pszSrc, "External symbol #%u (%s) has an empty name.\n", iSym, pszSymName); + } + else if (bBind != STB_LOCAL || iSym != 0) /* Entry zero is usually a dummy. */ + return error(pThis->pszSrc, "Unsupported or invalid bind type %#x for undefined symbol #%u (%s)\n", + bBind, iSym, pszSymName); + } + else if (idxSection < cSections) + { + pThis->paSymbols[iSym].idxSegDef = pThis->paSegments[idxSection].iSegDef; + pThis->paSymbols[iSym].idxGrpDef = pThis->paSegments[idxSection].iGrpDef; + if (bBind == STB_GLOBAL) + { + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_PUBDEF; + pThis->paSegments[idxSection].cPubDefs++; + cPubSyms++; + if (bType == STT_SECTION) + return error(pThis->pszSrc, "Don't know how to export STT_SECTION symbol #%u (%s)\n", iSym, pszSymName); + if (*pszSymName == '\0') + return error(pThis->pszSrc, "Public symbol #%u (%s) has an empty name.\n", iSym, pszSymName); + } + else if (bType == STT_SECTION) + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_SEGDEF; + else + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_INTERNAL; + } + else if (idxSection == SHN_ABS) + { + if (bType != STT_FILE) + { + if (bBind == STB_GLOBAL) + { + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_PUBDEF; + pThis->paSymbols[iSym].idxSegDef = 0; + pThis->paSymbols[iSym].idxGrpDef = 0; + cAbsSyms++; + if (*pszSymName == '\0') + return error(pThis->pszSrc, "Public absolute symbol #%u (%s) has an empty name.\n", iSym, pszSymName); + } + else + return error(pThis->pszSrc, "Unsupported or invalid bind type %#x for absolute symbol #%u (%s)\n", + bBind, iSym, pszSymName); + } + } + else if (idxSection == SHN_COMMON) + return error(pThis->pszSrc, "Symbol #%u (%s) is in the unsupported 'common' section.\n", iSym, pszSymName); + else + return error(pThis->pszSrc, "Unsupported or invalid section number %#x for symbol #%u (%s)\n", + idxSection, iSym, pszSymName); + } + + /* + * Emit the PUBDEFs the first time around (see order of records in TIS spec). + */ + uint16_t idxPubDef = 1; + if (cPubSyms) + { + for (uint32_t iSeg = 0; iSeg < pThis->cSegments; iSeg++) + if (pThis->paSegments[iSeg].cPubDefs > 0) + { + uint16_t const idxSegDef = pThis->paSegments[iSeg].iSegDef; + if (!omfWriter_PubDefBegin(pThis, pThis->paSegments[iSeg].iGrpDef, idxSegDef)) + return false; + for (uint16_t iSym = 0; iSym < cSymbols; iSym++) + if ( pThis->paSymbols[iSym].idxSegDef == idxSegDef + && pThis->paSymbols[iSym].enmType == OMFSYMTYPE_PUBDEF) + { + /* Underscore prefix all names not already underscored/mangled. */ + const char *pszName = &pElfStuff->pchStrTab[paSymbols[iSym].st_name]; + if (!omfWriter_PubDefAdd(pThis, paSymbols[iSym].st_value, pszName, pszName[0] != '_')) + return false; + pThis->paSymbols[iSym].idx = idxPubDef++; + } + if (!omfWriter_PubDefEnd(pThis)) + return false; + } + } + + if (cAbsSyms > 0) + { + if (!omfWriter_PubDefBegin(pThis, 0, 0)) + return false; + for (uint16_t iSym = 0; iSym < cSymbols; iSym++) + if ( pThis->paSymbols[iSym].idxSegDef == 0 + && pThis->paSymbols[iSym].enmType == OMFSYMTYPE_PUBDEF) + { + /* Underscore prefix all names not already underscored/mangled. */ + const char *pszName = &pElfStuff->pchStrTab[paSymbols[iSym].st_name]; + if (!omfWriter_PubDefAdd(pThis, paSymbols[iSym].st_value, pszName, pszName[0] != '_')) + return false; + pThis->paSymbols[iSym].idx = idxPubDef++; + } + if (!omfWriter_PubDefEnd(pThis)) + return false; + } + + /* + * Go over the symbol table and emit external definition records. + */ + if (!omfWriter_ExtDefBegin(pThis)) + return false; + uint16_t idxExtDef = 1; + for (uint16_t iSym = 0; iSym < cSymbols; iSym++) + if (pThis->paSymbols[iSym].enmType == OMFSYMTYPE_EXTDEF) + { + /* Underscore prefix all names not already underscored/mangled. */ + const char *pszName = &pElfStuff->pchStrTab[paSymbols[iSym].st_name]; + if (!omfWriter_ExtDefAdd(pThis, pszName, *pszName != '_')) + return false; + pThis->paSymbols[iSym].idx = idxExtDef++; + } + + if (!omfWriter_ExtDefEnd(pThis)) + return false; + + return true; +} + +/** + * @callback_method_impl{FNRTSORTCMP, For Elf64_Rela tables.} + */ +static DECLCALLBACK(int) convertElfCompareRelA(void const *pvElement1, void const *pvElement2, void *pvUser) +{ + Elf64_Rela const *pReloc1 = (Elf64_Rela const *)pvElement1; + Elf64_Rela const *pReloc2 = (Elf64_Rela const *)pvElement2; + if (pReloc1->r_offset < pReloc2->r_offset) + return -1; + if (pReloc1->r_offset > pReloc2->r_offset) + return 1; + RT_NOREF_PV(pvUser); + return 0; +} + +static bool convertElfSectionsToLeDataAndFixupps(POMFWRITER pThis, PCELFDETAILS pElfStuff, uint8_t const *pbFile, size_t cbFile) +{ + Elf64_Sym const *paSymbols = pElfStuff->paSymbols; + Elf64_Shdr const *paShdrs = pElfStuff->paShdrs; + bool fRet = true; + RT_NOREF_PV(cbFile); + + for (uint32_t i = 1; i < pThis->cSegments; i++) + { + if (pThis->paSegments[i].iSegDef == UINT16_MAX) + continue; + + const char *pszSegNm = &pElfStuff->pchShStrTab[paShdrs[i].sh_name]; + bool const fRelocs = i + 1 < pThis->cSegments && paShdrs[i + 1].sh_type == SHT_RELA; + uint32_t cRelocs = fRelocs ? paShdrs[i + 1].sh_size / sizeof(Elf64_Rela) : 0; + Elf64_Rela const *paRelocs = fRelocs ? (Elf64_Rela *)&pbFile[paShdrs[i + 1].sh_offset] : NULL; + Elf64_Xword cbVirtData = paShdrs[i].sh_size; + Elf64_Xword cbData = paShdrs[i].sh_type == SHT_NOBITS ? 0 : cbVirtData; + uint8_t const *pbData = &pbFile[paShdrs[i].sh_offset]; + uint32_t off = 0; + + /* We sort fixups by r_offset in order to more easily split them into chunks. */ + RTSortShell((void *)paRelocs, cRelocs, sizeof(paRelocs[0]), convertElfCompareRelA, NULL); + + /* The OMF record size requires us to split larger sections up. To make + life simple, we fill zeros for unitialized (BSS) stuff. */ + const uint32_t cbMaxData = RT_MIN(OMF_MAX_RECORD_PAYLOAD - 1 - (pThis->paSegments[i].iSegDef >= 128) - 4 - 1, _1K); + while (cbVirtData > 0) + { + /* Figure out how many bytes to put out in this chunk. Must make sure + fixups doesn't cross chunk boundraries. ASSUMES sorted relocs. */ + uint32_t cChunkRelocs = cRelocs; + uint32_t cbChunk = cbVirtData; + uint32_t offEnd = off + cbChunk; + if (cbChunk > cbMaxData) + { + cbChunk = cbMaxData; + offEnd = off + cbChunk; + cChunkRelocs = 0; + + /* Quickly determin the reloc range. */ + while ( cChunkRelocs < cRelocs + && paRelocs[cChunkRelocs].r_offset < offEnd) + cChunkRelocs++; + + /* Ensure final reloc doesn't go beyond chunk. */ + while ( cChunkRelocs > 0 + && paRelocs[cChunkRelocs - 1].r_offset + + ELF_AMD64_RELOC_SIZE(ELF64_R_TYPE(paRelocs[cChunkRelocs - 1].r_info)) + > offEnd) + { + uint32_t cbDrop = offEnd - paRelocs[cChunkRelocs - 1].r_offset; + cbChunk -= cbDrop; + offEnd -= cbDrop; + cChunkRelocs--; + } + + if (!cbVirtData) + return error(pThis->pszSrc, "Wtf? cbVirtData is zero!\n"); + } + if (g_cVerbose >= 2) + printf("debug: LEDATA off=%#x cb=%#x cRelocs=%#x sect=#%u segdef=%#x grpdef=%#x '%s'\n", + off, cbChunk, cRelocs, i, pThis->paSegments[i].iSegDef, pThis->paSegments[i].iGrpDef, pszSegNm); + + /* + * We stash the bytes into the OMF writer record buffer, receiving a + * pointer to the start of it so we can make adjustments if necessary. + */ + uint8_t *pbCopy; + if (!omfWriter_LEDataBeginEx(pThis, pThis->paSegments[i].iSegDef, off, cbChunk, cbData, pbData, &pbCopy)) + return false; + + /* + * Convert fiuxps. + */ + for (uint32_t iReloc = 0; iReloc < cChunkRelocs; iReloc++) + { + /* Get the OMF and ELF data for the symbol the reloc references. */ + uint32_t const uType = ELF64_R_TYPE(paRelocs[iReloc].r_info); + uint32_t const iSymbol = ELF64_R_SYM(paRelocs[iReloc].r_info); + Elf64_Sym const * const pElfSym = &paSymbols[iSymbol]; + POMFSYMBOL const pOmfSym = &pThis->paSymbols[iSymbol]; + const char * const pszSymName = &pElfStuff->pchStrTab[pElfSym->st_name]; + + /* Calc fixup location in the pending chunk and setup a flexible pointer to it. */ + uint16_t offDataRec = (uint16_t)(paRelocs[iReloc].r_offset - off); + RTPTRUNION uLoc; + uLoc.pu8 = &pbCopy[offDataRec]; + + /* OMF fixup data initialized with typical defaults. */ + bool fSelfRel = true; + uint8_t bLocation = OMF_FIX_LOC_32BIT_OFFSET; + uint8_t bFrame = OMF_FIX_F_GRPDEF; + uint16_t idxFrame = pThis->idxGrpFlat; + uint8_t bTarget; + uint16_t idxTarget; + bool fTargetDisp; + uint32_t offTargetDisp; + switch (pOmfSym->enmType) + { + case OMFSYMTYPE_INTERNAL: + case OMFSYMTYPE_PUBDEF: + bTarget = OMF_FIX_T_SEGDEF; + idxTarget = pOmfSym->idxSegDef; + fTargetDisp = true; + offTargetDisp = pElfSym->st_value; + break; + + case OMFSYMTYPE_SEGDEF: + bTarget = OMF_FIX_T_SEGDEF_NO_DISP; + idxTarget = pOmfSym->idxSegDef; + fTargetDisp = false; + offTargetDisp = 0; + break; + + case OMFSYMTYPE_EXTDEF: + bTarget = OMF_FIX_T_EXTDEF_NO_DISP; + idxTarget = pOmfSym->idx; + fTargetDisp = false; + offTargetDisp = 0; + break; + + default: + return error(pThis->pszSrc, "Relocation in segment #%u '%s' references ignored or invalid symbol (%s)\n", + i, pszSegNm, pszSymName); + } + + /* Do COFF relocation type conversion. */ + switch (uType) + { + case R_X86_64_64: + { + int64_t iAddend = paRelocs[iReloc].r_addend; + if (iAddend > _1G || iAddend < -_1G) + fRet = error(pThis->pszSrc, "R_X86_64_64 with large addend (%" ELF_FMT_D64 ") at %#x in segment #%u '%s'\n", + iAddend, paRelocs[iReloc].r_offset, i, pszSegNm); + *uLoc.pu64 = iAddend; + fSelfRel = false; + break; + } + + case R_X86_64_32: + case R_X86_64_32S: /* signed, unsigned, whatever. */ + fSelfRel = false; + RT_FALL_THRU(); + case R_X86_64_PC32: + case R_X86_64_PLT32: /* binutils commit 451875b4f976a527395e9303224c7881b65e12ed feature/regression. */ + { + /* defaults are ok, just handle the addend. */ + int32_t iAddend = paRelocs[iReloc].r_addend; + if (iAddend != paRelocs[iReloc].r_addend) + fRet = error(pThis->pszSrc, "R_X86_64_PC32 with large addend (%d) at %#x in segment #%u '%s'\n", + iAddend, paRelocs[iReloc].r_offset, i, pszSegNm); + if (fSelfRel) + *uLoc.pu32 = iAddend + 4; + else + *uLoc.pu32 = iAddend; + break; + } + + case R_X86_64_NONE: + continue; /* Ignore this one */ + + case R_X86_64_GOT32: + case R_X86_64_COPY: + case R_X86_64_GLOB_DAT: + case R_X86_64_JMP_SLOT: + case R_X86_64_RELATIVE: + case R_X86_64_GOTPCREL: + case R_X86_64_16: + case R_X86_64_PC16: + case R_X86_64_8: + case R_X86_64_PC8: + case R_X86_64_DTPMOD64: + case R_X86_64_DTPOFF64: + case R_X86_64_TPOFF64: + case R_X86_64_TLSGD: + case R_X86_64_TLSLD: + case R_X86_64_DTPOFF32: + case R_X86_64_GOTTPOFF: + case R_X86_64_TPOFF32: + default: + return error(pThis->pszSrc, "Unsupported fixup type %#x (%s) at rva=%#x in section #%u '%s' against '%s'\n", + uType, g_apszElfAmd64RelTypes[uType], paRelocs[iReloc].r_offset, i, pszSegNm, pszSymName); + } + + /* Add the fixup. */ + if (idxFrame == UINT16_MAX) + error(pThis->pszSrc, "idxFrame=UINT16_MAX for %s type=%s\n", pszSymName, g_apszElfAmd64RelTypes[uType]); + fRet = omfWriter_LEDataAddFixup(pThis, offDataRec, fSelfRel, bLocation, bFrame, idxFrame, + bTarget, idxTarget, fTargetDisp, offTargetDisp) && fRet; + } + + /* + * Write the LEDATA and associated FIXUPPs. + */ + if (!omfWriter_LEDataEnd(pThis)) + return false; + + /* + * Advance. + */ + paRelocs += cChunkRelocs; + cRelocs -= cChunkRelocs; + if (cbData > cbChunk) + { + cbData -= cbChunk; + pbData += cbChunk; + } + else + cbData = 0; + off += cbChunk; + cbVirtData -= cbChunk; + } + } + + return fRet; +} + + +static bool convertElfToOmf(const char *pszFile, uint8_t const *pbFile, size_t cbFile, FILE *pDst) +{ + /* + * Validate the source file a little. + */ + ELFDETAILS ElfStuff; + if (!validateElf(pszFile, pbFile, cbFile, &ElfStuff)) + return false; + + /* + * Instantiate the OMF writer. + */ + POMFWRITER pThis = omfWriter_Create(pszFile, ElfStuff.pEhdr->e_shnum, ElfStuff.cSymbols, pDst); + if (!pThis) + return false; + + /* + * Write the OMF object file. + */ + if (omfWriter_BeginModule(pThis, pszFile)) + { + if ( convertElfSectionsToSegDefsAndGrpDefs(pThis, &ElfStuff) + && convertElfSymbolsToPubDefsAndExtDefs(pThis, &ElfStuff) + && omfWriter_LinkPassSeparator(pThis) + && convertElfSectionsToLeDataAndFixupps(pThis, &ElfStuff, pbFile, cbFile) + && omfWriter_EndModule(pThis) ) + { + + omfWriter_Destroy(pThis); + return true; + } + } + + omfWriter_Destroy(pThis); + return false; +} + + + +/********************************************************************************************************************************* +* COFF -> OMF Converter * +*********************************************************************************************************************************/ + +/** AMD64 relocation type names for (Microsoft) COFF. */ +static const char * const g_apszCoffAmd64RelTypes[] = +{ + "ABSOLUTE", + "ADDR64", + "ADDR32", + "ADDR32NB", + "REL32", + "REL32_1", + "REL32_2", + "REL32_3", + "REL32_4", + "REL32_5", + "SECTION", + "SECREL", + "SECREL7", + "TOKEN", + "SREL32", + "PAIR", + "SSPAN32" +}; + +/** AMD64 relocation type sizes for (Microsoft) COFF. */ +static uint8_t const g_acbCoffAmd64RelTypes[] = +{ + 8, /* ABSOLUTE */ + 8, /* ADDR64 */ + 4, /* ADDR32 */ + 4, /* ADDR32NB */ + 4, /* REL32 */ + 4, /* REL32_1 */ + 4, /* REL32_2 */ + 4, /* REL32_3 */ + 4, /* REL32_4 */ + 4, /* REL32_5 */ + 2, /* SECTION */ + 4, /* SECREL */ + 1, /* SECREL7 */ + 0, /* TOKEN */ + 4, /* SREL32 */ + 0, /* PAIR */ + 4, /* SSPAN32 */ +}; + +/** Macro for getting the size of a AMD64 COFF relocation. */ +#define COFF_AMD64_RELOC_SIZE(a_Type) ( (a_Type) < RT_ELEMENTS(g_acbCoffAmd64RelTypes) ? g_acbCoffAmd64RelTypes[(a_Type)] : 1) + + +static const char *coffGetSymbolName(PCIMAGE_SYMBOL pSym, const char *pchStrTab, uint32_t cbStrTab, char pszShortName[16]) +{ + if (pSym->N.Name.Short != 0) + { + memcpy(pszShortName, pSym->N.ShortName, 8); + pszShortName[8] = '\0'; + return pszShortName; + } + if (pSym->N.Name.Long < cbStrTab) + { + uint32_t const cbLeft = cbStrTab - pSym->N.Name.Long; + const char *pszRet = pchStrTab + pSym->N.Name.Long; + if (memchr(pszRet, '\0', cbLeft) != NULL) + return pszRet; + } + error("<null>", "Invalid string table index %#x!\n", pSym->N.Name.Long); + return "Invalid Symbol Table Entry"; +} + +static bool validateCoff(const char *pszFile, uint8_t const *pbFile, size_t cbFile) +{ + /* + * Validate the header and our other expectations. + */ + PIMAGE_FILE_HEADER pHdr = (PIMAGE_FILE_HEADER)pbFile; + if (pHdr->Machine != IMAGE_FILE_MACHINE_AMD64) + return error(pszFile, "Expected IMAGE_FILE_MACHINE_AMD64 not %#x\n", pHdr->Machine); + if (pHdr->SizeOfOptionalHeader != 0) + return error(pszFile, "Expected SizeOfOptionalHeader to be zero, not %#x\n", pHdr->SizeOfOptionalHeader); + if (pHdr->NumberOfSections == 0) + return error(pszFile, "Expected NumberOfSections to be non-zero\n"); + uint32_t const cbHeaders = pHdr->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) + sizeof(*pHdr); + if (cbHeaders > cbFile) + return error(pszFile, "Section table goes beyond the end of the of the file (cSections=%#x)\n", pHdr->NumberOfSections); + if (pHdr->NumberOfSymbols) + { + if ( pHdr->PointerToSymbolTable >= cbFile + || pHdr->NumberOfSymbols * (uint64_t)IMAGE_SIZE_OF_SYMBOL > cbFile) + return error(pszFile, "Symbol table goes beyond the end of the of the file (cSyms=%#x, offFile=%#x)\n", + pHdr->NumberOfSymbols, pHdr->PointerToSymbolTable); + } + + return true; +} + + +static bool convertCoffSectionsToSegDefsAndGrpDefs(POMFWRITER pThis, PCIMAGE_SECTION_HEADER paShdrs, uint16_t cSections) +{ + /* + * Do the list of names pass. + */ + uint16_t idxGrpFlat, idxGrpData; + uint16_t idxClassCode, idxClassData, idxClassDebugSymbols, idxClassDebugTypes; + if ( !omfWriter_LNamesBegin(pThis, true /*fAddZeroEntry*/) + || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("FLAT"), &idxGrpFlat) + || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("BS3DATA64_GROUP"), &idxGrpData) + || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("BS3CLASS64CODE"), &idxClassCode) + || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("FAR_DATA"), &idxClassData) + || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("DEBSYM"), &idxClassDebugSymbols) + || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("DEBTYP"), &idxClassDebugTypes) + ) + return false; + + bool fHaveData = false; + for (uint16_t i = 0; i < cSections; i++) + { + /* Copy the name and terminate it. */ + char szName[32]; + memcpy(szName, paShdrs[i].Name, sizeof(paShdrs[i].Name)); + unsigned cchName = sizeof(paShdrs[i].Name); + while (cchName > 0 && RT_C_IS_SPACE(szName[cchName - 1])) + cchName--; + if (cchName == 0) + return error(pThis->pszSrc, "Section #%u has an empty name!\n", i); + szName[cchName] = '\0'; + + if ( (paShdrs[i].Characteristics & (IMAGE_SCN_LNK_REMOVE | IMAGE_SCN_LNK_INFO)) + || strcmp(szName, ".pdata") == 0 /* Exception stuff, I think, so discard it. */ + || strcmp(szName, ".xdata") == 0 /* Ditto. */ ) + { + pThis->paSegments[i].iSegDef = UINT16_MAX; + pThis->paSegments[i].iGrpDef = UINT16_MAX; + pThis->paSegments[i].iSegNm = UINT16_MAX; + pThis->paSegments[i].iGrpNm = UINT16_MAX; + pThis->paSegments[i].iClassNm = UINT16_MAX; + pThis->paSegments[i].pszName = NULL; + } + else + { + /* Translate the name, group and class. */ + if ( strcmp(szName, ".text") == 0 + || strcmp(szName, ".text$mn") == 0 /* Seen first in VC++ 14.1 (could be older). */) + { + strcpy(szName, "BS3TEXT64"); + pThis->paSegments[i].iGrpNm = idxGrpFlat; + pThis->paSegments[i].iClassNm = idxClassCode; + } + else if (strcmp(szName, ".data") == 0) + { + strcpy(szName, "BS3DATA64"); + pThis->paSegments[i].iGrpNm = idxGrpData; + pThis->paSegments[i].iClassNm = idxClassData; + } + else if (strcmp(szName, ".bss") == 0) + { + strcpy(szName, "BS3BSS64"); + pThis->paSegments[i].iGrpNm = idxGrpData; + pThis->paSegments[i].iClassNm = idxClassData; + } + else if (strcmp(szName, ".rdata") == 0) + { + strcpy(szName, "BS3DATA64CONST"); + pThis->paSegments[i].iGrpNm = idxGrpData; + pThis->paSegments[i].iClassNm = idxClassData; + } + else if (strcmp(szName, ".debug$S") == 0) + { + strcpy(szName, "$$SYMBOLS"); + pThis->paSegments[i].iGrpNm = UINT16_MAX; + pThis->paSegments[i].iClassNm = idxClassDebugSymbols; + } + else if (strcmp(szName, ".debug$T") == 0) + { + strcpy(szName, "$$TYPES"); + pThis->paSegments[i].iGrpNm = UINT16_MAX; + pThis->paSegments[i].iClassNm = idxClassDebugTypes; + } + else if (paShdrs[i].Characteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE)) + { + pThis->paSegments[i].iGrpNm = idxGrpFlat; + pThis->paSegments[i].iClassNm = idxClassCode; + error(pThis->pszSrc, "Unknown code segment: '%s'\n", szName); + } + else + { + pThis->paSegments[i].iGrpNm = idxGrpData; + pThis->paSegments[i].iClassNm = idxClassData; + error(pThis->pszSrc, "Unknown data (?) segment: '%s'\n", szName); + } + + /* Save the name. */ + pThis->paSegments[i].pszName = strdup(szName); + if (!pThis->paSegments[i].pszName) + return error(pThis->pszSrc, "Out of memory!\n"); + + /* Add the section name. */ + if (!omfWriter_LNamesAdd(pThis, pThis->paSegments[i].pszName, &pThis->paSegments[i].iSegNm)) + return false; + + fHaveData |= pThis->paSegments[i].iGrpNm == idxGrpData; + } + } + + if (!omfWriter_LNamesEnd(pThis)) + return false; + + /* + * Emit segment definitions. + */ + uint16_t iSegDef = 1; /* Start counting at 1. */ + for (uint16_t i = 0; i < cSections; i++) + { + if (pThis->paSegments[i].iSegDef == UINT16_MAX) + continue; + + uint8_t bSegAttr = 0; + + /* The A field. */ + switch (paShdrs[i].Characteristics & IMAGE_SCN_ALIGN_MASK) + { + default: + case IMAGE_SCN_ALIGN_1BYTES: + bSegAttr |= 1 << 5; + break; + case IMAGE_SCN_ALIGN_2BYTES: + bSegAttr |= 2 << 5; + break; + case IMAGE_SCN_ALIGN_4BYTES: + bSegAttr |= 5 << 5; + break; + case IMAGE_SCN_ALIGN_8BYTES: + case IMAGE_SCN_ALIGN_16BYTES: + bSegAttr |= 3 << 5; + break; + case IMAGE_SCN_ALIGN_32BYTES: + case IMAGE_SCN_ALIGN_64BYTES: + case IMAGE_SCN_ALIGN_128BYTES: + case IMAGE_SCN_ALIGN_256BYTES: + bSegAttr |= 4 << 5; + break; + case IMAGE_SCN_ALIGN_512BYTES: + case IMAGE_SCN_ALIGN_1024BYTES: + case IMAGE_SCN_ALIGN_2048BYTES: + case IMAGE_SCN_ALIGN_4096BYTES: + case IMAGE_SCN_ALIGN_8192BYTES: + bSegAttr |= 6 << 5; /* page aligned, pharlabs extension. */ + break; + } + + /* The C field. */ + bSegAttr |= 2 << 2; /* public */ + + /* The B field. We don't have 4GB segments, so leave it as zero. */ + + /* The D field shall be set as we're doing USE32. */ + bSegAttr |= 1; + + + /* Done. */ + if (!omfWriter_SegDef(pThis, bSegAttr, paShdrs[i].SizeOfRawData, + pThis->paSegments[i].iSegNm, + pThis->paSegments[i].iClassNm)) + return false; + pThis->paSegments[i].iSegDef = iSegDef++; + } + + /* + * Flat group definition (#1) - special, no members. + */ + uint16_t iGrpDef = 1; + if ( !omfWriter_GrpDefBegin(pThis, idxGrpFlat) + || !omfWriter_GrpDefEnd(pThis)) + return false; + for (uint16_t i = 0; i < cSections; i++) + if (pThis->paSegments[i].iGrpNm == idxGrpFlat) + pThis->paSegments[i].iGrpDef = iGrpDef; + pThis->idxGrpFlat = iGrpDef++; + + /* + * Data group definition (#2). + */ + /** @todo do we need to consider missing segments and ordering? */ + uint16_t cGrpNms = 0; + uint16_t aiGrpNms[2] = { 0, 0 }; /* Shut up, GCC. */ + if (fHaveData) + aiGrpNms[cGrpNms++] = idxGrpData; + for (uint32_t iGrpNm = 0; iGrpNm < cGrpNms; iGrpNm++) + { + if (!omfWriter_GrpDefBegin(pThis, aiGrpNms[iGrpNm])) + return false; + for (uint16_t i = 0; i < cSections; i++) + if (pThis->paSegments[i].iGrpNm == aiGrpNms[iGrpNm]) + { + pThis->paSegments[i].iGrpDef = iGrpDef; + if (!omfWriter_GrpDefAddSegDef(pThis, pThis->paSegments[i].iSegDef)) + return false; + } + if (!omfWriter_GrpDefEnd(pThis)) + return false; + iGrpDef++; + } + + return true; +} + +/** + * This is for matching STATIC symbols with value 0 against the section name, + * to see if it's a section reference or symbol at offset 0 reference. + * + * @returns true / false. + * @param pszSymbol The symbol name. + * @param pachSectName8 The section name (8-bytes). + */ +static bool isCoffSymbolMatchingSectionName(const char *pszSymbol, uint8_t const pachSectName8[8]) +{ + uint32_t off = 0; + char ch; + while (off < 8 && (ch = pszSymbol[off]) != '\0') + { + if (ch != pachSectName8[off]) + return false; + off++; + } + while (off < 8) + { + if (!RT_C_IS_SPACE((ch = pachSectName8[off]))) + return ch == '\0'; + off++; + } + return true; +} + +static bool convertCoffSymbolsToPubDefsAndExtDefs(POMFWRITER pThis, PCIMAGE_SYMBOL paSymbols, uint16_t cSymbols, + const char *pchStrTab, PCIMAGE_SECTION_HEADER paShdrs) +{ + + if (!cSymbols) + return true; + uint32_t const cbStrTab = *(uint32_t const *)pchStrTab; + char szShort[16]; + + /* + * Process the symbols the first. + */ + uint32_t iSymImageBase = UINT32_MAX; + uint32_t cAbsSyms = 0; + uint32_t cExtSyms = 0; + uint32_t cPubSyms = 0; + for (uint32_t iSeg = 0; iSeg < pThis->cSegments; iSeg++) + pThis->paSegments[iSeg].cPubDefs = 0; + + for (uint16_t iSym = 0; iSym < cSymbols; iSym++) + { + const char *pszSymName = coffGetSymbolName(&paSymbols[iSym], pchStrTab, cbStrTab, szShort); + + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_IGNORED; + pThis->paSymbols[iSym].idx = UINT16_MAX; + pThis->paSymbols[iSym].idxSegDef = UINT16_MAX; + pThis->paSymbols[iSym].idxGrpDef = UINT16_MAX; + + int16_t const idxSection = paSymbols[iSym].SectionNumber; + if ( (idxSection >= 1 && idxSection <= (int32_t)pThis->cSegments) + || idxSection == IMAGE_SYM_ABSOLUTE) + { + switch (paSymbols[iSym].StorageClass) + { + case IMAGE_SYM_CLASS_EXTERNAL: + if (idxSection != IMAGE_SYM_ABSOLUTE) + { + if (pThis->paSegments[idxSection - 1].iSegDef != UINT16_MAX) + { + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_PUBDEF; + pThis->paSymbols[iSym].idxSegDef = pThis->paSegments[idxSection - 1].iSegDef; + pThis->paSymbols[iSym].idxGrpDef = pThis->paSegments[idxSection - 1].iGrpDef; + pThis->paSegments[idxSection - 1].cPubDefs++; + cPubSyms++; + } + } + else + { + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_PUBDEF; + pThis->paSymbols[iSym].idxSegDef = 0; + pThis->paSymbols[iSym].idxGrpDef = 0; + cAbsSyms++; + } + break; + + case IMAGE_SYM_CLASS_STATIC: + if ( paSymbols[iSym].Value == 0 + && idxSection != IMAGE_SYM_ABSOLUTE + && isCoffSymbolMatchingSectionName(pszSymName, paShdrs[idxSection - 1].Name) ) + { + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_SEGDEF; + pThis->paSymbols[iSym].idxSegDef = pThis->paSegments[idxSection - 1].iSegDef; + pThis->paSymbols[iSym].idxGrpDef = pThis->paSegments[idxSection - 1].iGrpDef; + break; + } + RT_FALL_THRU(); + + case IMAGE_SYM_CLASS_END_OF_FUNCTION: + case IMAGE_SYM_CLASS_AUTOMATIC: + case IMAGE_SYM_CLASS_REGISTER: + case IMAGE_SYM_CLASS_LABEL: + case IMAGE_SYM_CLASS_MEMBER_OF_STRUCT: + case IMAGE_SYM_CLASS_ARGUMENT: + case IMAGE_SYM_CLASS_STRUCT_TAG: + case IMAGE_SYM_CLASS_MEMBER_OF_UNION: + case IMAGE_SYM_CLASS_UNION_TAG: + case IMAGE_SYM_CLASS_TYPE_DEFINITION: + case IMAGE_SYM_CLASS_ENUM_TAG: + case IMAGE_SYM_CLASS_MEMBER_OF_ENUM: + case IMAGE_SYM_CLASS_REGISTER_PARAM: + case IMAGE_SYM_CLASS_BIT_FIELD: + case IMAGE_SYM_CLASS_BLOCK: + case IMAGE_SYM_CLASS_FUNCTION: + case IMAGE_SYM_CLASS_END_OF_STRUCT: + case IMAGE_SYM_CLASS_FILE: + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_INTERNAL; + if (idxSection != IMAGE_SYM_ABSOLUTE) + { + pThis->paSymbols[iSym].idxSegDef = pThis->paSegments[idxSection - 1].iSegDef; + pThis->paSymbols[iSym].idxGrpDef = pThis->paSegments[idxSection - 1].iGrpDef; + } + else + { + pThis->paSymbols[iSym].idxSegDef = 0; + pThis->paSymbols[iSym].idxGrpDef = 0; + } + break; + + case IMAGE_SYM_CLASS_SECTION: + case IMAGE_SYM_CLASS_EXTERNAL_DEF: + case IMAGE_SYM_CLASS_NULL: + case IMAGE_SYM_CLASS_UNDEFINED_LABEL: + case IMAGE_SYM_CLASS_UNDEFINED_STATIC: + case IMAGE_SYM_CLASS_CLR_TOKEN: + case IMAGE_SYM_CLASS_FAR_EXTERNAL: + case IMAGE_SYM_CLASS_WEAK_EXTERNAL: + return error(pThis->pszSrc, "Unsupported storage class value %#x for symbol #%u (%s)\n", + paSymbols[iSym].StorageClass, iSym, pszSymName); + + default: + return error(pThis->pszSrc, "Unknown storage class value %#x for symbol #%u (%s)\n", + paSymbols[iSym].StorageClass, iSym, pszSymName); + } + } + else if (idxSection == IMAGE_SYM_UNDEFINED) + { + if ( paSymbols[iSym].StorageClass == IMAGE_SYM_CLASS_EXTERNAL + || paSymbols[iSym].StorageClass == IMAGE_SYM_CLASS_EXTERNAL_DEF) + { + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_EXTDEF; + cExtSyms++; + if (iSymImageBase == UINT32_MAX && strcmp(pszSymName, "__ImageBase") == 0) + iSymImageBase = iSym; + } + else + return error(pThis->pszSrc, "Unknown/unknown storage class value %#x for undefined symbol #%u (%s)\n", + paSymbols[iSym].StorageClass, iSym, pszSymName); + } + else if (idxSection != IMAGE_SYM_DEBUG) + return error(pThis->pszSrc, "Invalid section number %#x for symbol #%u (%s)\n", idxSection, iSym, pszSymName); + + /* Skip AUX symbols. */ + uint8_t cAuxSyms = paSymbols[iSym].NumberOfAuxSymbols; + while (cAuxSyms-- > 0) + { + iSym++; + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_INVALID; + pThis->paSymbols[iSym].idx = UINT16_MAX; + } + } + + /* + * Emit the PUBDEFs the first time around (see order of records in TIS spec). + */ + uint16_t idxPubDef = 1; + if (cPubSyms) + { + for (uint32_t iSeg = 0; iSeg < pThis->cSegments; iSeg++) + if (pThis->paSegments[iSeg].cPubDefs > 0) + { + uint16_t const idxSegDef = pThis->paSegments[iSeg].iSegDef; + if (!omfWriter_PubDefBegin(pThis, pThis->paSegments[iSeg].iGrpDef, idxSegDef)) + return false; + for (uint16_t iSym = 0; iSym < cSymbols; iSym++) + if ( pThis->paSymbols[iSym].idxSegDef == idxSegDef + && pThis->paSymbols[iSym].enmType == OMFSYMTYPE_PUBDEF) + { + /* Underscore prefix all symbols not already underscored or mangled. */ + const char *pszName = coffGetSymbolName(&paSymbols[iSym], pchStrTab, cbStrTab, szShort); + if (!omfWriter_PubDefAdd(pThis, paSymbols[iSym].Value, pszName, pszName[0] != '_' && pszName[0] != '?')) + return false; + pThis->paSymbols[iSym].idx = idxPubDef++; + } + if (!omfWriter_PubDefEnd(pThis)) + return false; + } + } + + if (cAbsSyms > 0) + { + if (!omfWriter_PubDefBegin(pThis, 0, 0)) + return false; + for (uint16_t iSym = 0; iSym < cSymbols; iSym++) + if ( pThis->paSymbols[iSym].idxSegDef == 0 + && pThis->paSymbols[iSym].enmType == OMFSYMTYPE_PUBDEF) + { + /* Underscore prefix all symbols not already underscored or mangled. */ + const char *pszName = coffGetSymbolName(&paSymbols[iSym], pchStrTab, cbStrTab, szShort); + if (!omfWriter_PubDefAdd(pThis, paSymbols[iSym].Value, pszName, pszName[0] != '_' && pszName[0] != '?') ) + return false; + pThis->paSymbols[iSym].idx = idxPubDef++; + } + if (!omfWriter_PubDefEnd(pThis)) + return false; + } + + /* + * Go over the symbol table and emit external definition records. + */ + if (!omfWriter_ExtDefBegin(pThis)) + return false; + uint16_t idxExtDef = 1; + for (uint16_t iSym = 0; iSym < cSymbols; iSym++) + if (pThis->paSymbols[iSym].enmType == OMFSYMTYPE_EXTDEF) + { + /* Underscore prefix all symbols not already underscored or mangled. */ + const char *pszName = coffGetSymbolName(&paSymbols[iSym], pchStrTab, cbStrTab, szShort); + if (!omfWriter_ExtDefAdd(pThis, pszName, pszName[0] != '_' && pszName[0] != '?')) + return false; + pThis->paSymbols[iSym].idx = idxExtDef++; + } + + /* Always add an __ImageBase reference, in case we need it to deal with ADDR32NB fixups. */ + /** @todo maybe we don't actually need this and could use FLAT instead? */ + if (iSymImageBase != UINT32_MAX) + pThis->idxExtImageBase = pThis->paSymbols[iSymImageBase].idx; + else if (omfWriter_ExtDefAdd(pThis, "__ImageBase", false /*fPrependUnderscore*/)) + pThis->idxExtImageBase = idxExtDef; + else + return false; + + if (!omfWriter_ExtDefEnd(pThis)) + return false; + + return true; +} + + +static bool convertCoffSectionsToLeDataAndFixupps(POMFWRITER pThis, uint8_t const *pbFile, size_t cbFile, + PCIMAGE_SECTION_HEADER paShdrs, uint16_t cSections, + PCIMAGE_SYMBOL paSymbols, uint16_t cSymbols, const char *pchStrTab) +{ + RT_NOREF_PV(cbFile); + RT_NOREF_PV(cSections); + RT_NOREF_PV(cSymbols); + + uint32_t const cbStrTab = *(uint32_t const *)pchStrTab; + bool fRet = true; + for (uint32_t i = 0; i < pThis->cSegments; i++) + { + if (pThis->paSegments[i].iSegDef == UINT16_MAX) + continue; + + char szShortName[16]; + const char *pszSegNm = pThis->paSegments[i].pszName; + uint16_t cRelocs = paShdrs[i].NumberOfRelocations; + PCIMAGE_RELOCATION paRelocs = (PCIMAGE_RELOCATION)&pbFile[paShdrs[i].PointerToRelocations]; + uint32_t cbVirtData = paShdrs[i].SizeOfRawData; + uint32_t cbData = paShdrs[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ? 0 : cbVirtData; + uint8_t const *pbData = &pbFile[paShdrs[i].PointerToRawData]; + uint32_t off = 0; + + /* Check that the relocations are sorted and within the section. */ + for (uint32_t iReloc = 1; iReloc < cRelocs; iReloc++) + if (paRelocs[iReloc - 1].u.VirtualAddress >= paRelocs[iReloc].u.VirtualAddress) + return error(pThis->pszSrc, "Section #%u (%s) relocations aren't sorted\n", i, pszSegNm); + if ( cRelocs > 0 + && paRelocs[cRelocs - 1].u.VirtualAddress - paShdrs[i].VirtualAddress + + COFF_AMD64_RELOC_SIZE(paRelocs[cRelocs - 1].Type) > cbVirtData) + return error(pThis->pszSrc, + "Section #%u (%s) relocations beyond section data! cbVirtData=%#x RvaFix=%#x RVASeg=%#x type=%#x\n", + i, pszSegNm, cbVirtData, paRelocs[cRelocs - 1].u.VirtualAddress, paShdrs[i].VirtualAddress, + paRelocs[cRelocs - 1].Type); + + /* The OMF record size requires us to split larger sections up. To make + life simple, we fill zeros for unitialized (BSS) stuff. */ + const uint32_t cbMaxData = RT_MIN(OMF_MAX_RECORD_PAYLOAD - 1 - (pThis->paSegments[i].iSegDef >= 128) - 4 - 1, _1K); + while (cbVirtData > 0) + { + /* Figure out how many bytes to put out in this chunk. Must make sure + fixups doesn't cross chunk boundraries. ASSUMES sorted relocs. */ + uint32_t cChunkRelocs = cRelocs; + uint32_t cbChunk = cbVirtData; + uint32_t uRvaEnd = paShdrs[i].VirtualAddress + off + cbChunk; + if (cbChunk > cbMaxData) + { + cbChunk = cbMaxData; + uRvaEnd = paShdrs[i].VirtualAddress + off + cbChunk; + cChunkRelocs = 0; + + /* Quickly determin the reloc range. */ + while ( cChunkRelocs < cRelocs + && paRelocs[cChunkRelocs].u.VirtualAddress < uRvaEnd) + cChunkRelocs++; + + /* Ensure final reloc doesn't go beyond chunk. */ + while ( cChunkRelocs > 0 + && paRelocs[cChunkRelocs - 1].u.VirtualAddress + COFF_AMD64_RELOC_SIZE(paRelocs[cChunkRelocs - 1].Type) + > uRvaEnd) + { + uint32_t cbDrop = uRvaEnd - paRelocs[cChunkRelocs - 1].u.VirtualAddress; + cbChunk -= cbDrop; + uRvaEnd -= cbDrop; + cChunkRelocs--; + } + + if (!cbVirtData) + return error(pThis->pszSrc, "Wtf? cbVirtData is zero!\n"); + } + + /* + * We stash the bytes into the OMF writer record buffer, receiving a + * pointer to the start of it so we can make adjustments if necessary. + */ + uint8_t *pbCopy; + if (!omfWriter_LEDataBeginEx(pThis, pThis->paSegments[i].iSegDef, off, cbChunk, cbData, pbData, &pbCopy)) + return false; + + /* + * Convert fiuxps. + */ + uint32_t const uRvaChunk = paShdrs[i].VirtualAddress + off; + for (uint32_t iReloc = 0; iReloc < cChunkRelocs; iReloc++) + { + /* Get the OMF and COFF data for the symbol the reloc references. */ + if (paRelocs[iReloc].SymbolTableIndex >= pThis->cSymbols) + return error(pThis->pszSrc, "Relocation symtab index (%#x) is out of range in segment #%u '%s'\n", + paRelocs[iReloc].SymbolTableIndex, i, pszSegNm); + PCIMAGE_SYMBOL pCoffSym = &paSymbols[paRelocs[iReloc].SymbolTableIndex]; + POMFSYMBOL pOmfSym = &pThis->paSymbols[paRelocs[iReloc].SymbolTableIndex]; + + /* Calc fixup location in the pending chunk and setup a flexible pointer to it. */ + uint16_t offDataRec = (uint16_t)(paRelocs[iReloc].u.VirtualAddress - uRvaChunk); + RTPTRUNION uLoc; + uLoc.pu8 = &pbCopy[offDataRec]; + + /* OMF fixup data initialized with typical defaults. */ + bool fSelfRel = true; + uint8_t bLocation = OMF_FIX_LOC_32BIT_OFFSET; + uint8_t bFrame = OMF_FIX_F_GRPDEF; + uint16_t idxFrame = pThis->idxGrpFlat; + uint8_t bTarget; + uint16_t idxTarget; + bool fTargetDisp; + uint32_t offTargetDisp; + switch (pOmfSym->enmType) + { + case OMFSYMTYPE_INTERNAL: + case OMFSYMTYPE_PUBDEF: + bTarget = OMF_FIX_T_SEGDEF; + idxTarget = pOmfSym->idxSegDef; + fTargetDisp = true; + offTargetDisp = pCoffSym->Value; + break; + + case OMFSYMTYPE_SEGDEF: + bTarget = OMF_FIX_T_SEGDEF_NO_DISP; + idxTarget = pOmfSym->idxSegDef; + fTargetDisp = false; + offTargetDisp = 0; + break; + + case OMFSYMTYPE_EXTDEF: + bTarget = OMF_FIX_T_EXTDEF_NO_DISP; + idxTarget = pOmfSym->idx; + fTargetDisp = false; + offTargetDisp = 0; + break; + + default: + return error(pThis->pszSrc, "Relocation in segment #%u '%s' references ignored or invalid symbol (%s)\n", + i, pszSegNm, coffGetSymbolName(pCoffSym, pchStrTab, cbStrTab, szShortName)); + } + + /* Do COFF relocation type conversion. */ + switch (paRelocs[iReloc].Type) + { + case IMAGE_REL_AMD64_ADDR64: + { + uint64_t uAddend = *uLoc.pu64; + if (uAddend > _1G) + fRet = error(pThis->pszSrc, "ADDR64 with large addend (%#llx) at %#x in segment #%u '%s'\n", + uAddend, paRelocs[iReloc].u.VirtualAddress, i, pszSegNm); + fSelfRel = false; + break; + } + + case IMAGE_REL_AMD64_REL32_1: + case IMAGE_REL_AMD64_REL32_2: + case IMAGE_REL_AMD64_REL32_3: + case IMAGE_REL_AMD64_REL32_4: + case IMAGE_REL_AMD64_REL32_5: + /** @todo Check whether OMF read addends from the data or relies on the + * displacement. Also, check what it's relative to. */ + *uLoc.pu32 -= paRelocs[iReloc].Type - IMAGE_REL_AMD64_REL32; + break; + + case IMAGE_REL_AMD64_ADDR32: + fSelfRel = false; + break; + + case IMAGE_REL_AMD64_ADDR32NB: + fSelfRel = false; + bFrame = OMF_FIX_F_EXTDEF; + idxFrame = pThis->idxExtImageBase; + break; + + case IMAGE_REL_AMD64_REL32: + /* defaults are ok. */ + break; + + case IMAGE_REL_AMD64_SECTION: + bLocation = OMF_FIX_LOC_16BIT_SEGMENT; + RT_FALL_THRU(); + + case IMAGE_REL_AMD64_SECREL: + fSelfRel = false; + if (pOmfSym->enmType == OMFSYMTYPE_EXTDEF) + { + bFrame = OMF_FIX_F_EXTDEF; + idxFrame = pOmfSym->idx; + } + else + { + bFrame = OMF_FIX_F_SEGDEF; + idxFrame = pOmfSym->idxSegDef; + } + break; + + case IMAGE_REL_AMD64_ABSOLUTE: + continue; /* Ignore it like the PECOFF.DOC says we should. */ + + case IMAGE_REL_AMD64_SECREL7: + default: + return error(pThis->pszSrc, "Unsupported fixup type %#x (%s) at rva=%#x in section #%u '%-8.8s'\n", + paRelocs[iReloc].Type, + paRelocs[iReloc].Type < RT_ELEMENTS(g_apszCoffAmd64RelTypes) + ? g_apszCoffAmd64RelTypes[paRelocs[iReloc].Type] : "unknown", + paRelocs[iReloc].u.VirtualAddress, i, paShdrs[i].Name); + } + + /* Add the fixup. */ + if (idxFrame == UINT16_MAX) + error(pThis->pszSrc, "idxFrame=UINT16_MAX for %s type=%s\n", + coffGetSymbolName(pCoffSym, pchStrTab, cbStrTab, szShortName), + g_apszCoffAmd64RelTypes[paRelocs[iReloc].Type]); + fRet = omfWriter_LEDataAddFixup(pThis, offDataRec, fSelfRel, bLocation, bFrame, idxFrame, + bTarget, idxTarget, fTargetDisp, offTargetDisp) && fRet; + } + + /* + * Write the LEDATA and associated FIXUPPs. + */ + if (!omfWriter_LEDataEnd(pThis)) + return false; + + /* + * Advance. + */ + paRelocs += cChunkRelocs; + cRelocs -= cChunkRelocs; + if (cbData > cbChunk) + { + cbData -= cbChunk; + pbData += cbChunk; + } + else + cbData = 0; + off += cbChunk; + cbVirtData -= cbChunk; + } + } + + return fRet; +} + + +static bool convertCoffToOmf(const char *pszFile, uint8_t const *pbFile, size_t cbFile, FILE *pDst) +{ + /* + * Validate the source file a little. + */ + if (!validateCoff(pszFile, pbFile, cbFile)) + return false; + + /* + * Instantiate the OMF writer. + */ + PIMAGE_FILE_HEADER pHdr = (PIMAGE_FILE_HEADER)pbFile; + POMFWRITER pThis = omfWriter_Create(pszFile, pHdr->NumberOfSections, pHdr->NumberOfSymbols, pDst); + if (!pThis) + return false; + + /* + * Write the OMF object file. + */ + if (omfWriter_BeginModule(pThis, pszFile)) + { + PCIMAGE_SECTION_HEADER paShdrs = (PCIMAGE_SECTION_HEADER)(pHdr + 1); + PCIMAGE_SYMBOL paSymTab = (PCIMAGE_SYMBOL)&pbFile[pHdr->PointerToSymbolTable]; + const char *pchStrTab = (const char *)&paSymTab[pHdr->NumberOfSymbols]; + if ( convertCoffSectionsToSegDefsAndGrpDefs(pThis, paShdrs, pHdr->NumberOfSections) + && convertCoffSymbolsToPubDefsAndExtDefs(pThis, paSymTab, pHdr->NumberOfSymbols, pchStrTab, paShdrs) + && omfWriter_LinkPassSeparator(pThis) + && convertCoffSectionsToLeDataAndFixupps(pThis, pbFile, cbFile, paShdrs, pHdr->NumberOfSections, + paSymTab, pHdr->NumberOfSymbols, pchStrTab) + && omfWriter_EndModule(pThis) ) + { + + omfWriter_Destroy(pThis); + return true; + } + } + + omfWriter_Destroy(pThis); + return false; +} + + +/********************************************************************************************************************************* +* Mach-O/AMD64 -> OMF/i386 Converter * +*********************************************************************************************************************************/ + +//#define MACHO_TO_OMF_CONVERSION +#ifdef MACHO_TO_OMF_CONVERSION + +/** AMD64 relocation type names for Mach-O. */ +static const char * const g_apszMachOAmd64RelTypes[] = +{ + "X86_64_RELOC_UNSIGNED", + "X86_64_RELOC_SIGNED", + "X86_64_RELOC_BRANCH", + "X86_64_RELOC_GOT_LOAD", + "X86_64_RELOC_GOT", + "X86_64_RELOC_SUBTRACTOR", + "X86_64_RELOC_SIGNED_1", + "X86_64_RELOC_SIGNED_2", + "X86_64_RELOC_SIGNED_4" +}; + +/** AMD64 relocation type sizes for Mach-O. */ +static uint8_t const g_acbMachOAmd64RelTypes[] = +{ + 8, /* X86_64_RELOC_UNSIGNED */ + 4, /* X86_64_RELOC_SIGNED */ + 4, /* X86_64_RELOC_BRANCH */ + 4, /* X86_64_RELOC_GOT_LOAD */ + 4, /* X86_64_RELOC_GOT */ + 8, /* X86_64_RELOC_SUBTRACTOR */ + 4, /* X86_64_RELOC_SIGNED_1 */ + 4, /* X86_64_RELOC_SIGNED_2 */ + 4, /* X86_64_RELOC_SIGNED_4 */ +}; + +/** Macro for getting the size of a AMD64 Mach-O relocation. */ +#define MACHO_AMD64_RELOC_SIZE(a_Type) ( (a_Type) < RT_ELEMENTS(g_acbMachOAmd64RelTypes) ? g_acbMachOAmd64RelTypes[(a_Type)] : 1) + + +typedef struct MACHODETAILS +{ + /** The ELF header. */ + Elf64_Ehdr const *pEhdr; + /** The section header table. */ + Elf64_Shdr const *paShdrs; + /** The string table for the section names. */ + const char *pchShStrTab; + + /** The symbol table section number. UINT16_MAX if not found. */ + uint16_t iSymSh; + /** The string table section number. UINT16_MAX if not found. */ + uint16_t iStrSh; + + /** The symbol table. */ + Elf64_Sym const *paSymbols; + /** The number of symbols in the symbol table. */ + uint32_t cSymbols; + + /** Pointer to the (symbol) string table if found. */ + const char *pchStrTab; + /** The string table size. */ + size_t cbStrTab; + +} MACHODETAILS; +typedef MACHODETAILS *PMACHODETAILS; +typedef MACHODETAILS const *PCMACHODETAILS; + + +static bool validateMacho(const char *pszFile, uint8_t const *pbFile, size_t cbFile, PMACHODETAILS pMachOStuff) +{ + /* + * Initialize the Mach-O details structure. + */ + memset(pMachOStuff, 0, sizeof(*pMachOStuff)); + pMachOStuff->iSymSh = UINT16_MAX; + pMachOStuff->iStrSh = UINT16_MAX; + + /* + * Validate the header and our other expectations. + */ + Elf64_Ehdr const *pEhdr = (Elf64_Ehdr const *)pbFile; + pMachOStuff->pEhdr = pEhdr; + if ( pEhdr->e_ident[EI_CLASS] != ELFCLASS64 + || pEhdr->e_ident[EI_DATA] != ELFDATA2LSB + || pEhdr->e_ehsize != sizeof(Elf64_Ehdr) + || pEhdr->e_shentsize != sizeof(Elf64_Shdr) + || pEhdr->e_version != EV_CURRENT ) + return error(pszFile, "Unsupported ELF config\n"); + if (pEhdr->e_type != ET_REL) + return error(pszFile, "Expected relocatable ELF file (e_type=%d)\n", pEhdr->e_type); + if (pEhdr->e_machine != EM_X86_64) + return error(pszFile, "Expected relocatable ELF file (e_type=%d)\n", pEhdr->e_machine); + if (pEhdr->e_phnum != 0) + return error(pszFile, "Expected e_phnum to be zero not %u\n", pEhdr->e_phnum); + if (pEhdr->e_shnum < 2) + return error(pszFile, "Expected e_shnum to be two or higher\n"); + if (pEhdr->e_shstrndx >= pEhdr->e_shnum || pEhdr->e_shstrndx == 0) + return error(pszFile, "Bad e_shstrndx=%u (e_shnum=%u)\n", pEhdr->e_shstrndx, pEhdr->e_shnum); + if ( pEhdr->e_shoff >= cbFile + || pEhdr->e_shoff + pEhdr->e_shnum * sizeof(Elf64_Shdr) > cbFile) + return error(pszFile, "Section table is outside the file (e_shoff=%#llx, e_shnum=%u, cbFile=%#llx)\n", + pEhdr->e_shstrndx, pEhdr->e_shnum, (uint64_t)cbFile); + + /* + * Locate the section name string table. + * We assume it's okay as we only reference it in verbose mode. + */ + Elf64_Shdr const *paShdrs = (Elf64_Shdr const *)&pbFile[pEhdr->e_shoff]; + pMachOStuff->paShdrs = paShdrs; + + Elf64_Xword const cbShStrTab = paShdrs[pEhdr->e_shstrndx].sh_size; + if ( paShdrs[pEhdr->e_shstrndx].sh_offset > cbFile + || cbShStrTab > cbFile + || paShdrs[pEhdr->e_shstrndx].sh_offset + cbShStrTab > cbFile) + return error(pszFile, + "Section string table is outside the file (sh_offset=%#" ELF_FMT_X64 " sh_size=%#" ELF_FMT_X64 " cbFile=%#" ELF_FMT_X64 ")\n", + paShdrs[pEhdr->e_shstrndx].sh_offset, paShdrs[pEhdr->e_shstrndx].sh_size, (Elf64_Xword)cbFile); + const char *pchShStrTab = (const char *)&pbFile[paShdrs[pEhdr->e_shstrndx].sh_offset]; + pMachOStuff->pchShStrTab = pchShStrTab; + + /* + * Work the section table. + */ + bool fRet = true; + for (uint32_t i = 1; i < pEhdr->e_shnum; i++) + { + if (paShdrs[i].sh_name >= cbShStrTab) + return error(pszFile, "Invalid sh_name value (%#x) for section #%u\n", paShdrs[i].sh_name, i); + const char *pszShNm = &pchShStrTab[paShdrs[i].sh_name]; + + if ( paShdrs[i].sh_offset > cbFile + || paShdrs[i].sh_size > cbFile + || paShdrs[i].sh_offset + paShdrs[i].sh_size > cbFile) + return error(pszFile, "Section #%u '%s' has data outside the file: %#" ELF_FMT_X64 " LB %#" ELF_FMT_X64 " (cbFile=%#" ELF_FMT_X64 ")\n", + i, pszShNm, paShdrs[i].sh_offset, paShdrs[i].sh_size, (Elf64_Xword)cbFile); + if (g_cVerbose) + printf("shdr[%u]: name=%#x '%s' type=%#x flags=%#" ELF_FMT_X64 " addr=%#" ELF_FMT_X64 " off=%#" ELF_FMT_X64 " size=%#" ELF_FMT_X64 "\n" + " link=%u info=%#x align=%#" ELF_FMT_X64 " entsize=%#" ELF_FMT_X64 "\n", + i, paShdrs[i].sh_name, pszShNm, paShdrs[i].sh_type, paShdrs[i].sh_flags, + paShdrs[i].sh_addr, paShdrs[i].sh_offset, paShdrs[i].sh_size, + paShdrs[i].sh_link, paShdrs[i].sh_info, paShdrs[i].sh_addralign, paShdrs[i].sh_entsize); + + if (paShdrs[i].sh_link >= pEhdr->e_shnum) + return error(pszFile, "Section #%u '%s' links to a section outside the section table: %#x, max %#x\n", + i, pszShNm, paShdrs[i].sh_link, pEhdr->e_shnum); + if (!RT_IS_POWER_OF_TWO(paShdrs[i].sh_addralign)) + return error(pszFile, "Section #%u '%s' alignment value is not a power of two: %#" ELF_FMT_X64 "\n", + i, pszShNm, paShdrs[i].sh_addralign); + if (!RT_IS_POWER_OF_TWO(paShdrs[i].sh_addralign)) + return error(pszFile, "Section #%u '%s' alignment value is not a power of two: %#" ELF_FMT_X64 "\n", + i, pszShNm, paShdrs[i].sh_addralign); + if (paShdrs[i].sh_addr != 0) + return error(pszFile, "Section #%u '%s' has non-zero address: %#" ELF_FMT_X64 "\n", i, pszShNm, paShdrs[i].sh_addr); + + if (paShdrs[i].sh_type == SHT_RELA) + { + if (paShdrs[i].sh_entsize != sizeof(Elf64_Rela)) + return error(pszFile, "Expected sh_entsize to be %u not %u for section #%u (%s)\n", (unsigned)sizeof(Elf64_Rela), + paShdrs[i].sh_entsize, i, pszShNm); + uint32_t const cRelocs = paShdrs[i].sh_size / sizeof(Elf64_Rela); + if (cRelocs * sizeof(Elf64_Rela) != paShdrs[i].sh_size) + return error(pszFile, "Uneven relocation entry count in #%u (%s): sh_size=%#" ELF_FMT_X64 "\n", + i, pszShNm, paShdrs[i].sh_size); + if ( paShdrs[i].sh_offset > cbFile + || paShdrs[i].sh_size >= cbFile + || paShdrs[i].sh_offset + paShdrs[i].sh_size > cbFile) + return error(pszFile, "The content of section #%u '%s' is outside the file (%#" ELF_FMT_X64 " LB %#" ELF_FMT_X64 ", cbFile=%#lx)\n", + i, pszShNm, paShdrs[i].sh_offset, paShdrs[i].sh_size, (unsigned long)cbFile); + if (paShdrs[i].sh_info != i - 1) + return error(pszFile, "Expected relocation section #%u (%s) to link to previous section: sh_info=%#u\n", + i, pszShNm, (unsigned)paShdrs[i].sh_link); + if (paShdrs[paShdrs[i].sh_link].sh_type != SHT_SYMTAB) + return error(pszFile, "Expected relocation section #%u (%s) to link to symbol table: sh_link=%#u -> sh_type=%#x\n", + i, pszShNm, (unsigned)paShdrs[i].sh_link, (unsigned)paShdrs[paShdrs[i].sh_link].sh_type); + uint32_t cSymbols = paShdrs[paShdrs[i].sh_link].sh_size / paShdrs[paShdrs[i].sh_link].sh_entsize; + + Elf64_Rela const *paRelocs = (Elf64_Rela *)&pbFile[paShdrs[i].sh_offset]; + for (uint32_t j = 0; j < cRelocs; j++) + { + uint8_t const bType = ELF64_R_TYPE(paRelocs[j].r_info); + if (RT_UNLIKELY(bType >= R_X86_64_COUNT)) + fRet = error(pszFile, + "%#018" ELF_FMT_X64 " %#018" ELF_FMT_X64 ": unknown fix up %#x (%+" ELF_FMT_D64 ")\n", + paRelocs[j].r_offset, paRelocs[j].r_info, bType, paRelocs[j].r_addend); + if (RT_UNLIKELY( j > 1 + && paRelocs[j].r_offset <= paRelocs[j - 1].r_offset + && paRelocs[j].r_offset + ELF_AMD64_RELOC_SIZE(ELF64_R_TYPE(paRelocs[j].r_info)) + < paRelocs[j - 1].r_offset )) + fRet = error(pszFile, + "%#018" ELF_FMT_X64 " %#018" ELF_FMT_X64 ": out of offset order (prev %" ELF_FMT_X64 ")\n", + paRelocs[j].r_offset, paRelocs[j].r_info, paRelocs[j - 1].r_offset); + uint32_t const iSymbol = ELF64_R_SYM(paRelocs[j].r_info); + if (RT_UNLIKELY(iSymbol >= cSymbols)) + fRet = error(pszFile, + "%#018" ELF_FMT_X64 " %#018" ELF_FMT_X64 ": symbol index (%#x) out of bounds (%#x)\n", + paRelocs[j].r_offset, paRelocs[j].r_info, iSymbol, cSymbols); + } + if (RT_UNLIKELY( cRelocs > 0 + && fRet + && ( paRelocs[cRelocs - 1].r_offset > paShdrs[i - 1].sh_size + || paRelocs[cRelocs - 1].r_offset + ELF_AMD64_RELOC_SIZE(ELF64_R_TYPE(paRelocs[cRelocs-1].r_info)) + > paShdrs[i - 1].sh_size ))) + fRet = error(pszFile, + "%#018" ELF_FMT_X64 " %#018" ELF_FMT_X64 ": out of bounds (sh_size %" ELF_FMT_X64 ")\n", + paRelocs[cRelocs - 1].r_offset, paRelocs[cRelocs - 1].r_info, paShdrs[i - 1].sh_size); + + } + else if (paShdrs[i].sh_type == SHT_REL) + fRet = error(pszFile, "Section #%u '%s': Unexpected SHT_REL section\n", i, pszShNm); + else if (paShdrs[i].sh_type == SHT_SYMTAB) + { + if (paShdrs[i].sh_entsize != sizeof(Elf64_Sym)) + fRet = error(pszFile, "Section #%u '%s': Unsupported symbol table entry size in : #%u (expected #%u)\n", + i, pszShNm, paShdrs[i].sh_entsize, sizeof(Elf64_Sym)); + Elf64_Xword const cSymbols = paShdrs[i].sh_size / paShdrs[i].sh_entsize; + if (cSymbols * paShdrs[i].sh_entsize != paShdrs[i].sh_size) + fRet = error(pszFile, "Section #%u '%s': Size not a multiple of entry size: %#" ELF_FMT_X64 " %% %#" ELF_FMT_X64 " = %#" ELF_FMT_X64 "\n", + i, pszShNm, paShdrs[i].sh_size, paShdrs[i].sh_entsize, paShdrs[i].sh_size % paShdrs[i].sh_entsize); + if (cSymbols > UINT32_MAX) + fRet = error(pszFile, "Section #%u '%s': too many symbols: %" ELF_FMT_X64 "\n", + i, pszShNm, paShdrs[i].sh_size, cSymbols); + + if (pMachOStuff->iSymSh == UINT16_MAX) + { + pMachOStuff->iSymSh = (uint16_t)i; + pMachOStuff->paSymbols = (Elf64_Sym const *)&pbFile[paShdrs[i].sh_offset]; + pMachOStuff->cSymbols = cSymbols; + + if (paShdrs[i].sh_link != 0) + { + /* Note! The symbol string table section header may not have been validated yet! */ + Elf64_Shdr const *pStrTabShdr = &paShdrs[paShdrs[i].sh_link]; + pMachOStuff->iStrSh = paShdrs[i].sh_link; + pMachOStuff->pchStrTab = (const char *)&pbFile[pStrTabShdr->sh_offset]; + pMachOStuff->cbStrTab = (size_t)pStrTabShdr->sh_size; + } + else + fRet = error(pszFile, "Section #%u '%s': String table link is out of bounds (%#x)\n", + i, pszShNm, paShdrs[i].sh_link); + } + else + fRet = error(pszFile, "Section #%u '%s': Found additonal symbol table, previous in #%u\n", + i, pszShNm, pMachOStuff->iSymSh); + } + } + return fRet; +} + +static bool convertMachoSectionsToSegDefsAndGrpDefs(POMFWRITER pThis, PCMACHODETAILS pMachOStuff) +{ + /* + * Do the list of names pass. + */ + uint16_t idxGrpFlat, idxGrpData; + uint16_t idxClassCode, idxClassData, idxClassDwarf; + if ( !omfWriter_LNamesBegin(pThis, true /*fAddZeroEntry*/) + || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("FLAT"), &idxGrpFlat) + || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("BS3DATA64_GROUP"), &idxGrpData) + || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("BS3CLASS64CODE"), &idxClassCode) + || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("FAR_DATA"), &idxClassData) + || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("DWARF"), &idxClassDwarf) + ) + return false; + + bool fHaveData = false; + Elf64_Shdr const *pShdr = &pMachOStuff->paShdrs[1]; + Elf64_Half const cSections = pMachOStuff->pEhdr->e_shnum; + for (Elf64_Half i = 1; i < cSections; i++, pShdr++) + { + const char *pszName = &pMachOStuff->pchShStrTab[pShdr->sh_name]; + if (*pszName == '\0') + return error(pThis->pszSrc, "Section #%u has an empty name!\n", i); + + switch (pShdr->sh_type) + { + case SHT_PROGBITS: + case SHT_NOBITS: + /* We drop a few sections we don't want:. */ + if ( strcmp(pszName, ".comment") != 0 /* compiler info */ + && strcmp(pszName, ".note.GNU-stack") != 0 /* some empty section for hinting the linker/whatever */ + && strcmp(pszName, ".eh_frame") != 0 /* unwind / exception info */ + ) + { + pThis->paSegments[i].iSegDef = UINT16_MAX; + pThis->paSegments[i].iGrpDef = UINT16_MAX; + + /* Translate the name and determine group and class. + Note! We currently strip sub-sections. */ + if ( strcmp(pszName, ".text") == 0 + || strncmp(pszName, RT_STR_TUPLE(".text.")) == 0) + { + pszName = "BS3TEXT64"; + pThis->paSegments[i].iGrpNm = idxGrpFlat; + pThis->paSegments[i].iClassNm = idxClassCode; + } + else if ( strcmp(pszName, ".data") == 0 + || strncmp(pszName, RT_STR_TUPLE(".data.")) == 0) + { + pszName = "BS3DATA64"; + pThis->paSegments[i].iGrpNm = idxGrpData; + pThis->paSegments[i].iClassNm = idxClassData; + } + else if (strcmp(pszName, ".bss") == 0) + { + pszName = "BS3BSS64"; + pThis->paSegments[i].iGrpNm = idxGrpData; + pThis->paSegments[i].iClassNm = idxClassData; + } + else if ( strcmp(pszName, ".rodata") == 0 + || strncmp(pszName, RT_STR_TUPLE(".rodata.")) == 0) + { + pszName = "BS3DATA64CONST"; + pThis->paSegments[i].iGrpNm = idxGrpData; + pThis->paSegments[i].iClassNm = idxClassData; + } + else if (strncmp(pszName, RT_STR_TUPLE(".debug_")) == 0) + { + pThis->paSegments[i].iGrpNm = UINT16_MAX; + pThis->paSegments[i].iClassNm = idxClassDwarf; + } + else + { + pThis->paSegments[i].iGrpNm = idxGrpData; + pThis->paSegments[i].iClassNm = idxClassData; + error(pThis->pszSrc, "Unknown data (?) segment: '%s'\n", pszName); + } + + /* Save the name. */ + pThis->paSegments[i].pszName = strdup(pszName); + if (!pThis->paSegments[i].pszName) + return error(pThis->pszSrc, "Out of memory!\n"); + + /* Add the section name. */ + if (!omfWriter_LNamesAdd(pThis, pThis->paSegments[i].pszName, &pThis->paSegments[i].iSegNm)) + return false; + + fHaveData |= pThis->paSegments[i].iGrpDef == idxGrpData; + break; + } + RT_FALL_THRU(); + + default: + pThis->paSegments[i].iSegDef = UINT16_MAX; + pThis->paSegments[i].iGrpDef = UINT16_MAX; + pThis->paSegments[i].iSegNm = UINT16_MAX; + pThis->paSegments[i].iGrpNm = UINT16_MAX; + pThis->paSegments[i].iClassNm = UINT16_MAX; + pThis->paSegments[i].pszName = NULL; + break; + } + } + + if (!omfWriter_LNamesEnd(pThis)) + return false; + + /* + * Emit segment definitions. + */ + uint16_t iSegDef = 1; /* Start counting at 1. */ + pShdr = &pMachOStuff->paShdrs[1]; + for (Elf64_Half i = 1; i < cSections; i++, pShdr++) + { + if (pThis->paSegments[i].iSegNm == UINT16_MAX) + continue; + + uint8_t bSegAttr = 0; + + /* The A field. */ + switch (pShdr->sh_addralign) + { + case 0: + case 1: + bSegAttr |= 1 << 5; + break; + case 2: + bSegAttr |= 2 << 5; + break; + case 4: + bSegAttr |= 5 << 5; + break; + case 8: + case 16: + bSegAttr |= 3 << 5; + break; + case 32: + case 64: + case 128: + case 256: + bSegAttr |= 4 << 5; + break; + default: + bSegAttr |= 6 << 5; /* page aligned, pharlabs extension. */ + break; + } + + /* The C field. */ + bSegAttr |= 2 << 2; /* public */ + + /* The B field. We don't have 4GB segments, so leave it as zero. */ + + /* The D field shall be set as we're doing USE32. */ + bSegAttr |= 1; + + + /* Done. */ + if (!omfWriter_SegDef(pThis, bSegAttr, (uint32_t)pShdr->sh_size, + pThis->paSegments[i].iSegNm, + pThis->paSegments[i].iClassNm)) + return false; + pThis->paSegments[i].iSegDef = iSegDef++; + } + + /* + * Flat group definition (#1) - special, no members. + */ + uint16_t iGrpDef = 1; + if ( !omfWriter_GrpDefBegin(pThis, idxGrpFlat) + || !omfWriter_GrpDefEnd(pThis)) + return false; + for (uint16_t i = 0; i < cSections; i++) + if (pThis->paSegments[i].iGrpNm == idxGrpFlat) + pThis->paSegments[i].iGrpDef = iGrpDef; + pThis->idxGrpFlat = iGrpDef++; + + /* + * Data group definition (#2). + */ + /** @todo do we need to consider missing segments and ordering? */ + uint16_t cGrpNms = 0; + uint16_t aiGrpNms[2] = { 0, 0 }; /* Shut up, GCC. */ + if (fHaveData) + aiGrpNms[cGrpNms++] = idxGrpData; + for (uint32_t iGrpNm = 0; iGrpNm < cGrpNms; iGrpNm++) + { + if (!omfWriter_GrpDefBegin(pThis, aiGrpNms[iGrpNm])) + return false; + for (uint16_t i = 0; i < cSections; i++) + if (pThis->paSegments[i].iGrpNm == aiGrpNms[iGrpNm]) + { + pThis->paSegments[i].iGrpDef = iGrpDef; + if (!omfWriter_GrpDefAddSegDef(pThis, pThis->paSegments[i].iSegDef)) + return false; + } + if (!omfWriter_GrpDefEnd(pThis)) + return false; + iGrpDef++; + } + + return true; +} + +static bool convertMachOSymbolsToPubDefsAndExtDefs(POMFWRITER pThis, PCMACHODETAILS pMachOStuff) +{ + if (!pMachOStuff->cSymbols) + return true; + + /* + * Process the symbols the first. + */ + uint32_t cAbsSyms = 0; + uint32_t cExtSyms = 0; + uint32_t cPubSyms = 0; + for (uint32_t iSeg = 0; iSeg < pThis->cSegments; iSeg++) + pThis->paSegments[iSeg].cPubDefs = 0; + + uint32_t const cSections = pMachOStuff->pEhdr->e_shnum; + uint32_t const cSymbols = pMachOStuff->cSymbols; + Elf64_Sym const * const paSymbols = pMachOStuff->paSymbols; + for (uint32_t iSym = 0; iSym < cSymbols; iSym++) + { + const uint8_t bBind = ELF64_ST_BIND(paSymbols[iSym].st_info); + const uint8_t bType = ELF64_ST_TYPE(paSymbols[iSym].st_info); + const char *pszSymName = &pMachOStuff->pchStrTab[paSymbols[iSym].st_name]; + if ( *pszSymName == '\0' + && bType == STT_SECTION + && paSymbols[iSym].st_shndx < cSections) + pszSymName = &pMachOStuff->pchShStrTab[pMachOStuff->paShdrs[paSymbols[iSym].st_shndx].sh_name]; + + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_IGNORED; + pThis->paSymbols[iSym].idx = UINT16_MAX; + pThis->paSymbols[iSym].idxSegDef = UINT16_MAX; + pThis->paSymbols[iSym].idxGrpDef = UINT16_MAX; + + uint32_t const idxSection = paSymbols[iSym].st_shndx; + if (idxSection == SHN_UNDEF) + { + if (bBind == STB_GLOBAL) + { + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_EXTDEF; + cExtSyms++; + if (*pszSymName == '\0') + return error(pThis->pszSrc, "External symbol #%u (%s) has an empty name.\n", iSym, pszSymName); + } + else if (bBind != STB_LOCAL || iSym != 0) /* Entry zero is usually a dummy. */ + return error(pThis->pszSrc, "Unsupported or invalid bind type %#x for undefined symbol #%u (%s)\n", + bBind, iSym, pszSymName); + } + else if (idxSection < cSections) + { + pThis->paSymbols[iSym].idxSegDef = pThis->paSegments[idxSection].iSegDef; + pThis->paSymbols[iSym].idxGrpDef = pThis->paSegments[idxSection].iGrpDef; + if (bBind == STB_GLOBAL) + { + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_PUBDEF; + pThis->paSegments[idxSection].cPubDefs++; + cPubSyms++; + if (bType == STT_SECTION) + return error(pThis->pszSrc, "Don't know how to export STT_SECTION symbol #%u (%s)\n", iSym, pszSymName); + if (*pszSymName == '\0') + return error(pThis->pszSrc, "Public symbol #%u (%s) has an empty name.\n", iSym, pszSymName); + } + else if (bType == STT_SECTION) + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_SEGDEF; + else + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_INTERNAL; + } + else if (idxSection == SHN_ABS) + { + if (bType != STT_FILE) + { + if (bBind == STB_GLOBAL) + { + pThis->paSymbols[iSym].enmType = OMFSYMTYPE_PUBDEF; + pThis->paSymbols[iSym].idxSegDef = 0; + pThis->paSymbols[iSym].idxGrpDef = 0; + cAbsSyms++; + if (*pszSymName == '\0') + return error(pThis->pszSrc, "Public absolute symbol #%u (%s) has an empty name.\n", iSym, pszSymName); + } + else + return error(pThis->pszSrc, "Unsupported or invalid bind type %#x for absolute symbol #%u (%s)\n", + bBind, iSym, pszSymName); + } + } + else + return error(pThis->pszSrc, "Unsupported or invalid section number %#x for symbol #%u (%s)\n", + idxSection, iSym, pszSymName); + } + + /* + * Emit the PUBDEFs the first time around (see order of records in TIS spec). + * Note! We expect the os x compiler to always underscore symbols, so unlike the + * other 64-bit converters we don't need to check for underscores and add them. + */ + uint16_t idxPubDef = 1; + if (cPubSyms) + { + for (uint32_t iSeg = 0; iSeg < pThis->cSegments; iSeg++) + if (pThis->paSegments[iSeg].cPubDefs > 0) + { + uint16_t const idxSegDef = pThis->paSegments[iSeg].iSegDef; + if (!omfWriter_PubDefBegin(pThis, pThis->paSegments[iSeg].iGrpDef, idxSegDef)) + return false; + for (uint16_t iSym = 0; iSym < cSymbols; iSym++) + if ( pThis->paSymbols[iSym].idxSegDef == idxSegDef + && pThis->paSymbols[iSym].enmType == OMFSYMTYPE_PUBDEF) + { + const char *pszName = &pMachOStuff->pchStrTab[paSymbols[iSym].st_name]; + if (!omfWriter_PubDefAdd(pThis, paSymbols[iSym].st_value, pszName, false /*fPrependUnderscore*/)) + return false; + pThis->paSymbols[iSym].idx = idxPubDef++; + } + if (!omfWriter_PubDefEnd(pThis)) + return false; + } + } + + if (cAbsSyms > 0) + { + if (!omfWriter_PubDefBegin(pThis, 0, 0)) + return false; + for (uint16_t iSym = 0; iSym < cSymbols; iSym++) + if ( pThis->paSymbols[iSym].idxSegDef == 0 + && pThis->paSymbols[iSym].enmType == OMFSYMTYPE_PUBDEF) + { + const char *pszName = &pMachOStuff->pchStrTab[paSymbols[iSym].st_name]; + if (!omfWriter_PubDefAdd(pThis, paSymbols[iSym].st_value, pszName, false /*fPrependUnderscore*/)) + return false; + pThis->paSymbols[iSym].idx = idxPubDef++; + } + if (!omfWriter_PubDefEnd(pThis)) + return false; + } + + /* + * Go over the symbol table and emit external definition records. + */ + if (!omfWriter_ExtDefBegin(pThis)) + return false; + uint16_t idxExtDef = 1; + for (uint16_t iSym = 0; iSym < cSymbols; iSym++) + if (pThis->paSymbols[iSym].enmType == OMFSYMTYPE_EXTDEF) + { + const char *pszName = &pMachOStuff->pchStrTab[paSymbols[iSym].st_name]; + if (!omfWriter_ExtDefAdd(pThis, pszName, false /*fPrependUnderscore*/)) + return false; + pThis->paSymbols[iSym].idx = idxExtDef++; + } + + if (!omfWriter_ExtDefEnd(pThis)) + return false; + + return true; +} + +static bool convertMachOSectionsToLeDataAndFixupps(POMFWRITER pThis, PCMACHODETAILS pMachOStuff, + uint8_t const *pbFile, size_t cbFile) +{ + Elf64_Sym const *paSymbols = pMachOStuff->paSymbols; + Elf64_Shdr const *paShdrs = pMachOStuff->paShdrs; + bool fRet = true; + for (uint32_t i = 1; i < pThis->cSegments; i++) + { + if (pThis->paSegments[i].iSegDef == UINT16_MAX) + continue; + + const char *pszSegNm = &pMachOStuff->pchShStrTab[paShdrs[i].sh_name]; + bool const fRelocs = i + 1 < pThis->cSegments && paShdrs[i + 1].sh_type == SHT_RELA; + uint32_t cRelocs = fRelocs ? paShdrs[i + 1].sh_size / sizeof(Elf64_Rela) : 0; + Elf64_Rela const *paRelocs = fRelocs ? (Elf64_Rela *)&pbFile[paShdrs[i + 1].sh_offset] : NULL; + Elf64_Xword cbVirtData = paShdrs[i].sh_size; + Elf64_Xword cbData = paShdrs[i].sh_type == SHT_NOBITS ? 0 : cbVirtData; + uint8_t const *pbData = &pbFile[paShdrs[i].sh_offset]; + uint32_t off = 0; + + /* The OMF record size requires us to split larger sections up. To make + life simple, we fill zeros for unitialized (BSS) stuff. */ + const uint32_t cbMaxData = RT_MIN(OMF_MAX_RECORD_PAYLOAD - 1 - (pThis->paSegments[i].iSegDef >= 128) - 4 - 1, _1K); + while (cbVirtData > 0) + { + /* Figure out how many bytes to put out in this chunk. Must make sure + fixups doesn't cross chunk boundraries. ASSUMES sorted relocs. */ + uint32_t cChunkRelocs = cRelocs; + uint32_t cbChunk = cbVirtData; + uint32_t offEnd = off + cbChunk; + if (cbChunk > cbMaxData) + { + cbChunk = cbMaxData; + offEnd = off + cbChunk; + cChunkRelocs = 0; + + /* Quickly determin the reloc range. */ + while ( cChunkRelocs < cRelocs + && paRelocs[cChunkRelocs].r_offset < offEnd) + cChunkRelocs++; + + /* Ensure final reloc doesn't go beyond chunk. */ + while ( cChunkRelocs > 0 + && paRelocs[cChunkRelocs - 1].r_offset + + ELF_AMD64_RELOC_SIZE(ELF64_R_TYPE(paRelocs[cChunkRelocs - 1].r_info)) + > offEnd) + { + uint32_t cbDrop = offEnd - paRelocs[cChunkRelocs - 1].r_offset; + cbChunk -= cbDrop; + offEnd -= cbDrop; + cChunkRelocs--; + } + + if (!cbVirtData) + return error(pThis->pszSrc, "Wtf? cbVirtData is zero!\n"); + } + + /* + * We stash the bytes into the OMF writer record buffer, receiving a + * pointer to the start of it so we can make adjustments if necessary. + */ + uint8_t *pbCopy; + if (!omfWriter_LEDataBeginEx(pThis, pThis->paSegments[i].iSegDef, off, cbChunk, cbData, pbData, &pbCopy)) + return false; + + /* + * Convert fiuxps. + */ + for (uint32_t iReloc = 0; iReloc < cChunkRelocs; iReloc++) + { + /* Get the OMF and ELF data for the symbol the reloc references. */ + uint32_t const uType = ELF64_R_TYPE(paRelocs[iReloc].r_info); + uint32_t const iSymbol = ELF64_R_SYM(paRelocs[iReloc].r_info); + Elf64_Sym const * const pElfSym = &paSymbols[iSymbol]; + POMFSYMBOL const pOmfSym = &pThis->paSymbols[iSymbol]; + const char * const pszSymName = &pMachOStuff->pchStrTab[pElfSym->st_name]; + + /* Calc fixup location in the pending chunk and setup a flexible pointer to it. */ + uint16_t offDataRec = (uint16_t)(paRelocs[iReloc].r_offset - off); + RTPTRUNION uLoc; + uLoc.pu8 = &pbCopy[offDataRec]; + + /* OMF fixup data initialized with typical defaults. */ + bool fSelfRel = true; + uint8_t bLocation = OMF_FIX_LOC_32BIT_OFFSET; + uint8_t bFrame = OMF_FIX_F_GRPDEF; + uint16_t idxFrame = pThis->idxGrpFlat; + uint8_t bTarget; + uint16_t idxTarget; + bool fTargetDisp; + uint32_t offTargetDisp; + switch (pOmfSym->enmType) + { + case OMFSYMTYPE_INTERNAL: + case OMFSYMTYPE_PUBDEF: + bTarget = OMF_FIX_T_SEGDEF; + idxTarget = pOmfSym->idxSegDef; + fTargetDisp = true; + offTargetDisp = pElfSym->st_value; + break; + + case OMFSYMTYPE_SEGDEF: + bTarget = OMF_FIX_T_SEGDEF_NO_DISP; + idxTarget = pOmfSym->idxSegDef; + fTargetDisp = false; + offTargetDisp = 0; + break; + + case OMFSYMTYPE_EXTDEF: + bTarget = OMF_FIX_T_EXTDEF_NO_DISP; + idxTarget = pOmfSym->idx; + fTargetDisp = false; + offTargetDisp = 0; + break; + + default: + return error(pThis->pszSrc, "Relocation in segment #%u '%s' references ignored or invalid symbol (%s)\n", + i, pszSegNm, pszSymName); + } + + /* Do COFF relocation type conversion. */ + switch (uType) + { + case R_X86_64_64: + { + int64_t iAddend = paRelocs[iReloc].r_addend; + if (iAddend > _1G || iAddend < -_1G) + fRet = error(pThis->pszSrc, "R_X86_64_64 with large addend (%" ELF_FMT_D64 ") at %#x in segment #%u '%s'\n", + iAddend, paRelocs[iReloc].r_offset, i, pszSegNm); + *uLoc.pu64 = iAddend; + fSelfRel = false; + break; + } + + case R_X86_64_32: + case R_X86_64_32S: /* signed, unsigned, whatever. */ + fSelfRel = false; + RT_FALL_THRU(); + case R_X86_64_PC32: + { + /* defaults are ok, just handle the addend. */ + int32_t iAddend = paRelocs[iReloc].r_addend; + if (iAddend != paRelocs[iReloc].r_addend) + fRet = error(pThis->pszSrc, "R_X86_64_PC32 with large addend (%d) at %#x in segment #%u '%s'\n", + iAddend, paRelocs[iReloc].r_offset, i, pszSegNm); + *uLoc.pu32 = iAddend; + break; + } + + case R_X86_64_NONE: + continue; /* Ignore this one */ + + case R_X86_64_GOT32: + case R_X86_64_PLT32: + case R_X86_64_COPY: + case R_X86_64_GLOB_DAT: + case R_X86_64_JMP_SLOT: + case R_X86_64_RELATIVE: + case R_X86_64_GOTPCREL: + case R_X86_64_16: + case R_X86_64_PC16: + case R_X86_64_8: + case R_X86_64_PC8: + case R_X86_64_DTPMOD64: + case R_X86_64_DTPOFF64: + case R_X86_64_TPOFF64: + case R_X86_64_TLSGD: + case R_X86_64_TLSLD: + case R_X86_64_DTPOFF32: + case R_X86_64_GOTTPOFF: + case R_X86_64_TPOFF32: + default: + return error(pThis->pszSrc, "Unsupported fixup type %#x (%s) at rva=%#x in section #%u '%s' against '%s'\n", + uType, g_apszElfAmd64RelTypes[uType], paRelocs[iReloc].r_offset, i, pszSegNm, pszSymName); + } + + /* Add the fixup. */ + if (idxFrame == UINT16_MAX) + error(pThis->pszSrc, "idxFrame=UINT16_MAX for %s type=%s\n", pszSymName, g_apszElfAmd64RelTypes[uType]); + fRet = omfWriter_LEDataAddFixup(pThis, offDataRec, fSelfRel, bLocation, bFrame, idxFrame, + bTarget, idxTarget, fTargetDisp, offTargetDisp) && fRet; + } + + /* + * Write the LEDATA and associated FIXUPPs. + */ + if (!omfWriter_LEDataEnd(pThis)) + return false; + + /* + * Advance. + */ + paRelocs += cChunkRelocs; + cRelocs -= cChunkRelocs; + if (cbData > cbChunk) + { + cbData -= cbChunk; + pbData += cbChunk; + } + else + cbData = 0; + off += cbChunk; + cbVirtData -= cbChunk; + } + } + + return fRet; +} + + +static bool convertMachoToOmf(const char *pszFile, uint8_t const *pbFile, size_t cbFile, FILE *pDst) +{ + /* + * Validate the source file a little. + */ + MACHODETAILS MachOStuff; + if (!validateMachO(pszFile, pbFile, cbFile, &MachOStuff)) + return false; + + /* + * Instantiate the OMF writer. + */ + POMFWRITER pThis = omfWriter_Create(pszFile, MachOStuff.pEhdr->e_shnum, MachOStuff.cSymbols, pDst); + if (!pThis) + return false; + + /* + * Write the OMF object file. + */ + if (omfWriter_BeginModule(pThis, pszFile)) + { + Elf64_Ehdr const *pEhdr = (Elf64_Ehdr const *)pbFile; + + if ( convertMachOSectionsToSegDefsAndGrpDefs(pThis, &MachOStuff) + && convertMachOSymbolsToPubDefsAndExtDefs(pThis, &MachOStuff) + && omfWriter_LinkPassSeparator(pThis) + && convertMachOSectionsToLeDataAndFixupps(pThis, &MachOStuff, pbFile, cbFile) + && omfWriter_EndModule(pThis) ) + { + + omfWriter_Destroy(pThis); + return true; + } + } + + omfWriter_Destroy(pThis); + return false; +} + +#endif /* !MACHO_TO_OMF_CONVERSION */ + + +/********************************************************************************************************************************* +* OMF Converter/Tweaker * +*********************************************************************************************************************************/ + +/** Watcom intrinsics we need to modify so we can mix 32-bit and 16-bit + * code, since the 16 and 32 bit compilers share several names. + * The names are length prefixed. + */ +static const char * const g_apszExtDefRenames[] = +{ + "\x05" "__I4D", + "\x05" "__I4M", + "\x05" "__I8D", + "\x06" "__I8DQ", + "\x07" "__I8DQE", + "\x06" "__I8DR", + "\x07" "__I8DRE", + "\x06" "__I8LS", + "\x05" "__I8M", + "\x06" "__I8ME", + "\x06" "__I8RS", + "\x05" "__PIA", + "\x05" "__PIS", + "\x05" "__PTC", + "\x05" "__PTS", + "\x05" "__U4D", + "\x05" "__U4M", + "\x05" "__U8D", + "\x06" "__U8DQ", + "\x07" "__U8DQE", + "\x06" "__U8DR", + "\x07" "__U8DRE", + "\x06" "__U8LS", + "\x05" "__U8M", + "\x06" "__U8ME", + "\x06" "__U8RS", +}; + +/** + * Segment definition. + */ +typedef struct OMFSEGDEF +{ + uint32_t cbSeg; + uint8_t bSegAttr; + uint16_t idxName; + uint16_t idxClass; + uint16_t idxOverlay; + uint8_t cchName; + uint8_t cchClass; + uint8_t cchOverlay; + const char *pchName; + const char *pchClass; + const char *pchOverlay; + bool fUse32; + bool f32bitRec; +} OMFSEGDEF; +typedef OMFSEGDEF *POMFSEGDEF; + +/** + * Group definition. + */ +typedef struct OMFGRPDEF +{ + const char *pchName; + uint16_t idxName; + uint8_t cchName; + uint16_t cSegDefs; + uint16_t *paidxSegDefs; +} OMFGRPDEF; +typedef OMFGRPDEF *POMFGRPDEF; + +/** + * Records line number information for a file in a segment (for CV8 debug info). + */ +typedef struct OMFFILELINES +{ + /** The source info offset. */ + uint32_t offSrcInfo; + /** Number of line/offset pairs. */ + uint32_t cPairs; + /** Number of pairs allocated. */ + uint32_t cPairsAlloc; + /** Table with line number and offset pairs, ordered by offset. */ + PRTCV8LINEPAIR paPairs; +} OMFFILEINES; +typedef OMFFILEINES *POMFFILEINES; + +/** + * Records line number information for a segment (for CV8 debug info). + */ +typedef struct OMFSEGLINES +{ + /** Number of files. */ + uint32_t cFiles; + /** Number of bytes we need. */ + uint32_t cb; + /** The segment index. */ + uint16_t idxSeg; + /** The group index for this segment. Initially OMF_REPLACE_GRP_XXX values, + * later convertOmfWriteDebugGrpDefs replaces them with actual values. */ + uint16_t idxGrp; + /** File table. */ + POMFFILEINES paFiles; +} OMFSEGLINES; +typedef OMFSEGLINES *POMFSEGLINES; + +/** @name OMF_REPLACE_GRP_XXX - Special OMFSEGLINES::idxGrp values. + * @{ */ +#define OMF_REPLACE_GRP_CGROUP16 UINT16_C(0xffe0) +#define OMF_REPLACE_GRP_RMCODE UINT16_C(0xffe1) +#define OMF_REPLACE_GRP_X0CODE UINT16_C(0xffe2) +#define OMF_REPLACE_GRP_X1CODE UINT16_C(0xffe3) +/** @} */ + + +/** + * OMF details allocation that needs to be freed when done. + */ +typedef struct OMFDETAILSALLOC +{ + /** Pointer to the next allocation. */ + struct OMFDETAILSALLOC *pNext; + /** The allocated bytes. */ + RT_FLEXIBLE_ARRAY_EXTENSION + uint8_t abData[RT_FLEXIBLE_ARRAY]; +} OMFDETAILSALLOC; +typedef OMFDETAILSALLOC *POMFDETAILSALLOC; + +/** + * OMF conversion details. + * + * Keeps information relevant to the conversion and CV8 debug info. + */ +typedef struct OMFDETAILS +{ + /** The input file name. */ + const char *pszFile; + + /** Set if it has line numbers. */ + bool fLineNumbers; + /** Set if we think this may be a 32-bit OMF file. */ + bool fProbably32bit; + /** Set if this module may need mangling. */ + bool fMayNeedMangling; + /** The LNAME index of '$$SYMBOLS' or UINT16_MAX it not found. */ + uint16_t iSymbolsNm; + /** The LNAME index of 'DEBSYM' or UINT16_MAX it not found. */ + uint16_t iDebSymNm; + /** The '$$SYMBOLS' segment index. */ + uint16_t iSymbolsSeg; + + /** Number of SEGDEFs records. */ + uint16_t cSegDefs; + /** Number of GRPDEFs records. */ + uint16_t cGrpDefs; + /** Number of listed names. */ + uint16_t cLNames; + + /** Segment defintions. */ + POMFSEGDEF paSegDefs; + /** Group defintions. */ + POMFGRPDEF paGrpDefs; + /** Name list. Points to the size repfix. */ + char **papchLNames; + + /** Code groups we need to keep an eye on for line number fixup purposes. */ + struct OMFLINEGROUPS + { + /** The name. */ + const char *pszName; + /** The primary class name. */ + const char *pszClass1; + /** The secondary class name. */ + const char *pszClass2; + /** The main segment name, NULL if not applicable (CGROUP16). */ + const char *pszSeg; + /** The name length. */ + uint8_t cchName; + /** The primary class name length. */ + uint8_t cchClass1; + /** The secondary class name length. */ + uint8_t cchClass2; + /** Whether this group is needed. */ + bool fNeeded; + /** The group index (UINT16_MAX if not found). */ + uint16_t idxGroup; + /** The group name. */ + uint16_t idxName; + /** The OMF_REPLACE_GRP_XXX value. */ + uint16_t idxReplaceGrp; + } aGroups[4]; + + /** CV8: Filename string table size. */ + uint32_t cbStrTab; + /** CV8: Filename string table allocation size (always multiple of dword, + * zero initialized). */ + uint32_t cbStrTabAlloc; + /** CV8: Filename String table. */ + char *pchStrTab; + /** CV8: Elements in the source info table. */ + uint16_t cSrcInfo; + /** CV8: Source info table. */ + PRTCV8SRCINFO paSrcInfo; + + /** Number of entries in the paSegLines table. */ + uint32_t cSegLines; + /** Segment line numbers, indexed by segment number. */ + POMFSEGLINES paSegLines; + + /** List of allocations that needs freeing. */ + POMFDETAILSALLOC pAllocHead; +} OMFDETAILS; +typedef OMFDETAILS *POMFDETAILS; +typedef OMFDETAILS const *PCOMFDETAILS; + + +/** Grows a table to a given size (a_cNewEntries). */ +#define OMF_GROW_TABLE_EX_RET_ERR(a_EntryType, a_paTable, a_cEntries, a_cNewEntries) \ + do\ + { \ + size_t cbOld = (a_cEntries) * sizeof(a_EntryType); \ + size_t cbNew = (a_cNewEntries) * sizeof(a_EntryType); \ + void *pvNew = realloc(a_paTable, cbNew); \ + if (pvNew) \ + { \ + memset((uint8_t *)pvNew + cbOld, 0, cbNew - cbOld); \ + (a_paTable) = (a_EntryType *)pvNew; \ + } \ + else return error("???", "Out of memory!\n"); \ + } while (0) + +/** Grows a table. */ +#define OMF_GROW_TABLE_RET_ERR(a_EntryType, a_paTable, a_cEntries, a_cEvery) \ + if ((a_cEntries) % (a_cEvery) != 0) { /* likely */ } \ + else do\ + { \ + size_t cbOld = (a_cEntries) * sizeof(a_EntryType); \ + size_t cbNew = cbOld + (a_cEvery) * sizeof(a_EntryType); \ + void *pvNew = realloc(a_paTable, cbNew); \ + if (pvNew) \ + { \ + memset((uint8_t *)pvNew + cbOld, 0, (a_cEvery) * sizeof(a_EntryType)); \ + (a_paTable) = (a_EntryType *)pvNew; \ + } \ + else return error("???", "Out of memory!\n"); \ + } while (0) + +#define OMF_EXPLODE_LNAME(a_pOmfStuff, a_idxName, a_pchName, a_cchName, a_Name) \ + do { \ + if ((a_idxName) < (a_pOmfStuff)->cLNames) \ + { \ + a_cchName = (uint8_t)*(a_pOmfStuff)->papchLNames[(a_idxName)]; \ + a_pchName = (a_pOmfStuff)->papchLNames[(a_idxName)] + 1; \ + } \ + else return error((a_pOmfStuff)->pszFile, "Invalid LNAME reference %#x in " #a_Name "!\n", a_idxName); \ + } while (0) + + +/** + * Allocates memory that will be freed when we're done converting. + * + * @returns Pointer tot he memory. + * @param pOmfStuff The OMF details data. + * @param cbNeeded The amount of memory required. + */ +static void *omfDetails_Alloc(POMFDETAILS pOmfStuff, size_t cbNeeded) +{ + POMFDETAILSALLOC pAlloc = (POMFDETAILSALLOC)malloc(RT_UOFFSETOF_DYN(OMFDETAILSALLOC, abData[cbNeeded])); + if (pAlloc) + { + pAlloc->pNext = pOmfStuff->pAllocHead; + pOmfStuff->pAllocHead = pAlloc; + return &pAlloc->abData[0]; + } + return NULL; +} + +/** + * Adds a line number to the CV8 debug info. + * + * @returns success indicator. + * @param pOmfStuff Where to collect CV8 debug info. + * @param cchSrcFile The length of the source file name. + * @param pchSrcFile The source file name, not terminated. + * @param poffFile Where to return the source file information table + * offset (for use in the line number tables). + */ +static bool collectOmfAddFile(POMFDETAILS pOmfStuff, uint8_t cchSrcFile, const char *pchSrcFile, uint32_t *poffFile) +{ + /* + * Do lookup first. + */ + uint32_t i = pOmfStuff->cSrcInfo; + while (i-- > 0) + { + const char *pszCur = &pOmfStuff->pchStrTab[pOmfStuff->paSrcInfo[i].offSourceName]; + if ( strncmp(pszCur, pchSrcFile, cchSrcFile) == 0 + && pszCur[cchSrcFile] == '\0') + { + *poffFile = i * sizeof(pOmfStuff->paSrcInfo[0]); + return true; + } + } + + /* + * Add it to the string table (dword aligned and zero padded). + */ + uint32_t offSrcTab = pOmfStuff->cbStrTab; + if (offSrcTab + cchSrcFile + 1 > pOmfStuff->cbStrTabAlloc) + { + uint32_t cbNew = (offSrcTab == 0) + offSrcTab + cchSrcFile + 1; + cbNew = RT_ALIGN(cbNew, 256); + void *pvNew = realloc(pOmfStuff->pchStrTab, cbNew); + if (!pvNew) + return error("???", "out of memory"); + pOmfStuff->pchStrTab = (char *)pvNew; + pOmfStuff->cbStrTabAlloc = cbNew; + memset(&pOmfStuff->pchStrTab[offSrcTab], 0, cbNew - offSrcTab); + + if (!offSrcTab) + offSrcTab++; + } + + memcpy(&pOmfStuff->pchStrTab[offSrcTab], pchSrcFile, cchSrcFile); + pOmfStuff->pchStrTab[offSrcTab + cchSrcFile] = '\0'; + pOmfStuff->cbStrTab = offSrcTab + cchSrcFile + 1; + + /* + * Add it to the filename info table. + */ + if ((pOmfStuff->cSrcInfo % 8) == 0) + { + void *pvNew = realloc(pOmfStuff->paSrcInfo, sizeof(pOmfStuff->paSrcInfo[0]) * (pOmfStuff->cSrcInfo + 8)); + if (!pvNew) + return error("???", "out of memory"); + pOmfStuff->paSrcInfo = (PRTCV8SRCINFO)pvNew; + } + + PRTCV8SRCINFO pSrcInfo = &pOmfStuff->paSrcInfo[pOmfStuff->cSrcInfo++]; + pSrcInfo->offSourceName = offSrcTab; + pSrcInfo->uDigestType = RTCV8SRCINFO_DIGEST_TYPE_MD5; + memset(&pSrcInfo->Digest, 0, sizeof(pSrcInfo->Digest)); + + *poffFile = (uint32_t)((uintptr_t)pSrcInfo - (uintptr_t)pOmfStuff->paSrcInfo); + return true; +} + + +/** + * Adds a line number to the CV8 debug info. + * + * @returns success indicator. + * @param pOmfStuff Where to collect CV8 debug info. + * @param idxSeg The segment index. + * @param off The segment offset. + * @param uLine The line number. + * @param offSrcInfo The source file info table offset. + */ +static bool collectOmfAddLine(POMFDETAILS pOmfStuff, uint16_t idxSeg, uint32_t off, uint16_t uLine, uint32_t offSrcInfo) +{ + /* + * Get/add the segment line structure. + */ + if (idxSeg >= pOmfStuff->cSegLines) + { + OMF_GROW_TABLE_EX_RET_ERR(OMFSEGLINES, pOmfStuff->paSegLines, pOmfStuff->cSegLines, idxSeg + 1); + for (uint32_t i = pOmfStuff->cSegLines; i <= idxSeg; i++) + { + pOmfStuff->paSegLines[i].idxSeg = i; + pOmfStuff->paSegLines[i].idxGrp = UINT16_MAX; + pOmfStuff->paSegLines[i].cb = sizeof(RTCV8LINESHDR); + } + pOmfStuff->cSegLines = idxSeg + 1; + } + POMFSEGLINES pSegLines = &pOmfStuff->paSegLines[idxSeg]; + + /* + * Get/add the file structure with the segment. + */ + POMFFILEINES pFileLines = NULL; + uint32_t i = pSegLines->cFiles; + while (i-- > 0) + if (pSegLines->paFiles[i].offSrcInfo == offSrcInfo) + { + pFileLines = &pSegLines->paFiles[i]; + break; + } + if (!pFileLines) + { + i = pSegLines->cFiles; + OMF_GROW_TABLE_RET_ERR(OMFFILEINES, pSegLines->paFiles, pSegLines->cFiles, 4); + pSegLines->cFiles = i + 1; + pSegLines->cb += sizeof(RTCV8LINESSRCMAP); + + pFileLines = &pSegLines->paFiles[i]; + pFileLines->offSrcInfo = offSrcInfo; + pFileLines->cPairs = 0; + pFileLines->cPairsAlloc = 0; + pFileLines->paPairs = NULL; + + /* + * Check for segment group requirements the first time a segment is used. + */ + if (i == 0) + { + if (idxSeg >= pOmfStuff->cSegDefs) + return error("???", "collectOmfAddLine: idxSeg=%#x is out of bounds (%#x)!\n", idxSeg, pOmfStuff->cSegDefs); + POMFSEGDEF pSegDef = &pOmfStuff->paSegDefs[idxSeg]; + unsigned j = RT_ELEMENTS(pOmfStuff->aGroups); + while (j-- > 0) + if ( ( pSegDef->cchClass == pOmfStuff->aGroups[j].cchClass1 + && memcmp(pSegDef->pchClass, pOmfStuff->aGroups[j].pszClass1, pSegDef->cchClass) == 0) + || ( pSegDef->cchClass == pOmfStuff->aGroups[j].cchClass2 + && memcmp(pSegDef->pchClass, pOmfStuff->aGroups[j].pszClass2, pSegDef->cchClass) == 0)) + { + pOmfStuff->aGroups[j].fNeeded = true; + pSegLines->idxGrp = pOmfStuff->aGroups[j].idxReplaceGrp; + break; + } + } + } + + /* + * Add the line number (sorted, duplicates removed). + */ + if (pFileLines->cPairs + 1 > pFileLines->cPairsAlloc) + { + void *pvNew = realloc(pFileLines->paPairs, (pFileLines->cPairsAlloc + 16) * sizeof(pFileLines->paPairs[0])); + if (!pvNew) + return error("???", "out of memory"); + pFileLines->paPairs = (PRTCV8LINEPAIR)pvNew; + pFileLines->cPairsAlloc += 16; + } + + i = pFileLines->cPairs; + while (i > 0 && ( off < pFileLines->paPairs[i - 1].offSection + || ( off == pFileLines->paPairs[i - 1].offSection + && uLine < pFileLines->paPairs[i - 1].uLineNumber)) ) + i--; + if ( i == pFileLines->cPairs + || off != pFileLines->paPairs[i].offSection + || uLine != pFileLines->paPairs[i].uLineNumber) + { + if (i < pFileLines->cPairs) + memmove(&pFileLines->paPairs[i + 1], &pFileLines->paPairs[i], + (pFileLines->cPairs - i) * sizeof(pFileLines->paPairs)); + pFileLines->paPairs[i].offSection = off; + pFileLines->paPairs[i].uLineNumber = uLine; + pFileLines->paPairs[i].fEndOfStatement = true; + pFileLines->cPairs++; + pSegLines->cb += sizeof(pFileLines->paPairs[0]); + } + + return true; +} + + +/** + * Parses OMF file gathering line numbers (for CV8 debug info) and checking out + * external defintions for mangling work (compiler instrinsics). + * + * @returns success indicator. + * @param pszFile The name of the OMF file. + * @param pbFile The file content. + * @param cbFile The size of the file content. + * @param pOmfStuff Where to collect CV8 debug info and anything else we + * find out about the OMF file. + */ +static bool collectOmfDetails(const char *pszFile, uint8_t const *pbFile, size_t cbFile, POMFDETAILS pOmfStuff) +{ + uint32_t cExtDefs = 0; + uint32_t cPubDefs = 0; + uint32_t off = 0; + uint8_t cchSrcFile = 0; + const char *pchSrcFile = NULL; + uint32_t offSrcInfo = UINT32_MAX; + + memset(pOmfStuff, 0, sizeof(*pOmfStuff)); + pOmfStuff->pszFile = pszFile; + pOmfStuff->iDebSymNm = UINT16_MAX; + pOmfStuff->iSymbolsNm = UINT16_MAX; + pOmfStuff->iSymbolsSeg = UINT16_MAX; + + /* Dummy entries. */ + OMF_GROW_TABLE_RET_ERR(char *, pOmfStuff->papchLNames, pOmfStuff->cLNames, 16); + pOmfStuff->papchLNames[0] = (char *)""; + pOmfStuff->cLNames = 1; + + OMF_GROW_TABLE_RET_ERR(OMFSEGDEF, pOmfStuff->paSegDefs, pOmfStuff->cSegDefs, 16); + pOmfStuff->cSegDefs = 1; + + OMF_GROW_TABLE_RET_ERR(OMFGRPDEF, pOmfStuff->paGrpDefs, pOmfStuff->cGrpDefs, 16); + pOmfStuff->cGrpDefs = 1; + + /* Groups we seek. */ +#define OMF_INIT_WANTED_GROUP(a_idx, a_szName, a_szClass1, a_szClass2, a_pszSeg, a_idxReplace) \ + pOmfStuff->aGroups[a_idx].pszName = a_szName; \ + pOmfStuff->aGroups[a_idx].cchName = sizeof(a_szName) - 1; \ + pOmfStuff->aGroups[a_idx].pszClass1 = a_szClass1; \ + pOmfStuff->aGroups[a_idx].cchClass1 = sizeof(a_szClass1) - 1; \ + pOmfStuff->aGroups[a_idx].pszClass2 = a_szClass2; \ + pOmfStuff->aGroups[a_idx].cchClass2 = sizeof(a_szClass2) - 1; \ + pOmfStuff->aGroups[a_idx].pszSeg = a_pszSeg; \ + pOmfStuff->aGroups[a_idx].fNeeded = false; \ + pOmfStuff->aGroups[a_idx].idxGroup = UINT16_MAX; \ + pOmfStuff->aGroups[a_idx].idxName = UINT16_MAX; \ + pOmfStuff->aGroups[a_idx].idxReplaceGrp = a_idxReplace + OMF_INIT_WANTED_GROUP(0, "CGROUP16", "BS3CLASS16CODE", "CODE", NULL, OMF_REPLACE_GRP_CGROUP16); + OMF_INIT_WANTED_GROUP(1, "BS3GROUPRMTEXT16", "BS3CLASS16RMCODE", "", "BS3RMTEXT16", OMF_REPLACE_GRP_RMCODE); + OMF_INIT_WANTED_GROUP(2, "BS3GROUPX0TEXT16", "BS3CLASS16X0CODE", "", "BS3X0TEXT16", OMF_REPLACE_GRP_X0CODE); + OMF_INIT_WANTED_GROUP(3, "BS3GROUPX1TEXT16", "BS3CLASS16X1CODE", "", "BS3X1TEXT16", OMF_REPLACE_GRP_X1CODE); + + /* + * Process the OMF records. + */ + while (off + 3 < cbFile) + { + uint8_t bRecType = pbFile[off]; + uint16_t cbRec = RT_MAKE_U16(pbFile[off + 1], pbFile[off + 2]); + if (g_cVerbose > 2) + printf( "%#07x: type=%#04x len=%#06x\n", off, bRecType, cbRec); + if (off + cbRec > cbFile) + return error(pszFile, "Invalid record length at %#x: %#x (cbFile=%#lx)\n", off, cbRec, (unsigned long)cbFile); + + uint32_t offRec = 0; + uint8_t const *pbRec = &pbFile[off + 3]; +#define OMF_CHECK_RET(a_cbReq, a_Name) /* Not taking the checksum into account, so we're good with 1 or 2 byte fields. */ \ + if (offRec + (a_cbReq) <= cbRec) {/*likely*/} \ + else return error(pszFile, "Malformed " #a_Name "! off=%#x offRec=%#x cbRec=%#x cbNeeded=%#x line=%d\n", \ + off, offRec, cbRec, (a_cbReq), __LINE__) +#define OMF_READ_IDX(a_idx, a_Name) \ + do { \ + OMF_CHECK_RET(2, a_Name); \ + a_idx = pbRec[offRec++]; \ + if ((a_idx) & 0x80) \ + a_idx = (((a_idx) & 0x7f) << 8) | pbRec[offRec++]; \ + } while (0) + +#define OMF_READ_U16(a_u16, a_Name) \ + do { \ + OMF_CHECK_RET(4, a_Name); \ + a_u16 = RT_MAKE_U16(pbRec[offRec], pbRec[offRec + 1]); \ + offRec += 2; \ + } while (0) +#define OMF_READ_U32(a_u32, a_Name) \ + do { \ + OMF_CHECK_RET(4, a_Name); \ + a_u32 = RT_MAKE_U32_FROM_U8(pbRec[offRec], pbRec[offRec + 1], pbRec[offRec + 2], pbRec[offRec + 3]); \ + offRec += 4; \ + } while (0) + + switch (bRecType) + { + /* + * Record LNAME records, scanning for FLAT. + */ + case OMF_LNAMES: + while (offRec + 1 < cbRec) + { + uint8_t cch = pbRec[offRec]; + if (offRec + 1 + cch >= cbRec) + return error(pszFile, "Invalid LNAME string length at %#x+3+%#x: %#x (cbFile=%#lx)\n", + off, offRec, cch, (unsigned long)cbFile); + + if (g_cVerbose > 2) + printf(" LNAME[%u]: %-*.*s\n", pOmfStuff->cLNames, cch, cch, &pbRec[offRec + 1]); + + OMF_GROW_TABLE_RET_ERR(char *, pOmfStuff->papchLNames, pOmfStuff->cLNames, 16); + pOmfStuff->papchLNames[pOmfStuff->cLNames] = (char *)&pbRec[offRec]; + + if (IS_OMF_STR_EQUAL_EX(cch, &pbRec[offRec + 1], "FLAT")) + pOmfStuff->fProbably32bit = true; + + if (IS_OMF_STR_EQUAL_EX(cch, &pbRec[offRec + 1], "DEBSYM")) + pOmfStuff->iDebSymNm = pOmfStuff->cLNames; + if (IS_OMF_STR_EQUAL_EX(cch, &pbRec[offRec + 1], "$$SYMBOLS")) + pOmfStuff->iSymbolsNm = pOmfStuff->cLNames; + + unsigned j = RT_ELEMENTS(pOmfStuff->aGroups); + while (j-- > 0) + if ( cch == pOmfStuff->aGroups[j].cchName + && memcmp(&pbRec[offRec + 1], pOmfStuff->aGroups[j].pszName, pOmfStuff->aGroups[j].cchName) == 0) + { + pOmfStuff->aGroups[j].idxName = pOmfStuff->cLNames; + break; + } + + pOmfStuff->cLNames++; + offRec += cch + 1; + } + break; + + /* + * Display external definitions if -v is specified, also check if anything needs mangling. + */ + case OMF_EXTDEF: + while (offRec + 1 < cbRec) + { + uint8_t cch = pbRec[offRec++]; + OMF_CHECK_RET(cch, EXTDEF); + char *pchName = (char *)&pbRec[offRec]; + offRec += cch; + + uint16_t idxType; + OMF_READ_IDX(idxType, EXTDEF); + + if (g_cVerbose > 2) + printf(" EXTDEF [%u]: %-*.*s type=%#x\n", cExtDefs, cch, cch, pchName, idxType); + else if (g_cVerbose > 0) + printf(" U %-*.*s\n", cch, cch, pchName); + + /* Look for g_apszExtDefRenames entries that requires changing. */ + if ( !pOmfStuff->fMayNeedMangling + && cch >= 5 + && cch <= 7 + && pchName[0] == '_' + && pchName[1] == '_' + && ( pchName[2] == 'U' + || pchName[2] == 'I' + || pchName[2] == 'P') + && ( pchName[3] == '4' + || pchName[3] == '8' + || pchName[3] == 'I' + || pchName[3] == 'T') ) + { + pOmfStuff->fMayNeedMangling = true; + } + } + break; + + /* + * Display public names if -v is specified. + */ + case OMF_PUBDEF32: + case OMF_LPUBDEF32: + pOmfStuff->fProbably32bit = true; + RT_FALL_THRU(); + case OMF_PUBDEF16: + case OMF_LPUBDEF16: + if (g_cVerbose > 0) + { + char const chType = bRecType == OMF_PUBDEF16 || bRecType == OMF_PUBDEF32 ? 'T' : 't'; + const char *pszRec = "LPUBDEF"; + if (chType == 'T') + pszRec++; + + uint16_t idxGrp; + OMF_READ_IDX(idxGrp, [L]PUBDEF); + + uint16_t idxSeg; + OMF_READ_IDX(idxSeg, [L]PUBDEF); + + uint16_t uFrameBase = 0; + if (idxSeg == 0) + { + OMF_CHECK_RET(2, [L]PUBDEF); + uFrameBase = RT_MAKE_U16(pbRec[offRec], pbRec[offRec + 1]); + offRec += 2; + } + if (g_cVerbose > 2) + printf(" %s: idxGrp=%#x idxSeg=%#x uFrameBase=%#x\n", pszRec, idxGrp, idxSeg, uFrameBase); + uint16_t const uSeg = idxSeg ? idxSeg : uFrameBase; + + while (offRec + 1 < cbRec) + { + uint8_t cch = pbRec[offRec++]; + OMF_CHECK_RET(cch, [L]PUBDEF); + const char *pchName = (const char *)&pbRec[offRec]; + offRec += cch; + + uint32_t offSeg; + if (bRecType & OMF_REC32) + { + OMF_CHECK_RET(4, [L]PUBDEF); + offSeg = RT_MAKE_U32_FROM_U8(pbRec[offRec], pbRec[offRec + 1], pbRec[offRec + 2], pbRec[offRec + 3]); + offRec += 4; + } + else + { + OMF_CHECK_RET(2, [L]PUBDEF); + offSeg = RT_MAKE_U16(pbRec[offRec], pbRec[offRec + 1]); + offRec += 2; + } + + uint16_t idxType; + OMF_READ_IDX(idxType, [L]PUBDEF); + + if (g_cVerbose > 2) + printf(" %s[%u]: off=%#010x type=%#x %-*.*s\n", pszRec, cPubDefs, offSeg, idxType, cch, cch, pchName); + else if (g_cVerbose > 0) + printf("%04x:%08x %c %-*.*s\n", uSeg, offSeg, chType, cch, cch, pchName); + } + } + break; + + /* + * Must count segment definitions to figure the index of our segment. + */ + case OMF_SEGDEF16: + case OMF_SEGDEF32: + { + OMF_GROW_TABLE_RET_ERR(OMFSEGDEF, pOmfStuff->paSegDefs, pOmfStuff->cSegDefs, 16); + POMFSEGDEF pSegDef = &pOmfStuff->paSegDefs[pOmfStuff->cSegDefs++]; + + OMF_CHECK_RET(1 + (bRecType == OMF_SEGDEF16 ? 2 : 4) + 1 + 1 + 1, SEGDEF); + pSegDef->f32bitRec = bRecType == OMF_SEGDEF32; + pSegDef->bSegAttr = pbRec[offRec++]; + pSegDef->fUse32 = pSegDef->bSegAttr & 1; + if ((pSegDef->bSegAttr >> 5) == 0) + { + /* A=0: skip frame number of offset. */ + OMF_CHECK_RET(3, SEGDEF); + offRec += 3; + } + if (bRecType == OMF_SEGDEF16) + OMF_READ_U16(pSegDef->cbSeg, SEGDEF16); + else + OMF_READ_U32(pSegDef->cbSeg, SEGDEF32); + OMF_READ_IDX(pSegDef->idxName, SEGDEF); + OMF_READ_IDX(pSegDef->idxClass, SEGDEF); + OMF_READ_IDX(pSegDef->idxOverlay, SEGDEF); + OMF_EXPLODE_LNAME(pOmfStuff, pSegDef->idxName, pSegDef->pchName, pSegDef->cchName, SEGDEF); + OMF_EXPLODE_LNAME(pOmfStuff, pSegDef->idxClass, pSegDef->pchClass, pSegDef->cchClass, SEGDEF); + OMF_EXPLODE_LNAME(pOmfStuff, pSegDef->idxOverlay, pSegDef->pchOverlay, pSegDef->cchOverlay, SEGDEF); + break; + } + + /* + * Must count segment definitions to figure the index of our group. + */ + case OMF_GRPDEF: + { + OMF_GROW_TABLE_RET_ERR(OMFGRPDEF, pOmfStuff->paGrpDefs, pOmfStuff->cGrpDefs, 8); + POMFGRPDEF pGrpDef = &pOmfStuff->paGrpDefs[pOmfStuff->cGrpDefs]; + + OMF_READ_IDX(pGrpDef->idxName, GRPDEF); + OMF_EXPLODE_LNAME(pOmfStuff, pGrpDef->idxName, pGrpDef->pchName, pGrpDef->cchName, GRPDEF); + + unsigned j = RT_ELEMENTS(pOmfStuff->aGroups); + while (j-- > 0) + if (pGrpDef->idxName == pOmfStuff->aGroups[j].idxName) + { + pOmfStuff->aGroups[j].idxGroup = pOmfStuff->cGrpDefs; + break; + } + + pGrpDef->cSegDefs = 0; + pGrpDef->paidxSegDefs = NULL; + while (offRec + 2 + 1 <= cbRec) + { + if (pbRec[offRec] != 0xff) + return error(pszFile, "Unsupported GRPDEF member type: %#x\n", pbRec[offRec]); + offRec++; + OMF_GROW_TABLE_RET_ERR(uint16_t, pGrpDef->paidxSegDefs, pGrpDef->cSegDefs, 16); + OMF_READ_IDX(pGrpDef->paidxSegDefs[pGrpDef->cSegDefs], GRPDEF); + pGrpDef->cSegDefs++; + } + pOmfStuff->cGrpDefs++; + break; + } + + /* + * Gather file names. + */ + case OMF_THEADR: /* watcom */ + cchSrcFile = pbRec[offRec++]; + OMF_CHECK_RET(cchSrcFile, OMF_THEADR); + pchSrcFile = (const char *)&pbRec[offRec]; + if (!collectOmfAddFile(pOmfStuff, cchSrcFile, pchSrcFile, &offSrcInfo)) + return false; + break; + + case OMF_COMENT: + { + OMF_CHECK_RET(2, COMENT); + offRec++; /* skip the type (flags) */ + uint8_t bClass = pbRec[offRec++]; + if (bClass == OMF_CCLS_BORLAND_SRC_FILE) /* nasm */ + { + OMF_CHECK_RET(1+1+4, BORLAND_SRC_FILE); + offRec++; /* skip unknown byte */ + cchSrcFile = pbRec[offRec++]; + OMF_CHECK_RET(cchSrcFile + 4, BORLAND_SRC_FILE); + pchSrcFile = (const char *)&pbRec[offRec]; + offRec += cchSrcFile; + if (offRec + 4 + 1 != cbRec) + return error(pszFile, "BAD BORLAND_SRC_FILE record at %#x: %d bytes left\n", + off, cbRec - offRec - 4 - 1); + if (!collectOmfAddFile(pOmfStuff, cchSrcFile, pchSrcFile, &offSrcInfo)) + return false; + break; + } + break; + } + + /* + * Line number conversion. + */ + case OMF_LINNUM16: + case OMF_LINNUM32: + { + uint16_t idxGrp; + OMF_READ_IDX(idxGrp, LINNUM); + uint16_t idxSeg; + OMF_READ_IDX(idxSeg, LINNUM); + + uint16_t iLine; + uint32_t offSeg; + if (bRecType == OMF_LINNUM16) + while (offRec + 4 < cbRec) + { + iLine = RT_MAKE_U16(pbRec[offRec + 0], pbRec[offRec + 1]); + offSeg = RT_MAKE_U16(pbRec[offRec + 2], pbRec[offRec + 3]); + if (!collectOmfAddLine(pOmfStuff, idxSeg, offSeg, iLine, offSrcInfo)) + return false; + offRec += 4; + } + else + while (offRec + 6 < cbRec) + { + iLine = RT_MAKE_U16(pbRec[offRec + 0], pbRec[offRec + 1]); + offSeg = RT_MAKE_U32_FROM_U8(pbRec[offRec + 2], pbRec[offRec + 3], pbRec[offRec + 4], pbRec[offRec + 5]); + if (!collectOmfAddLine(pOmfStuff, idxSeg, offSeg, iLine, offSrcInfo)) + return false; + offRec += 6; + } + if (offRec + 1 != cbRec) + return error(pszFile, "BAD LINNUM record at %#x: %d bytes left\n", off, cbRec - offRec - 1); + break; + } + } + + /* advance */ + off += cbRec + 3; + } + + return true; +#undef OMF_READ_IDX +#undef OMF_CHECK_RET +} + + +/** + * Adds a LNAMES entry (returns existing). + * + * @returns success indicator. + * @param pOmfStuff The OMF stuff. + * @param pszName The name to add. + * @param pidxName Where to return the name index. + */ +static bool omfDetails_AddLName(POMFDETAILS pOmfStuff, const char *pszName, uint16_t *pidxName) +{ + size_t const cchName = strlen(pszName); + + /* + * Check if we've already got the name. + */ + for (unsigned iName = 1; iName < pOmfStuff->cLNames; iName++) + if ( (unsigned char)pOmfStuff->papchLNames[iName][0] == cchName + && memcmp(pOmfStuff->papchLNames[iName] + 1, pszName, cchName) == 0) + { + *pidxName = iName; + return true; + } + + /* + * Not found, append it. + */ + char *pszCopy = (char *)omfDetails_Alloc(pOmfStuff, cchName + 2); + if (!pszCopy) + return false; + *(unsigned char *)&pszCopy[0] = (unsigned char)cchName; + memcpy(pszCopy + 1, pszName, cchName + 1); + + OMF_GROW_TABLE_RET_ERR(char *, pOmfStuff->papchLNames, pOmfStuff->cLNames, 16); + pOmfStuff->papchLNames[pOmfStuff->cLNames] = (char *)pszCopy; + *pidxName = pOmfStuff->cLNames; + pOmfStuff->cLNames++; + return true; +} + + +/** + * Adds a SEGDEF (always adds a new one). + * + * @returns success indicator. + * @param pOmfStuff The OMF stuff. + * @param bSegAttr The OMF segment attributes. + * @param cbSeg The segment size. + * @param idxSegName The LNAMES index of the segment name. + * @param idxSegClas The LNAMES index of the segment class. + * @param idxOverlay The LNAMES index of the overlay name; pass 1. + * @param fRec32 Set if SEGDEF32 should be emitted, clear for SEGDEF16. + * @param pidxSeg Where to return the segment index. + */ +static bool omfDetails_AddSegDef(POMFDETAILS pOmfStuff, uint8_t bSegAttr, uint32_t cbSeg, uint16_t idxSegName, + uint16_t idxSegClass, uint16_t idxOverlay, bool fRec32, uint16_t *pidxSeg) +{ + Assert(cbSeg <= UINT16_MAX || fRec32); + Assert(idxSegName < pOmfStuff->cLNames); + Assert(idxSegClass < pOmfStuff->cLNames); + + OMF_GROW_TABLE_RET_ERR(OMFSEGDEF, pOmfStuff->paSegDefs, pOmfStuff->cSegDefs, 16); + POMFSEGDEF pSegDef = &pOmfStuff->paSegDefs[pOmfStuff->cSegDefs]; + + pSegDef->bSegAttr = bSegAttr; + pSegDef->fUse32 = bSegAttr & 1; + pSegDef->f32bitRec = fRec32; + pSegDef->cbSeg = cbSeg; + pSegDef->idxName = idxSegName; + pSegDef->idxClass = idxSegClass; + pSegDef->idxOverlay = idxOverlay; + + OMF_EXPLODE_LNAME(pOmfStuff, pSegDef->idxName, pSegDef->pchName, pSegDef->cchName, SEGDEF); + OMF_EXPLODE_LNAME(pOmfStuff, pSegDef->idxClass, pSegDef->pchClass, pSegDef->cchClass, SEGDEF); + OMF_EXPLODE_LNAME(pOmfStuff, pSegDef->idxOverlay, pSegDef->pchOverlay, pSegDef->cchOverlay, SEGDEF); + + *pidxSeg = pOmfStuff->cSegDefs; + pOmfStuff->cSegDefs++; + return true; +} + + +/** + * Adds a SEGDEF if not found. + * + * @returns success indicator. + * @param pOmfStuff The OMF stuff. + * @param bSegAttr The OMF segment attributes. + * @param cbSeg The segment size. + * @param idxSegName The LNAMES index of the segment name. + * @param idxSegClas The LNAMES index of the segment class. + * @param idxOverlay The LNAMES index of the overlay name; pass 1. + * @param fRec32 Set if SEGDEF32 should be emitted, clear for SEGDEF16. + * @param pidxSeg Where to return the segment index. + */ +static bool omfDetails_AddSegDefIfNeeded(POMFDETAILS pOmfStuff, uint8_t bSegAttr, uint32_t cbSeg, uint16_t idxSegName, + uint16_t idxSegClass, uint16_t idxOverlay, bool fRec32, uint16_t *pidxSeg) +{ + /* Search for name */ + for (unsigned iSegDef = 1; iSegDef < pOmfStuff->cSegDefs; iSegDef++) + { + POMFSEGDEF pSegDef = &pOmfStuff->paSegDefs[iSegDef]; + if (pSegDef->idxName == idxSegName) + { + if ( pSegDef->bSegAttr != bSegAttr + || pSegDef->f32bitRec != fRec32 + || pSegDef->idxName != idxSegName + || pSegDef->idxClass != idxSegClass + || pSegDef->idxOverlay != idxOverlay) + return error(pOmfStuff->pszFile, + "Existing SEGDEF differs: bSegAttr=%#x vs %#x, f32bitRec=%d vs %d, idxName=%#x vs %#x, idxClass=%#x vs %#x, idxOverlay=%#x vs %#x\n", + pSegDef->bSegAttr, bSegAttr, + pSegDef->f32bitRec, fRec32, + pSegDef->idxName, idxSegName, + pSegDef->idxClass, idxSegClass, + pSegDef->idxOverlay, idxOverlay); + *pidxSeg = iSegDef; + return true; + } + } + return omfDetails_AddSegDef(pOmfStuff, bSegAttr, cbSeg, idxSegName, idxSegClass, idxOverlay, fRec32, pidxSeg); +} + + +#if 0 /* unused */ +/** + * Looks up a GRPDEF in the . + * + * @returns Index (0..32K) if found, UINT16_MAX if not found. + * @param pOmfStuff The OMF stuff. + * @param pchName The name to look up. + * @param cchName The length of the name. + */ +static uint16_t omfDetails_GrpDefLookupN(POMFDETAILS pOmfStuff, const char *pchName, size_t cchName) +{ + unsigned iGrpDef = pOmfStuff->cGrpDefs; + while (iGrpDef-- > 0) + { + if ( pOmfStuff->paGrpDefs[iGrpDef].cchName == cchName + && memcmp(pOmfStuff->paGrpDefs[iGrpDef].pchName, pchName, cchName) == 0) + return iGrpDef; + } + return UINT16_MAX; +} +#endif + + +/** + * Adds an empty GRPDEF (always adds a new one). + * + * @returns success indicator. + * @param pOmfStuff The OMF stuff. + * @param idxGrpName The LNAMES index of the group name. + * @param pidxGrp Where to return the group index. + */ +static bool omfDetails_AddGrpDef(POMFDETAILS pOmfStuff, uint16_t idxGrpName, uint16_t *pidxGrp) +{ + Assert(idxGrpName < pOmfStuff->cLNames); + + OMF_GROW_TABLE_RET_ERR(OMFGRPDEF, pOmfStuff->paGrpDefs, pOmfStuff->cGrpDefs, 8); + POMFGRPDEF pGrpDef = &pOmfStuff->paGrpDefs[pOmfStuff->cGrpDefs]; + + pGrpDef->idxName = idxGrpName; + pGrpDef->cSegDefs = 0; + pGrpDef->paidxSegDefs = NULL; + + *pidxGrp = pOmfStuff->cGrpDefs; + pOmfStuff->cGrpDefs++; + return true; +} + + +/** + * Adds a segment to an existing GRPDEF. + * + * @returns success indicator. + * @param pOmfStuff The OMF stuff. + * @param idxGrp The GRPDEF index of the group to append a member to. + * @param idxSeg The SEGDEF index of the segment name. + */ +static bool omfDetails_AddSegToGrpDef(POMFDETAILS pOmfStuff, uint16_t idxGrp, uint16_t idxSeg) +{ + Assert(idxGrp < pOmfStuff->cGrpDefs && idxGrp > 0); + Assert(idxSeg < pOmfStuff->cSegDefs && idxSeg > 0); + + POMFGRPDEF pGrpDef = &pOmfStuff->paGrpDefs[idxGrp]; + OMF_GROW_TABLE_RET_ERR(uint16_t, pGrpDef->paidxSegDefs, pGrpDef->cSegDefs, 16); + pGrpDef->paidxSegDefs[pGrpDef->cSegDefs] = idxSeg; + pGrpDef->cSegDefs++; + + return true; +} + + +/** + * Marks 16-bit code segment groups that is used in the object file as needed. + * + * @param pOmfStuff The OMF stuff. + */ +static void convertOmfLookForNeededGroups(POMFDETAILS pOmfStuff) +{ + /* + * Consult the groups in question. We mark the groups which segments are + * included in the segment definitions as needed. + */ + unsigned i = RT_ELEMENTS(pOmfStuff->aGroups); + while (i-- > 0) + if (pOmfStuff->aGroups[i].pszSeg) + { + const char * const pszSegNm = pOmfStuff->aGroups[i].pszSeg; + size_t const cchSegNm = strlen(pszSegNm); + for (unsigned iSegDef = 0; iSegDef < pOmfStuff->cSegDefs; iSegDef++) + if ( pOmfStuff->paSegDefs[iSegDef].cchName == cchSegNm + && memcmp(pOmfStuff->paSegDefs[iSegDef].pchName, pszSegNm, cchSegNm) == 0) + { + pOmfStuff->aGroups[i].fNeeded = true; + break; + } + } +} + + +/** + * Adds necessary group and segment definitions. + * + * @returns success indicator. + * @param pOmfStuff The OMF stuff. + */ +static bool convertOmfAddNeededGrpDefs(POMFDETAILS pOmfStuff) +{ + /* + * Process the groups. + */ + unsigned j = RT_ELEMENTS(pOmfStuff->aGroups); + while (j-- > 0) + if (pOmfStuff->aGroups[j].fNeeded) + { + if (pOmfStuff->aGroups[j].idxName == UINT16_MAX) + { + Assert(pOmfStuff->aGroups[j].idxGroup == UINT16_MAX); + if (!omfDetails_AddLName(pOmfStuff, pOmfStuff->aGroups[j].pszName, &pOmfStuff->aGroups[j].idxName)) + return false; + } + if (pOmfStuff->aGroups[j].idxGroup == UINT16_MAX) + { + if (!omfDetails_AddGrpDef(pOmfStuff, pOmfStuff->aGroups[j].idxName, &pOmfStuff->aGroups[j].idxGroup)) + return false; + + if (pOmfStuff->aGroups[j].pszSeg) + { + /* We need the segment class name. */ + uint16_t idxSegClass; + if (!omfDetails_AddLName(pOmfStuff, pOmfStuff->aGroups[j].pszClass1, &idxSegClass)) + return false; + + /* Prep segment name buffer. */ + size_t cchSegNm = strlen(pOmfStuff->aGroups[j].pszSeg); + char szSegNm[256+16]; + Assert(cchSegNm < 256); + memcpy(szSegNm, pOmfStuff->aGroups[j].pszSeg, cchSegNm); + + /* Add the three segments. */ + static RTSTRTUPLE const s_aSuffixes[3] = { {RT_STR_TUPLE("_START")}, {RT_STR_TUPLE("")}, {RT_STR_TUPLE("_END")}, }; + for (unsigned iSuffix = 0; iSuffix < RT_ELEMENTS(s_aSuffixes); iSuffix++) + { + uint16_t idxSegNm; + memcpy(&szSegNm[cchSegNm], s_aSuffixes[iSuffix].psz, s_aSuffixes[iSuffix].cch + 1); + if (!omfDetails_AddLName(pOmfStuff, szSegNm, &idxSegNm)) + return false; + uint8_t const fAlign = iSuffix == 1 ? OMF_SEG_ATTR_ALIGN_BYTE : OMF_SEG_ATTR_ALIGN_PARA; + uint16_t idxSeg; + if (!omfDetails_AddSegDefIfNeeded(pOmfStuff, fAlign | OMF_SEG_ATTR_COMB_PUBLIC | OMF_SEG_ATTR_USE16, + 0, idxSegNm, idxSegClass, 1, false /*fRec*/, &idxSeg)) + return false; + if (!omfDetails_AddSegToGrpDef(pOmfStuff, pOmfStuff->aGroups[j].idxGroup, idxSeg)) + return false; + } + } + } + } + + /* + * Replace group references in the segment lines table. + */ + j = RT_ELEMENTS(pOmfStuff->aGroups); + while (j-- > 0) + if (pOmfStuff->aGroups[j].fNeeded) + for (unsigned i = 0; i < pOmfStuff->cSegLines; i++) + if (pOmfStuff->paSegLines[i].idxGrp == pOmfStuff->aGroups[j].idxReplaceGrp) + pOmfStuff->paSegLines[i].idxGrp = pOmfStuff->aGroups[j].idxGroup; + return true; +} + + +/** + * Adds the debug segment definitions (names too) to the OMF state. + * + * @returns success indicator. + * @param pOmfStuff The OMF stuff with CV8 line number info. + */ +static bool convertOmfAddDebugSegDefs(POMFDETAILS pOmfStuff) +{ + if ( pOmfStuff->cSegLines == 0 + || pOmfStuff->iSymbolsSeg != UINT16_MAX) + return true; + + /* + * Add the names we need. + */ + if ( pOmfStuff->iSymbolsNm == UINT16_MAX + && !omfDetails_AddLName(pOmfStuff, "$$SYMBOLS", &pOmfStuff->iSymbolsNm)) + return false; + if ( pOmfStuff->iDebSymNm == UINT16_MAX + && !omfDetails_AddLName(pOmfStuff, "DEBSYM", &pOmfStuff->iDebSymNm)) + return false; + + /* + * Add the segment definition. + */ + uint8_t bSegAttr = 0; + bSegAttr |= 5 << 5; /* A: dword alignment */ + bSegAttr |= 0 << 2; /* C: private */ + bSegAttr |= 0 << 1; /* B: not big */ + bSegAttr |= 1; /* D: use32 */ + + /* calc the segment size. */ + uint32_t cbSeg = 4; /* dword 4 */ + cbSeg += 4 + 4 + RT_ALIGN_32(pOmfStuff->cbStrTab, 4); + cbSeg += 4 + 4 + pOmfStuff->cSrcInfo * sizeof(pOmfStuff->paSrcInfo[0]); + uint32_t i = pOmfStuff->cSegLines; + while (i-- > 0) + if (pOmfStuff->paSegLines[i].cFiles > 0) + cbSeg += 4 + 4 + pOmfStuff->paSegLines[i].cb; + return omfDetails_AddSegDef(pOmfStuff, bSegAttr, cbSeg, pOmfStuff->iSymbolsNm, pOmfStuff->iDebSymNm, 1 /*idxOverlay*/, + true /*fRec32*/, &pOmfStuff->iSymbolsSeg); +} + + +/** + * Writes the debug segment data. + * + * @returns success indicator. + * @param pThis The OMF writer. + * @param pOmfStuff The OMF stuff with CV8 line number info. + */ +static bool convertOmfWriteDebugData(POMFWRITER pThis, POMFDETAILS pOmfStuff) +{ + if (pOmfStuff->cSegLines == 0) + return true; + Assert(pOmfStuff->iSymbolsSeg != UINT16_MAX); + + /* Begin and write the CV version signature. */ + if ( !omfWriter_LEDataBegin(pThis, pOmfStuff->iSymbolsSeg, 0) + || !omfWriter_LEDataAddU32(pThis, RTCVSYMBOLS_SIGNATURE_CV8)) + return false; + + /* + * Emit the string table (no fixups). + */ + uint32_t cbLeft = pOmfStuff->cbStrTab; + if ( !omfWriter_LEDataAddU32(pThis, RTCV8SYMBLOCK_TYPE_SRC_STR) + || !omfWriter_LEDataAddU32(pThis, cbLeft) + || !omfWriter_LEDataAddBytes(pThis, pOmfStuff->pchStrTab, RT_ALIGN_32(cbLeft, 4)) ) /* table is zero padded to nearest dword */ + return false; + + /* + * Emit the source file info table (no fixups). + */ + cbLeft = pOmfStuff->cSrcInfo * sizeof(pOmfStuff->paSrcInfo[0]); + if ( !omfWriter_LEDataAddU32(pThis, RTCV8SYMBLOCK_TYPE_SRC_INFO) + || !omfWriter_LEDataAddU32(pThis, cbLeft) + || !omfWriter_LEDataAddBytes(pThis, pOmfStuff->paSrcInfo, cbLeft) ) + return false; + + /* + * Emit the segment line numbers. There are two fixups here at the start + * of each chunk. + */ + POMFSEGLINES pSegLines = pOmfStuff->paSegLines; + uint32_t i = pOmfStuff->cSegLines; + while (i-- > 0) + { + if (pSegLines->cFiles) + { + /* Calc covered area. */ + uint32_t cbSectionCovered = 0; + uint32_t j = pSegLines->cFiles; + while (j-- > 0) + { + uint32_t offLast = pSegLines->paFiles[j].paPairs[pSegLines->paFiles[j].cPairs - 1].offSection; + if (offLast > cbSectionCovered) + offLast = cbSectionCovered; + } + + /* For simplicity and debuggability, just split the LEDATA here. */ + if ( !omfWriter_LEDataSplit(pThis) + || !omfWriter_LEDataAddU32(pThis, RTCV8SYMBLOCK_TYPE_SECT_LINES) + || !omfWriter_LEDataAddU32(pThis, pSegLines->cb) + || !omfWriter_LEDataAddU32(pThis, 0) /*RTCV8LINESHDR::offSection*/ + || !omfWriter_LEDataAddU16(pThis, 0) /*RTCV8LINESHDR::iSection*/ + || !omfWriter_LEDataAddU16(pThis, 0) /*RTCV8LINESHDR::u16Padding*/ + || !omfWriter_LEDataAddU32(pThis, cbSectionCovered) /*RTCV8LINESHDR::cbSectionCovered*/ ) + return false; + + /* Default to the segment (BS3TEXT32, BS3TEXT64) or the group (CGROUP16, + RMGROUP16, etc). The important thing is that we're framing the fixups + using a segment or group which ends up in the codeview segment map. */ + uint16_t idxFrame = pSegLines->idxSeg; + uint8_t bFrame = OMF_FIX_F_SEGDEF; + if (pSegLines->idxGrp != UINT16_MAX) + { + idxFrame = pSegLines->idxGrp; + bFrame = OMF_FIX_F_GRPDEF; + } + + /* Fixup #1: segment offset - IMAGE_REL_AMD64_SECREL. */ + if (!omfWriter_LEDataAddFixupNoDisp(pThis, 4 + 4 + RT_UOFFSETOF(RTCV8LINESHDR, offSection), OMF_FIX_LOC_32BIT_OFFSET, + bFrame, idxFrame, OMF_FIX_T_SEGDEF_NO_DISP, pSegLines->idxSeg)) + return false; + + + /* Fixup #2: segment number - IMAGE_REL_AMD64_SECTION. */ + if (!omfWriter_LEDataAddFixupNoDisp(pThis, 4 + 4 + RT_UOFFSETOF(RTCV8LINESHDR, iSection), OMF_FIX_LOC_16BIT_SEGMENT, + bFrame, idxFrame, OMF_FIX_T_SEGDEF_NO_DISP, pSegLines->idxSeg)) + return false; + + /* Emit data for each source file. */ + for (j = 0; j < pSegLines->cFiles; j++) + { + uint32_t const cbPairs = pSegLines->paFiles[j].cPairs * sizeof(RTCV8LINEPAIR); + if ( !omfWriter_LEDataAddU32(pThis, pSegLines->paFiles[j].offSrcInfo) /*RTCV8LINESSRCMAP::offSourceInfo*/ + || !omfWriter_LEDataAddU32(pThis, pSegLines->paFiles[j].cPairs) /*RTCV8LINESSRCMAP::cLines*/ + || !omfWriter_LEDataAddU32(pThis, cbPairs + sizeof(RTCV8LINESSRCMAP)) /*RTCV8LINESSRCMAP::cb*/ + || !omfWriter_LEDataAddBytes(pThis, pSegLines->paFiles[j].paPairs, cbPairs)) + return false; + } + } + pSegLines++; + } + + return omfWriter_LEDataEnd(pThis); +} + + +/** + * Writes out all the segment group definitions. + * + * @returns success indicator. + * @param pThis The OMF writer. + * @param pOmfStuff The OMF stuff containing the segment defs. + * @param pfFlushState Pointer to the flush state variable. + */ +static bool convertOmfWriteAllSegDefs(POMFWRITER pThis, POMFDETAILS pOmfStuff, int *pfFlushState) +{ + if (*pfFlushState > 0) + { + for (unsigned iSegDef = 1; iSegDef < pOmfStuff->cSegDefs; iSegDef++) + { + if (!(pOmfStuff->paSegDefs[iSegDef].f32bitRec + ? omfWriter_SegDef : omfWriter_SegDef16)(pThis, pOmfStuff->paSegDefs[iSegDef].bSegAttr, + pOmfStuff->paSegDefs[iSegDef].cbSeg, + pOmfStuff->paSegDefs[iSegDef].idxName, + pOmfStuff->paSegDefs[iSegDef].idxClass, + pOmfStuff->paSegDefs[iSegDef].idxOverlay)) + return false; + } + *pfFlushState = -1; + } + return true; +} + + +/** + * Writes out all the segment group definitions. + * + * @returns success indicator. + * @param pThis The OMF writer. + * @param pOmfStuff The OMF stuff containing the group defs. + * @param pfFlushState Pointer to the flush state variable. + */ +static bool convertOmfWriteAllGrpDefs(POMFWRITER pThis, POMFDETAILS pOmfStuff, int *pfFlushState) +{ + if (*pfFlushState > 0) + { + for (unsigned iGrpDef = 1; iGrpDef < pOmfStuff->cGrpDefs; iGrpDef++) + { + if (!omfWriter_GrpDefBegin(pThis, pOmfStuff->paGrpDefs[iGrpDef].idxName)) + return false; + for (unsigned iSegDef = 0; iSegDef < pOmfStuff->paGrpDefs[iGrpDef].cSegDefs; iSegDef++) + if (!omfWriter_GrpDefAddSegDef(pThis, pOmfStuff->paGrpDefs[iGrpDef].paidxSegDefs[iSegDef])) + return false; + if (!omfWriter_GrpDefEnd(pThis)) + return false; + } + *pfFlushState = -1; + } + return true; +} + + +/** + * This does the actual converting, passthru style. + * + * It only modifies, removes and inserts stuff it care about, the rest is passed + * thru as-is. + * + * @returns success indicator. + * @param pThis The OMF writer. + * @param pbFile The original file content. + * @param cbFile The size of the original file. + * @param pOmfStuff The OMF stuff we've gathered during the first pass, + * contains CV8 line number info if we converted anything. + * @param fConvertLineNumbers Whether we're converting line numbers and stuff. + */ +static bool convertOmfPassthru(POMFWRITER pThis, uint8_t const *pbFile, size_t cbFile, POMFDETAILS pOmfStuff, + bool fConvertLineNumbers) +{ + int fFlushLNames = 1; + int fFlushSegDefs = 1; + int fFlushGrpDefs = 1; + bool fSeenTheAdr = false; + bool fConvertFixupp = false; + + uint32_t off = 0; + while (off + 3 < cbFile) + { + uint8_t bRecType = pbFile[off]; + uint16_t cbRec = RT_MAKE_U16(pbFile[off + 1], pbFile[off + 2]); + uint32_t offRec = 0; + uint8_t const *pbRec = &pbFile[off + 3]; + +#define OMF_READ_IDX(a_idx, a_Name) \ + do { \ + a_idx = pbRec[offRec++]; \ + if ((a_idx) & 0x80) \ + a_idx = (((a_idx) & 0x7f) << 8) | pbRec[offRec++]; \ + } while (0) + +#define OMF_PEEK_IDX(a_idx, a_offRec) \ + do { \ + a_idx = pbRec[a_offRec]; \ + if ((a_idx) & 0x80) \ + a_idx = (((a_idx) & 0x7f) << 8) | pbRec[(a_offRec) + 1]; \ + } while (0) + + /* + * Remove/insert switch. will + */ + bool fSkip = false; + switch (bRecType) + { + /* + * Mangle watcom intrinsics if necessary. + */ + case OMF_EXTDEF: + if (pOmfStuff->fMayNeedMangling) + { + if (!omfWriter_ExtDefBegin(pThis)) + return false; + while (offRec + 1 < cbRec) + { + uint8_t cchName = pbRec[offRec++]; + char *pchName = (char *)&pbRec[offRec]; + offRec += cchName; + + uint16_t idxType; + OMF_READ_IDX(idxType, EXTDEF); + + /* Look for g_apszExtDefRenames entries that requires changing. */ + if ( cchName >= 5 + && cchName <= 7 + && pchName[0] == '_' + && pchName[1] == '_' + && ( pchName[2] == 'U' + || pchName[2] == 'I' + || pchName[2] == 'P') + && ( pchName[3] == '4' + || pchName[3] == '8' + || pchName[3] == 'I' + || pchName[3] == 'T') ) + { + char szName[12]; + memcpy(szName, pchName, cchName); + szName[cchName] = '\0'; + + uint32_t i = RT_ELEMENTS(g_apszExtDefRenames); + while (i-- > 0) + if ( cchName == (uint8_t)g_apszExtDefRenames[i][0] + && memcmp(&g_apszExtDefRenames[i][1], szName, cchName) == 0) + { + szName[0] = pOmfStuff->fProbably32bit ? '?' : '_'; + szName[1] = '?'; + break; + } + + if (!omfWriter_ExtDefAddN(pThis, szName, cchName, idxType, false /*fPrependUnderscore*/)) + return false; + } + else if (!omfWriter_ExtDefAddN(pThis, pchName, cchName, idxType, false /*fPrependUnderscore*/)) + return false; + } + if (!omfWriter_ExtDefEnd(pThis)) + return false; + fSkip = true; + } + break; + + /* + * Remove line number records. + */ + case OMF_LINNUM16: + case OMF_LINNUM32: + fSkip = fConvertLineNumbers; + break; + + /* + * Remove all but the first OMF_THEADR. + */ + case OMF_THEADR: + fSkip = fSeenTheAdr && fConvertLineNumbers; + fSeenTheAdr = true; + break; + + /* + * Remove borland source file changes. Also, make sure the group + * definitions are written out. + */ + case OMF_COMENT: + if (pbRec[1] == OMF_CCLS_LINK_PASS_SEP) + { + Assert(fFlushSegDefs <= 0); + if ( fFlushGrpDefs > 0 + && !convertOmfWriteAllGrpDefs(pThis, pOmfStuff, &fFlushGrpDefs)) + return false; + } + if (fConvertLineNumbers) + fSkip = pbRec[1] == OMF_CCLS_BORLAND_SRC_FILE; + break; + + /* + * Redo these so the OMF writer is on top of the index thing. + */ + case OMF_LNAMES: + if (fFlushLNames >= 0) + { + if (!omfWriter_LNamesBegin(pThis, false /*fAddZeroEntry*/)) + return false; + if (!fFlushLNames) + { + while (offRec + 1 < cbRec) + { + uint8_t cch = pbRec[offRec]; + const char *pch = (const char *)&pbRec[offRec + 1]; + if (!omfWriter_LNamesAddN(pThis, pch, cch, NULL)) + return false; + offRec += cch + 1; + } + } + else + { + /* Flush all LNAMES in one go. */ + for (unsigned i = 1; i < pOmfStuff->cLNames; i++) + if (!omfWriter_LNamesAddN(pThis, pOmfStuff->papchLNames[i] + 1, *pOmfStuff->papchLNames[i], NULL)) + return false; + fFlushLNames = -1; + } + if (!omfWriter_LNamesEnd(pThis)) + return false; + } + fSkip = true; + break; + + /* + * We may want to flush all the segments when we see the first one. + */ + case OMF_SEGDEF16: + case OMF_SEGDEF32: + fSkip = fFlushSegDefs != 0; + if (!convertOmfWriteAllSegDefs(pThis, pOmfStuff, &fFlushSegDefs)) + return false; + break; + + /* + * We may want to flush all the groups when we see the first one. + */ + case OMF_GRPDEF: + fSkip = fFlushGrpDefs != 0; + if (!convertOmfWriteAllGrpDefs(pThis, pOmfStuff, &fFlushGrpDefs)) + return false; + break; + + /* + * Hook LEDATA to flush groups and figure out when to convert FIXUPP records. + */ + case OMF_LEDATA16: + case OMF_LEDATA32: + if ( fFlushGrpDefs > 0 + && !convertOmfWriteAllGrpDefs(pThis, pOmfStuff, &fFlushGrpDefs)) + return false; + fConvertFixupp = false; +#if 0 + if ( g_f16BitWatcomC + && bRecType == OMF_LEDATA16) + { + /* Check if this is a code segment. */ + uint16_t idxSeg; + OMF_PEEK_IDX(idxSeg, offRec); + + } +#endif + break; + + + /* + * Convert fixups for 16-bit code segments to groups. + * Deals with switch table trouble. + */ + case OMF_FIXUPP16: + if (fConvertFixupp) + { + /* Gave up on this for now, easier to drop the eyecatcher in the _START segments. */ + } + break; + + /* + * Upon seeing MODEND we write out the debug info. + */ + case OMF_MODEND16: + case OMF_MODEND32: + if (fConvertLineNumbers) + if (!convertOmfWriteDebugData(pThis, pOmfStuff)) + return false; + break; + } + + /* + * Pass the record thru, if so was decided. + */ + if (!fSkip) + { + if ( omfWriter_RecBegin(pThis, bRecType) + && omfWriter_RecAddBytes(pThis, pbRec, cbRec) + && omfWriter_RecEnd(pThis, false)) + { /* likely */ } + else return false; + } + + /* advance */ + off += cbRec + 3; + } + + return true; +} + + +/** + * Converts LINNUMs and compiler intrinsics in an OMF object file. + * + * Wlink does a cheesy (to use their own term) job of generating the + * sstSrcModule subsection. It is limited to one file and cannot deal with line + * numbers in different segment. The latter is very annoying in assembly files + * that jumps between segments, these a frequent on crash stacks. + * + * The solution is to convert to the same line number tables that cl.exe /Z7 + * generates for our 64-bit C code, we named that format codeview v8, or CV8. + * Our code codeview debug info reader can deal with this already because of the + * 64-bit code, so Bob's your uncle. + * + * @returns success indicator. + * @param pszFile The name of the file being converted. + * @param pbFile The file content. + * @param cbFile The size of the file content. + * @param pDst The destiation (output) file. + */ +static bool convertOmfToOmf(const char *pszFile, uint8_t const *pbFile, size_t cbFile, FILE *pDst) +{ + bool const fConvertLineNumbers = true; + + /* + * Collect line number information, names, segment defintions, groups definitions and such. + */ + OMFDETAILS OmfStuff; + if (!collectOmfDetails(pszFile, pbFile, cbFile, &OmfStuff)) + return false; + + /* Mark groups for 16-bit code segments used by this object file as needed + so we can reframe fixups to these segments correctly. */ + convertOmfLookForNeededGroups(&OmfStuff); + + /* Add debug segments definitions. */ + bool fRc = true; + if (fConvertLineNumbers) + fRc = convertOmfAddDebugSegDefs(&OmfStuff); + + /* Add any additional group defintions we may need (for 16-bit code segs). */ + if (fRc) + fRc = convertOmfAddNeededGrpDefs(&OmfStuff); + if (fRc) + { + /* + * Instantiate the OMF writer and do pass-thru modifications. + */ + POMFWRITER pThis = omfWriter_Create(pszFile, 0, 0, pDst); + if (pThis) + { + fRc = convertOmfPassthru(pThis, pbFile, cbFile, &OmfStuff, fConvertLineNumbers); + omfWriter_Destroy(pThis); + } + else + fRc = false; + } + + /* + * Cleanup OmfStuff. + */ + uint32_t i = OmfStuff.cSegLines; + while (i-- >0) + { + uint32_t j = OmfStuff.paSegLines[i].cFiles; + while (j-- > 0) + free(OmfStuff.paSegLines[i].paFiles[j].paPairs); + free(OmfStuff.paSegLines[i].paFiles); + } + free(OmfStuff.paSegLines); + free(OmfStuff.paSrcInfo); + free(OmfStuff.pchStrTab); + + while (OmfStuff.pAllocHead) + { + POMFDETAILSALLOC pFreeMe = OmfStuff.pAllocHead; + OmfStuff.pAllocHead = OmfStuff.pAllocHead->pNext; + free(pFreeMe); + } + + return fRc; +} + + +/** + * Does the convertion using convertelf and convertcoff. + * + * @returns exit code (0 on success, non-zero on failure) + * @param pszFile The file to convert. + */ +static int convertit(const char *pszFile) +{ + /* Construct the filename for saving the unmodified file. */ + char szOrgFile[_4K]; + size_t cchFile = strlen(pszFile); + if (cchFile + sizeof(".original") > sizeof(szOrgFile)) + { + error(pszFile, "Filename too long!\n"); + return RTEXITCODE_FAILURE; + } + memcpy(szOrgFile, pszFile, cchFile); + memcpy(&szOrgFile[cchFile], ".original", sizeof(".original")); + + /* Read the whole file. */ + void *pvFile; + size_t cbFile; + if (readfile(pszFile, &pvFile, &cbFile)) + { + /* + * Do format conversions / adjustments. + */ + bool fRc = false; + uint8_t *pbFile = (uint8_t *)pvFile; + if ( cbFile > sizeof(Elf64_Ehdr) + && pbFile[0] == ELFMAG0 + && pbFile[1] == ELFMAG1 + && pbFile[2] == ELFMAG2 + && pbFile[3] == ELFMAG3) + { + if (writefile(szOrgFile, pvFile, cbFile)) + { + FILE *pDst = openfile(pszFile, true /*fWrite*/); + if (pDst) + { + fRc = convertElfToOmf(pszFile, pbFile, cbFile, pDst); + fRc = fclose(pDst) == 0 && fRc; + } + } + } + else if ( cbFile > sizeof(IMAGE_FILE_HEADER) + && RT_MAKE_U16(pbFile[0], pbFile[1]) == IMAGE_FILE_MACHINE_AMD64 + && RT_MAKE_U16(pbFile[2], pbFile[3]) * sizeof(IMAGE_SECTION_HEADER) + sizeof(IMAGE_FILE_HEADER) + < cbFile + && RT_MAKE_U16(pbFile[2], pbFile[3]) > 0) + { + if (writefile(szOrgFile, pvFile, cbFile)) + { + FILE *pDst = openfile(pszFile, true /*fWrite*/); + if (pDst) + { + fRc = convertCoffToOmf(pszFile, pbFile, cbFile, pDst); + fRc = fclose(pDst) == 0 && fRc; + } + } + } + else if ( cbFile >= 8 + && pbFile[0] == OMF_THEADR + && RT_MAKE_U16(pbFile[1], pbFile[2]) < cbFile) + { + if (writefile(szOrgFile, pvFile, cbFile)) + { + FILE *pDst = openfile(pszFile, true /*fWrite*/); + if (pDst) + { + fRc = convertOmfToOmf(pszFile, pbFile, cbFile, pDst); + fRc = fclose(pDst) == 0 && fRc; + } + } + } + else + fprintf(stderr, "error: Don't recognize format of '%s' (%#x %#x %#x %#x, cbFile=%lu)\n", + pszFile, pbFile[0], pbFile[1], pbFile[2], pbFile[3], (unsigned long)cbFile); + free(pvFile); + if (fRc) + return 0; + } + return 1; +} + + +int main(int argc, char **argv) +{ + int rcExit = 0; + + /* + * Scan the arguments. + */ + for (int i = 1; i < argc; i++) + { + if (argv[i][0] == '-') + { + const char *pszOpt = &argv[i][1]; + if (*pszOpt == '-') + { + /* Convert long options to short ones. */ + pszOpt--; + if (!strcmp(pszOpt, "--wcc")) + pszOpt = "w"; + else if (!strcmp(pszOpt, "--verbose")) + pszOpt = "v"; + else if (!strcmp(pszOpt, "--version")) + pszOpt = "V"; + else if (!strcmp(pszOpt, "--help")) + pszOpt = "h"; + else + { + fprintf(stderr, "syntax errro: Unknown options '%s'\n", pszOpt); + return 2; + } + } + + /* Process the list of short options. */ + while (*pszOpt) + { + switch (*pszOpt++) + { + case 'w': + g_f16BitWatcomC = true; + break; + + case 'v': + g_cVerbose++; + break; + + case 'V': + printf("%s\n", "$Revision: 155244 $"); + return 0; + + case '?': + case 'h': + printf("usage: %s [options] -o <output> <input1> [input2 ... [inputN]]\n", + argv[0]); + return 0; + } + } + } + else + { + /* + * File to convert. Do the job right away. + */ + rcExit = convertit(argv[i]); + if (rcExit != 0) + break; + } + } + + return rcExit; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/asmdefs-first.mac b/src/VBox/ValidationKit/bootsectors/bs3kit/asmdefs-first.mac new file mode 100644 index 00000000..54c545fe --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/asmdefs-first.mac @@ -0,0 +1,62 @@ +; $Id: asmdefs-first.mac $ +;; @file +; BS3Kit - Included by asmdefs.mac when assembling IPRT code. +; +; This will only be included if asmdefs.mac is included before bs3kit.mac, so +; it will not be used for bs3*.asm files, only IPRT ones. +; + +; +; Copyright (C) 2006-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +%ifndef ___asmdefs_first_mac +%define ___asmdefs_first_mac + +%include "bs3kit-template-header.mac" + +; +; Redefine some macros to suite us. +; +; We do near 16-bit code and produce far stubs separately as needed. +; +%define BEGINCODE TMPL_BEGIN_TEXT +%define BEGINPROC_EXPORTED BS3_BEGINPROC_EXPORTED_WRAPPER +%define ENDPROC BS3_PROC_END_CMN +%undef NAME +%define NAME(a) BS3_CMN_NM(a) + +%macro BS3_BEGINPROC_EXPORTED_WRAPPER 1-2 0 ; %2 is ignored as we don't do endbr32/64 +BS3_PROC_BEGIN_CMN %1, BS3_PBC_NEAR +%endmacro + +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-bootsector.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-bootsector.asm new file mode 100644 index 00000000..edd26f4d --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-bootsector.asm @@ -0,0 +1,594 @@ +; $Id: bs3-bootsector.asm $ +;; @file +; Generic bootsector for BS3. +; +; This sets up stack at %fff0 and loads the next sectors from the floppy at +; %10000 (1000:0000 in real mode), then starts executing at cs:ip=1000:0000. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit.mac" +%include "iprt/asmdefs.mac" +%include "iprt/x86.mac" + + +;********************************************************************************************************************************* +;* Defined Constants And Macros * +;********************************************************************************************************************************* +;; Enabled faster loading. +%define BS3KIT_BOOTSECTOR_FASTER_LOAD +;; Enabled load progress dots. +%define BS3KIT_BOOTSECTOR_LOAD_DOTS + +;; Halts on failure location. For debugging. +;%define HLT_ON_FAILURE 1 + +;; Enables saving of initial register state. +;; Dropping this is useful for making more room for debugging. +%define BS3KIT_BOOTSECTOR_SAVE_INITIAL_STATE + + +%ifdef __YASM__ +[map all] +%endif + +; +; Start with a jump just to follow the convention. +; Also declare all segments/sections to establish them and their order. +; + ORG 07c00h + +BITS 16 +CPU 8086 +start: + jmp short bs3InitCode + db 0ah ; Should be nop, but this looks better. +g_OemId: ; 003h + db 'BS3Kit', 0ah, 0ah + +; +; DOS 4.0 Extended Bios Parameter Block: +; +g_cBytesPerSector: ; 00bh + dw 512 +g_cSectorsPerCluster: ; 00dh + db 1 +g_cReservedSectors: ; 00eh + dw 1 +g_cFATs: ; 010h + db 0 +g_cRootDirEntries: ; 011h + dw 0 +g_cTotalSectors: ; 013h + dw 0 +g_bMediaDescriptor: ; 015h + db 0 +g_cSectorsPerFAT: ; 016h + dw 0 +g_cPhysSectorsPerTrack: ; 018h + dw 18 +g_cHeads: ; 01ah + dw 2 +g_cHiddentSectors: ; 01ch + dd 1 +g_cLargeTotalSectors: ; 020h - We (ab)use this to indicate the number of sectors to load. + dd 0 +g_bBootDrv: ; 024h + db 80h +g_bFlagsEtc: ; 025h + db 0 +g_bExtendedSignature: ; 026h + db 0x29 +g_dwSerialNumber: ; 027h + dd 0x0a458634 +g_abLabel: ; 02bh + db 'VirtualBox', 0ah +g_abFSType: ; 036h + db 'RawCode', 0ah +g_BpbEnd: ; 03ch + + +; +; Where to real init code starts. +; +bs3InitCode: + cli + +%ifdef BS3KIT_BOOTSECTOR_SAVE_INITIAL_STATE + ; save the registers. + mov [cs:BS3_ADDR_REG_SAVE + BS3REGCTX.rax], ax + mov [cs:BS3_ADDR_REG_SAVE + BS3REGCTX.ds], ds +%endif + + ; set up the DS segment reister so we can skip the CS prefix when saving more prefixes.. + mov ax, 0 + mov ds, ax + +%ifdef BS3KIT_BOOTSECTOR_SAVE_INITIAL_STATE + mov [BS3_ADDR_REG_SAVE + BS3REGCTX.rdi], di + mov di, BS3_ADDR_REG_SAVE + mov [di + BS3REGCTX.rsp], sp + mov [di + BS3REGCTX.ss], ss + mov [di + BS3REGCTX.rcx], cx + mov [di + BS3REGCTX.es], es + mov [di + BS3REGCTX.rbp], bp +%endif + + ; set up the stack. + mov ss, ax + mov sp, BS3_ADDR_STACK + + ; Load es and setup bp frame. + mov es, ax + mov bp, sp +%if 0 + mov [bp], ax ; clear the first 8 bytes (terminates the ebp chain) + mov [bp + 02h], ax + mov [bp + 04h], ax + mov [bp + 06h], ax +%else + mov di, sp ; Combine clearing the rbp chain and register save area. +%endif + + ; Save flags now that we know that there's a valid stack. + pushf + + ; + ; Clear the register area. + ; +%if 0 + mov di, BS3_ADDR_REG_SAVE + mov cx, BS3REGCTX_size/2 +%else + mov cx, (BS3_ADDR_LOAD - BS3_ADDR_STACK) / 2 +%endif + cld + rep stosw + + ; + ; Do basic CPU detection. + ; + + ; 0. Load the register save area address into DI to avoid absolute addressing + ; when saving additional state. To avoid disp16, offset the address. + mov di, BS3_ADDR_REG_SAVE + 0x70 + + ; 1. bit 15-bit was fixed to 1 in pre-286 CPUs, and fixed to 0 in 286+. + mov ax, [bp - 2] + test ah, 080h ; always set on pre 286, clear on 286 and later + jnz .pre_80286 + + ; 2. On a 286 you cannot popf IOPL and NT from real mode. +.detect_286_or_386plus: +CPU 286 + mov ah, (X86_EFL_IOPL | X86_EFL_NT) >> 8 + push ax + popf + pushf + cmp ah, [bp - 3] + pop ax + je .is_386plus +.is_80286: +CPU 286 +%ifdef BS3KIT_BOOTSECTOR_SAVE_INITIAL_STATE + smsw [di + BS3REGCTX.cr0 - 0x70] +%endif +.pre_80286: +CPU 8086 +%ifdef BS3KIT_BOOTSECTOR_SAVE_INITIAL_STATE + mov [di - 0x70 + BS3REGCTX.rbx], bx + mov [di - 0x70 + BS3REGCTX.rdx], dx + mov [di - 0x70 + BS3REGCTX.rsi], si +%endif + jmp .do_load + + ; Save 386 registers. We can now skip the CS prefix as DS is flat. +CPU 386 +.is_386plus: +%ifdef BS3KIT_BOOTSECTOR_SAVE_INITIAL_STATE + shr eax, 16 + mov [di - 0x70 + BS3REGCTX.rax+2], ax + mov eax, esp + shr eax, 16 + mov [di - 0x70 + BS3REGCTX.rsp+2], ax + mov eax, ebp + shr eax, 16 + mov [di - 0x70 + BS3REGCTX.rbp+2], ax + mov eax, edi + shr eax, 16 + mov [di - 0x70 + BS3REGCTX.rdi+2], ax + shr ecx, 16 + mov [di - 0x70 + BS3REGCTX.rcx+2], cx + mov [di - 0x70 + BS3REGCTX.fs], fs + mov [di - 0x70 + BS3REGCTX.gs], gs + mov [di - 0x70 + BS3REGCTX.rbx], ebx + mov [di - 0x70 + BS3REGCTX.rdx], edx + mov [di - 0x70 + BS3REGCTX.rsi], esi + mov eax, cr2 + mov [di - 0x70 + BS3REGCTX.cr2], eax + mov eax, cr3 + mov [di - 0x70 + BS3REGCTX.cr3], eax + mov byte [di - 0x70 + BS3REGCTX.bMode], BS3_MODE_RM + mov [di - 0x70 + BS3REGCTX.cs], cs + xor eax, eax + mov ax, start + mov [di - 0x70 + BS3REGCTX.rip], eax + + ; Pentium/486+: CR4 requires VME/CPUID, so we need to detect that before accessing it. + mov [di - 0x70 + BS3REGCTX.cr4], eax + popf ; (restores IOPL+NT) + pushfd + pop eax + mov [di - 0x70 + BS3REGCTX.rflags], eax + xor eax, X86_EFL_ID + push eax + popfd + pushfd + pop ebx + cmp ebx, eax + jne .no_cr4 + mov eax, cr4 + mov [di - 0x70 + BS3REGCTX.cr4], eax +.no_cr4: +%endif + ; Make sure caching is enabled and alignment is off. + mov eax, cr0 +%ifdef BS3KIT_BOOTSECTOR_SAVE_INITIAL_STATE + mov [di - 0x70 + BS3REGCTX.cr0], eax +%endif + and eax, ~(X86_CR0_NW | X86_CR0_CD | X86_CR0_AM) + mov cr0, eax + + ; Load all the code. +.do_load + mov [g_bBootDrv], dl + call NAME(bs3InitLoadImage) +%if 0 + mov al, '=' + call bs3PrintChrInAl +%endif + + ; + ; Call the user 'main' procedure (shouldn't return). + ; + cld + call BS3_SEL_TEXT16:0000h + + ; Panic/hang. +Bs3Panic: + cli + jmp Bs3Panic + + +;; For debug and error handling. +; @uses ax +bs3PrintHexInAl: +CPU 286 + push ax + shr al, 4 + call bs3PrintHexDigitInAl + pop ax +bs3PrintHexDigitInAl: + and al, 0fh + cmp al, 10 + jb .decimal + add al, 'a' - '0' - 10 +.decimal: + add al, '0' +bs3PrintChrInAl: + push bx + mov ah, 0eh + mov bx, 0ff00h + int 10h + pop bx + ret + + +;; +; Loads the image off the floppy. +; +; This uses g_cLargeTotalSectors to figure out how much to load. +; +; Clobbers everything except ebp and esp. Panics on failure. +; +; @param dl The boot drive number (from BIOS). +; @uses ax, cx, bx, esi, di +; +BEGINPROC bs3InitLoadImage + push bp + mov bp, sp + push es +%define bSavedDiskNo byte [bp - 04h] + push dx +%define bMaxSector byte [bp - 06h] +%define wMaxSector word [bp - 06h] + xor ax, ax + push ax +%define bMaxHead byte [bp - 08h] + push ax + + ; + ; Try figure the geometry. + ; + mov ah, 08h + int 13h +%ifndef HLT_ON_FAILURE + jc .failure +%else + jnc .ok_geometry_call + cli + hlt +.ok_geometry_call: +%endif + and cl, 63 ; only the sector count. + mov bMaxSector, cl + mov bMaxHead, dh + mov dl, bSavedDiskNo + +%if 0 ; bMaxSector=0x12 (18); bMaxHead=0x01; bMaxCylinder=0x4f (79) + mov al, 'S' + call bs3PrintChrInAl + mov al, bMaxSector + call bs3PrintHexInAl + mov al, 'H' + call bs3PrintChrInAl + mov al, bMaxHead + call bs3PrintHexInAl + mov al, 'C' + call bs3PrintChrInAl + mov al, ch ; first 8-bit of cylinder count. + call bs3PrintHexInAl + mov al, ';' + call bs3PrintChrInAl +%endif + +%ifndef BS3KIT_BOOTSECTOR_FASTER_LOAD + ; + ; Load the sectors following the boot sector one at a time (avoids problems). + ; + mov si, [g_cLargeTotalSectors] ; 16-bit sector count ==> max 512 * 65 535 = 33 553 920 bytes. + dec si ; Practically max: ca 575 KB, or 1150 sectors. Linker set BS3_MAX_SIZE to 480KB. + + mov di, BS3_ADDR_LOAD / 16 ; The current load segment. + mov cx, 0002h ; ch/cylinder=0 (0-based); cl/sector=2 (1-based) + xor dh, dh ; dh/head=0 +.the_load_loop: + %if 0 + mov al, 'c' + call bs3PrintChrInAl + mov al, ch + call bs3PrintHexInAl + mov al, 's' + call bs3PrintChrInAl + mov al, cl + call bs3PrintHexInAl + mov al, 'h' + call bs3PrintChrInAl + mov al, dh + call bs3PrintHexInAl + mov al, ';' + call bs3PrintChrInAl + %elifdef BS3KIT_BOOTSECTOR_LOAD_DOTS + mov al, '.' + call bs3PrintChrInAl + %endif + xor bx, bx + mov es, di ; es:bx -> buffer + mov ax, 0201h ; al=1 sector; ah=read function + int 13h + %ifndef HLT_ON_FAILURE + jc .failure + %else + jnc .read_ok + cli + hlt +.read_ok: + %endif + + ; advance to the next sector/head/cylinder. + inc cl + cmp cl, bMaxSector + jbe .adv_addr + + mov cl, 1 + inc dh + cmp dh, bMaxHead + jbe .adv_addr + + mov dh, 0 + inc ch + +.adv_addr: + add di, 512 / 16 + dec si + jnz .the_load_loop + +%else ; BS3KIT_BOOTSECTOR_FASTER_LOAD + ; + ; Load the sectors following the boot sector, trying to load a whole + ; side in each bios call, falling back on single sector reads if we + ; run into DMA 64KB boundrary issues (BIOS must tell us). + ; + mov si, [g_cLargeTotalSectors] ; 16-bit sector count ==> max 512 * 65 535 = 33 553 920 bytes. + dec si ; Skip the boot sector, it's not part of the test image we execute. + mov di, BS3_ADDR_LOAD / 16 ; The current load segment. + mov cx, 0002h ; ch/cylinder=0 (0-based); cl/sector=0 (1-based) + xor dh, dh ; dh/head=0 +.the_load_loop: + %if 0 + mov al, 'c' + call bs3PrintChrInAl + mov al, ch + call bs3PrintHexInAl + mov al, 's' + call bs3PrintChrInAl + mov al, cl + call bs3PrintHexInAl + mov al, 'h' + call bs3PrintChrInAl + mov al, dh + call bs3PrintHexInAl + mov al, ';' + call bs3PrintChrInAl + %elifdef BS3KIT_BOOTSECTOR_LOAD_DOTS + mov al, '.' + call bs3PrintChrInAl + %endif + mov ax, wMaxSector ; read to the end of the side by default. + sub al, cl + inc al +.read_again: + cmp si, ax + jae .do_read + mov ax, si +.do_read: + mov ah, 02h ; ah=read function + xor bx, bx + mov es, di ; es:bx -> buffer + int 13h + jnc .advance_sector + + cmp ah, 9 ; DMA 64KB crossing error +%if 0 ; This hack doesn't work. If the FDC is in single sided mode we end up with a garbled image. Probably "missing" sides. + je .read_one + + cmp ah, 20h ; Controller error, probably because we're reading side 1 on a single sided floppy + jne .failure + cmp bMaxHead, 0 + je .failure + cmp dh, 1 + jne .failure + xor dh, dh + mov bMaxHead, dh + inc ch + jmp .the_load_loop +.read_one: +%elifdef HLT_ON_FAILURE + je .read_one_ok + cli + hlt +.read_one_ok: +%else + jne .failure +%endif + mov ax, 1 ; Retry reading a single sector. + jmp .read_again + + ; advance to the next sector/head/cylinder and address. +.advance_sector: + inc cl + cmp cl, bMaxSector + jbe .adv_addr + + mov cl, 1 + inc dh + cmp dh, bMaxHead + jbe .adv_addr + + mov dh, 0 + inc ch + +.adv_addr: + dec si + jz .done_reading + add di, 512 / 16 + dec al + jnz .advance_sector + jmp .the_load_loop + +.done_reading: +%endif ; BS3KIT_BOOTSECTOR_FASTER_LOAD +%if 0 + mov al, 'D' + call bs3PrintChrInAl +%elifdef BS3KIT_BOOTSECTOR_LOAD_DOTS + mov al, 13 + call bs3PrintChrInAl + mov al, 10 + call bs3PrintChrInAl +%endif + + add sp, 2*2 + pop dx + pop es + pop bp + ret + +%ifndef HLT_ON_FAILURE + ; + ; Something went wrong, display a message. + ; +.failure: + %if 1 ; Disable to save space for debugging. + %if 1 + push ax + %endif + + ; print message + mov si, .s_szErrMsg +.failure_next_char: + lodsb + call bs3PrintChrInAl + cmp si, .s_szErrMsgEnd + jb .failure_next_char + + ; panic + %if 1 + pop ax + mov al, ah + push bs3PrintHexInAl + %endif + call Bs3Panic +.s_szErrMsg: + db 13, 10, 'rd err! ' + %else + hlt + jmp .failure + %endif +%endif +.s_szErrMsgEnd: +;ENDPROC bs3InitLoadImage - don't want the padding. + + +; +; Pad the remainder of the sector with int3's and end it with the DOS signature. +; +bs3Padding: + times ( 510 - ( (bs3Padding - start) % 512 ) ) db 0cch + db 055h, 0aah + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-CreateHybridFarRet.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-CreateHybridFarRet.asm new file mode 100644 index 00000000..ca372f66 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-CreateHybridFarRet.asm @@ -0,0 +1,63 @@ +; $Id: bs3-c16-CreateHybridFarRet.asm $ +;; @file +; BS3Kit - Bs3A20Disable. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +%include "bs3kit.mac" + + +;; +; Worker for BS3_PROC_BEGIN_CMN +; @uses nothing +BS3_PROC_BEGIN Bs3CreateHybridFarRet_c16 + push ax ; reserve space + push bp + mov bp, sp + push ax ; save it + + ; Move the return address up a word. + mov ax, [bp + 4] + mov [bp + 2], ax + ; Move the caller's return address up a word. + mov ax, [bp + 6] + mov [bp + 4], ax + ; Add CS to the caller's far return address. + mov [bp + 6], cs + + pop ax + pop bp + ret +BS3_PROC_END Bs3CreateHybridFarRet_c16 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-SwitchFromV86To16BitAndCallC.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-SwitchFromV86To16BitAndCallC.asm new file mode 100644 index 00000000..5e0fcb90 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-SwitchFromV86To16BitAndCallC.asm @@ -0,0 +1,109 @@ +; $Id: bs3-c16-SwitchFromV86To16BitAndCallC.asm $ +;; @file +; BS3Kit - Bs3SwitchFromV86To16BitAndCallC +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" +%if TMPL_BITS != 16 + %error "16-bit only" +%endif + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +%ifdef BS3_STRICT +BS3_EXTERN_DATA16 g_bBs3CurrentMode +TMPL_BEGIN_TEXT +BS3_EXTERN_CMN Bs3Panic +%endif +BS3_EXTERN_CMN Bs3SwitchTo16Bit +BS3_EXTERN_CMN Bs3SwitchTo16BitV86 +BS3_EXTERN_CMN Bs3SelRealModeCodeToProtMode + + +;; +; @cproto BS3_CMN_PROTO_STUB(int, Bs3SwitchFromV86To16BitAndCallC,(FPFNBS3FAR fpfnCall, unsigned cbParams, ...)); +; +BS3_PROC_BEGIN_CMN Bs3SwitchFromV86To16BitAndCallC, BS3_PBC_HYBRID + inc bp + push bp + mov bp, sp + + ; + ; Push the arguments first. + ; + mov ax, si ; save si + mov si, [bp + 2 + cbCurRetAddr + 4] +%ifdef BS3_STRICT + test si, 1 + jz .cbParams_ok + call Bs3Panic +.cbParams_ok: + test byte [g_bBs3CurrentMode], BS3_MODE_CODE_V86 + jnz .mode_ok + call Bs3Panic +.mode_ok: +%endif + +.push_more: + push word [bp + 2 + cbCurRetAddr + 4 + 2 + si - 2] + sub si, 2 + jnz .push_more + mov si, ax ; restore si + + ; + ; Convert the code segment to a 16-bit prot mode selector + ; + push word [bp + 2 + cbCurRetAddr + 2] + call Bs3SelRealModeCodeToProtMode + mov [bp + 2 + cbCurRetAddr + 2], ax + add sp, 2 + + ; + ; Switch mode. + ; + call Bs3SwitchTo16Bit + call far [bp + 2 + cbCurRetAddr] + call Bs3SwitchTo16BitV86 + + mov sp, bp + pop bp + dec bp + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3SwitchFromV86To16BitAndCallC + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-Trap16Generic.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-Trap16Generic.asm new file mode 100644 index 00000000..3db838a2 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-Trap16Generic.asm @@ -0,0 +1,720 @@ +; $Id: bs3-c16-Trap16Generic.asm $ +;; @file +; BS3Kit - Trap, 16-bit assembly handlers. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + +%ifndef TMPL_16BIT + %error "16-bit only template" +%endif + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_EXTERN_DATA16 g_bBs3CurrentMode +BS3_EXTERN_DATA16 g_uBs3TrapEipHint +BS3_EXTERN_DATA16 g_uBs3CpuDetected +BS3_EXTERN_DATA16 g_apfnBs3TrapHandlers_c16 +BS3_EXTERN_SYSTEM16 Bs3Gdt +TMPL_BEGIN_TEXT +BS3_EXTERN_CMN Bs3TrapDefaultHandler +BS3_EXTERN_CMN Bs3RegCtxRestore +TMPL_BEGIN_TEXT + + +;; +; Generic entry points for IDT handlers, 8 byte spacing. +; +BS3_PROC_BEGIN _Bs3Trap16GenericEntries +BS3_PROC_BEGIN Bs3Trap16GenericEntries +%macro Bs3Trap16GenericEntryNoErr 1 + push byte 0 ; 2 byte: fake error code + db 06ah, i ; 2 byte: push imm8 - note that this is a signextended value. + jmp %1 ; 3 byte + ALIGNCODE(8) +%assign i i+1 +%endmacro + +%macro Bs3Trap16GenericEntryErrCd 1 + db 06ah, i ; 2 byte: push imm8 - note that this is a signextended value. + jmp %1 ; 3 byte + ALIGNCODE(8) +%assign i i+1 +%endmacro + +%assign i 0 ; start counter. + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 0 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 1 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 2 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 3 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 4 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 5 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 6 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 7 + Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; 8 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 9 + Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; a + Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; b + Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; c + Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; d + Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; e + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; f (reserved) + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 10 + Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; 11 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 12 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 13 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 14 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 15 (reserved) + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 16 (reserved) + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 17 (reserved) + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 18 (reserved) + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 19 (reserved) + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 1a (reserved) + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 1b (reserved) + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 1c (reserved) + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 1d (reserved) + Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; 1e + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 1f (reserved) +%rep 224 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt +%endrep +BS3_PROC_END Bs3Trap16GenericEntries +AssertCompile(Bs3Trap16GenericEntries_EndProc - Bs3Trap16GenericEntries == 8*256) + + +;; +; Trap or interrupt with error code, faked if necessary. +; +; Note! This code is going to "misbehave" if the high word of ESP is not cleared. +; +BS3_PROC_BEGIN _bs3Trap16GenericTrapOrInt +BS3_PROC_BEGIN bs3Trap16GenericTrapOrInt +CPU 386 + jmp near bs3Trap16GenericTrapErrCode80286 ; Bs3Trap16Init adjusts this on 80386+ + push ebp + movzx ebp, sp + push ebx ; BP - 04h + pushfd ; BP - 08h + cld + push edx ; BP - 0ch + push ss ; BP - 0eh + push esp ; BP - 12h + + ; + ; We may be comming from 32-bit code where SS is flat and ESP has a non- + ; zero high word. We need to thunk it for C code to work correctly with + ; [BP+xx] and [SS:BX+xx] style addressing that leaves out the high word. + ; + ; Note! Require ring-0 handler for non-standard stacks (SS.DPL must equal CPL). + ; + mov bx, ss + lar ebx, bx + test ebx, X86LAR_F_D + jz .stack_fine + test esp, 0ffff0000h + jnz .stack_thunk +.stack_load_r0_ss16: + mov bx, ss + and bl, 3 + AssertCompile(BS3_SEL_RING_SHIFT == 8) + mov bh, bl + add bx, BS3_SEL_R0_SS16 + jmp .stack_load_bx_into_ss +.stack_thunk: + mov ebx, esp + shr ebx, 16 + shl ebx, X86_SEL_SHIFT + add ebx, BS3_SEL_TILED_R0 + cmp ebx, BS3_SEL_TILED_R0_LAST + ja .stack_esp_out_of_bounds +.stack_load_bx_into_ss: + mov ss, bx +.stack_fine: + movzx esp, sp + + ; Reserve space for the register and trap frame. + mov bx, (BS3TRAPFRAME_size + 7) / 8 +.more_zeroed_space: + push 0 + push 0 + push 0 + push 0 + dec bx + jnz .more_zeroed_space + movzx ebx, sp + + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], eax + mov edx, [bp - 12h] ; This isn't quite right for wrap arounds, but close enough for now + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], edx ; high bits + mov [ss:bx + BS3TRAPFRAME.uHandlerRsp], edx ; high bits + mov dx, [bp - 0eh] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], dx + mov [ss:bx + BS3TRAPFRAME.uHandlerSs], dx + mov edx, [bp - 0ch] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], edx + mov edx, [bp - 8] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], edx ; high bits + mov [ss:bx + BS3TRAPFRAME.fHandlerRfl], edx + mov edx, [bp - 4] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], edx + mov edx, [bp] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], edx + + mov dl, [bp + 4] + mov [ss:bx + BS3TRAPFRAME.bXcpt], dl + + mov dx, [bp + 6] +;; @todo Do voodoo checks for 'int xx' or misguided hardware interrupts. + mov [ss:bx + BS3TRAPFRAME.uErrCd], dx + + add bp, 6 ; adjust so it points to the word before the iret frame. + xor dx, dx + jmp bs3Trap16GenericCommon + +.stack_esp_out_of_bounds: +%ifdef BS3_STRICT + int3 +%endif + jmp .stack_esp_out_of_bounds +BS3_PROC_END bs3Trap16GenericTrapErrCode + +;; +; Trap with error code - 80286 code variant. +; +BS3_PROC_BEGIN bs3Trap16GenericTrapErrCode80286 +CPU 286 + push bp + mov bp, sp + push bx + pushf + cld + + ; Reserve space for the register and trap frame. + mov bx, (BS3TRAPFRAME_size + 7) / 8 +.more_zeroed_space: + push 0 + push 0 + push 0 + push 0 + dec bx + jnz .more_zeroed_space + mov bx, sp + + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], ax + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], ss + mov [ss:bx + BS3TRAPFRAME.uHandlerSs], ss + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], dx + mov dx, [bp - 4] + mov [ss:bx + BS3TRAPFRAME.fHandlerRfl], dx + mov dx, [bp - 2] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], dx + mov dx, [bp] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], dx + + mov dl, [bp + 2] + mov [ss:bx + BS3TRAPFRAME.bXcpt], dl + + mov dx, [bp + 4] +;; @todo Do voodoo checks for 'int xx' or misguided hardware interrupts. + mov [ss:bx + BS3TRAPFRAME.uErrCd], dx + + add bp, 4 ; adjust so it points to the word before the iret frame. + mov dl, 1 + jmp bs3Trap16GenericCommon +BS3_PROC_END bs3Trap16GenericTrapErrCode80286 + + +;; +; Common context saving code and dispatching. +; +; @param bx Pointer to the trap frame, zero filled. The following members +; have been filled in by the previous code: +; - bXcpt +; - uErrCd +; - fHandlerRFL +; - Ctx.eax +; - Ctx.edx +; - Ctx.ebx +; - Ctx.ebp +; - Ctx.rflags - high bits only. +; - Ctx.esp - high bits only. +; - Ctx.ss - for same cpl frames +; - All other bytes are zeroed. +; +; @param bp Pointer to the word before the iret frame, i.e. where bp +; would be saved if this was a normal near call. +; @param dx One (1) if 286, zero (0) if 386+. +; +BS3_PROC_BEGIN bs3Trap16GenericCommon +CPU 286 + ; + ; Fake EBP frame. + ; + mov ax, [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp] + mov [bp], ax + + ; + ; Save the remaining GPRs and segment registers. + ; + test dx, dx + jnz .save_word_grps +CPU 386 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], ecx + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], edi + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], esi + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fs], fs + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.gs], gs + jmp .save_segment_registers +.save_word_grps: +CPU 286 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], cx + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], di + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], si +.save_segment_registers: + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ds], ds + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.es], es + mov [ss:bx + BS3TRAPFRAME.uHandlerCs], cs + + ; + ; Load 16-bit data selector for the DPL we're executing at into DS and ES. + ; + mov ax, ss + and ax, 3 + mov cx, ax + shl ax, BS3_SEL_RING_SHIFT + or ax, cx + add ax, BS3_SEL_R0_DS16 + mov ds, ax + mov es, ax + + ; + ; Copy and update the mode now that we've got a flat DS. + ; + mov al, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bMode], al + mov cl, al + and cl, ~BS3_MODE_CODE_MASK + or cl, BS3_MODE_CODE_16 + mov [BS3_DATA16_WRT(g_bBs3CurrentMode)], cl + + ; + ; Copy iret info. + ; + lea cx, [bp + 2] + mov [ss:bx + BS3TRAPFRAME.uHandlerRsp], cx + mov cx, [bp + 2] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rip], cx + mov cx, [bp + 6] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], cx + mov cx, [bp + 4] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cs], cx + + test al, BS3_MODE_CODE_V86 + jnz .iret_frame_v8086 + + mov ax, ss + and al, 3 + and cl, 3 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bCpl], cl + cmp cl, al + je .iret_frame_same_cpl + +.ret_frame_different_cpl: + mov cx, [bp + 10] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], cx + mov cx, [bp + 8] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], cx + mov byte [ss:bx + BS3TRAPFRAME.cbIretFrame], 5*2 + test dx, dx + jnz .iret_frame_done + jmp .iret_frame_seed_high_eip_word + +.iret_frame_same_cpl: ; (ss and high bits was saved by CPU specific part) + lea cx, [bp + 8] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], cx + mov byte [ss:bx + BS3TRAPFRAME.cbIretFrame], 3*2 + test dx, dx + jnz .iret_frame_done + jmp .iret_frame_seed_high_eip_word + +.iret_frame_v8086: +CPU 386 + or dword [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], X86_EFL_VM + mov byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bCpl], 3 + or byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bMode], BS3_MODE_CODE_V86 ; paranoia ^ 2 +%if 0 ;; @todo testcase: high ESP word from V86 mode, 16-bit TSS. + movzx ecx, word [bp + 8] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], ecx +%else + mov cx, word [bp + 8] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], cx +%endif + mov cx, [bp + 10] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], cx + mov cx, [bp + 12] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.es], cx + mov cx, [bp + 14] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ds], cx + mov cx, [bp + 16] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fs], cx + mov cx, [bp + 18] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.gs], cx + mov byte [ss:bx + BS3TRAPFRAME.cbIretFrame], 9*2 + jmp .iret_frame_done + + ; + ; For 386 we do special tricks to supply the high word of EIP when + ; arriving here from 32-bit code. (ESP was seeded earlier.) + ; +.iret_frame_seed_high_eip_word: + lar eax, [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cs] + jnz .iret_frame_done + test eax, X86LAR_F_D + jz .iret_frame_done + mov ax, [g_uBs3TrapEipHint+2] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rip + 2], ax + +.iret_frame_done: + ; + ; Control registers. + ; + str [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.tr] + sldt [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ldtr] + test dx, dx + jnz .save_286_control_registers +.save_386_control_registers: +CPU 386 + mov ax, ss + test al, 3 + jnz .skip_crX_because_cpl_not_0 + mov eax, cr0 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0], eax + mov eax, cr2 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr2], eax + mov eax, cr3 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr3], eax + + test byte [1 + BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_CPUID >> 8) ; CR4 first appeared in later 486es. + jz .skip_cr4_because_not_there + mov eax, cr4 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr4], eax + jmp .set_flags + +.skip_cr4_because_not_there: + mov byte [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR4 + jmp .set_flags + +.skip_crX_because_cpl_not_0: + or byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], \ + BS3REG_CTX_F_NO_CR2_CR3 | BS3REG_CTX_F_NO_CR4 | BS3REG_CTX_F_NO_CR0_IS_MSW + +CPU 286 +.save_286_control_registers: + smsw [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0] + +.set_flags: ; The double fault code joins us here. + or byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_AMD64 + + ; + ; Dispatch it to C code. + ; +.dispatch_to_handler: + mov di, bx + mov bl, byte [ss:bx + BS3TRAPFRAME.bXcpt] + mov bh, 0 + shl bx, 1 + mov bx, [bx + BS3_DATA16_WRT(_g_apfnBs3TrapHandlers_c16)] + or bx, bx + jnz .call_handler + mov bx, Bs3TrapDefaultHandler +.call_handler: + push ss + push di + call bx + + ; + ; Resume execution using trap frame. + ; + push 0 + push ss + add di, BS3TRAPFRAME.Ctx + push di + call Bs3RegCtxRestore +.panic: + hlt + jmp .panic +BS3_PROC_END bs3Trap16GenericCommon + + +;; +; Helper. +; +; @retruns Flat address in es:di. +; @param di +; @uses eax +; +bs3Trap16TssInDiToFar1616InEsDi: +CPU 286 + push ax + + ; ASSUME Bs3Gdt is being used. + push BS3_SEL_SYSTEM16 + pop es + and di, 0fff8h + add di, Bs3Gdt wrt BS3SYSTEM16 + + ; Load the TSS base into ax:di (di is low, ax high) + mov al, [es:di + (X86DESCGENERIC_BIT_OFF_BASE_HIGH1 / 8)] + mov ah, [es:di + (X86DESCGENERIC_BIT_OFF_BASE_HIGH2 / 8)] + mov di, [es:di + (X86DESCGENERIC_BIT_OFF_BASE_LOW / 8)] + + ; Convert ax to tiled selector, if not within the tiling area we read + ; random BS3SYSTEM16 bits as that's preferable to #GP'ing. + shl ax, X86_SEL_SHIFT + cmp ax, BS3_SEL_TILED_LAST - BS3_SEL_TILED +%ifdef BS3_STRICT + jbe .tiled + int3 +%endif + ja .return ; don't crash again. +.tiled: + add ax, BS3_SEL_TILED + mov es, ax +.return: + pop ax + ret + + +;; +; Double fault handler. +; +; We don't have to load any selectors or clear anything in EFLAGS because the +; TSS specified sane values which got loaded during the task switch. +; +; @param dx Zero (0) for indicating 386+ to the common code. +; +BS3_PROC_BEGIN _Bs3Trap16DoubleFaultHandler80386 +BS3_PROC_BEGIN Bs3Trap16DoubleFaultHandler80386 +CPU 386 + push 0 ; We'll copy the rip from the other TSS here later to create a more sensible call chain. + push ebp + mov bp, sp + pushfd ; Handler flags. + + ; Reserve space for the register and trap frame. + mov bx, (BS3TRAPFRAME_size + 15) / 16 +.more_zeroed_space: + push dword 0 + push dword 0 + push dword 0 + push dword 0 + dec bx + jz .more_zeroed_space + mov bx, sp + + ; + ; Fill in the high GRP register words before we mess them up. + ; + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], eax + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], ebx + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], ecx + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], edx + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], esi + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], edi + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], ebp + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], esp + + ; + ; FS and GS are not part of the 16-bit TSS because they are 386+ specfic. + ; + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fs], fs + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.gs], gs + + ; + ; Fill in the non-context trap frame bits. + ; + mov ecx, [bp - 4] + mov [ss:bx + BS3TRAPFRAME.fHandlerRfl], ecx + mov byte [ss:bx + BS3TRAPFRAME.bXcpt], X86_XCPT_DF + mov [ss:bx + BS3TRAPFRAME.uHandlerCs], cs + mov [ss:bx + BS3TRAPFRAME.uHandlerSs], ss + mov ecx, esp + lea cx, [bp + 8] + mov [ss:bx + BS3TRAPFRAME.uHandlerRsp], ecx + mov cx, [bp + 6] + mov [ss:bx + BS3TRAPFRAME.uErrCd], cx + + ; + ; Copy 80386+ control registers. + ; + mov ecx, cr0 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0], ecx + mov ecx, cr2 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr2], ecx + mov ecx, cr3 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr3], ecx + + test byte [1 + BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_CPUID >> 8) ; CR4 first appeared in later 486es. + jz .skip_cr4_because_not_there + mov ecx, cr4 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr4], ecx + jmp .common + +.skip_cr4_because_not_there: + mov byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR4 + + ; + ; Copy the register state from the previous task segment. + ; The 80286 code with join us here. + ; +.common: +CPU 286 + ; Find our TSS. + str di + call bs3Trap16TssInDiToFar1616InEsDi + + ; Find the previous TSS. + mov di, [es:di + X86TSS32.selPrev] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.tr], ax + call bs3Trap16TssInDiToFar1616InEsDi + + ; Do the copying. + mov cx, [es:di + X86TSS16.ax] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], cx + mov cx, [es:di + X86TSS16.cx] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], cx + mov cx, [es:di + X86TSS16.dx] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], cx + mov cx, [es:di + X86TSS16.bx] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], cx + mov cx, [es:di + X86TSS16.sp] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], cx + mov cx, [es:di + X86TSS16.bp] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], cx + mov [bp], cx ; For better call stacks. + mov cx, [es:di + X86TSS16.si] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], cx + mov cx, [es:di + X86TSS16.di] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], cx + mov cx, [es:di + X86TSS16.si] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], cx + mov cx, [es:di + X86TSS16.flags] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], cx + mov cx, [es:di + X86TSS16.ip] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rip], cx + mov [bp + 2], cx ; For better call stacks. + mov cx, [es:di + X86TSS16.cs] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cs], cx + mov cx, [es:di + X86TSS16.ds] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ds], cx + mov cx, [es:di + X86TSS16.es] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.es], cx + mov cx, [es:di + X86TSS16.ss] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], cx + mov cx, [es:di + X86TSS16.selLdt] ; Note! This isn't necessarily the ldtr at the time of the fault. + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ldtr], cx + + ; + ; Set CPL; copy and update mode. + ; + mov cl, [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss] + and cl, 3 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bCpl], cl + + mov cl, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bMode], cl + and cl, ~BS3_MODE_CODE_MASK + or cl, BS3_MODE_CODE_16 + mov [BS3_DATA16_WRT(g_bBs3CurrentMode)], cl + + ; + ; Join code paths with the generic handler code. + ; + jmp bs3Trap16GenericCommon.set_flags +BS3_PROC_END Bs3Trap16DoubleFaultHandler + + +;; +; Double fault handler. +; +; We don't have to load any selectors or clear anything in EFLAGS because the +; TSS specified sane values which got loaded during the task switch. +; +; @param dx One (1) for indicating 386+ to the common code. +; +BS3_PROC_BEGIN _Bs3Trap16DoubleFaultHandler80286 +BS3_PROC_BEGIN Bs3Trap16DoubleFaultHandler80286 +CPU 286 + push 0 ; We'll copy the rip from the other TSS here later to create a more sensible call chain. + push bp + mov bp, sp + pushf ; Handler flags. + + ; Reserve space for the register and trap frame. + mov bx, (BS3TRAPFRAME_size + 7) / 8 +.more_zeroed_space: + push 0 + push 0 + push 0 + push 0 + dec bx + jz .more_zeroed_space + mov bx, sp + + ; + ; Fill in the non-context trap frame bits. + ; + mov cx, [bp - 2] + mov [ss:bx + BS3TRAPFRAME.fHandlerRfl], cx + mov byte [ss:bx + BS3TRAPFRAME.bXcpt], X86_XCPT_DF + mov [ss:bx + BS3TRAPFRAME.uHandlerCs], cs + mov [ss:bx + BS3TRAPFRAME.uHandlerSs], ss + lea cx, [bp + 8] + mov [ss:bx + BS3TRAPFRAME.uHandlerRsp], cx + mov cx, [bp + 6] + mov [ss:bx + BS3TRAPFRAME.uErrCd], cx + + ; + ; Copy 80286 specific control register. + ; + smsw [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0] + + jmp Bs3Trap16DoubleFaultHandler80386.common +BS3_PROC_END Bs3Trap16DoubleFaultHandler80286 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-TrapRmV86Data.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-TrapRmV86Data.c new file mode 100644 index 00000000..6398157f --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-TrapRmV86Data.c @@ -0,0 +1,53 @@ +/* $Id: bs3-c16-TrapRmV86Data.c $ */ +/** @file + * BS3Kit - Real mode and V86 trap data. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +#if ARCH_BITS == 16 +/** Copy of the original real-mode interrupt vector table. */ +RTFAR16 g_aBs3RmIvtOriginal[256]; +/** Indicates whether we've copied the real-mode IVT or not. */ +bool g_fBs3RmIvtCopied = false; +#endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-TrapRmV86Generic.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-TrapRmV86Generic.asm new file mode 100644 index 00000000..017f112a --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-TrapRmV86Generic.asm @@ -0,0 +1,401 @@ +; $Id: bs3-c16-TrapRmV86Generic.asm $ +;; @file +; BS3Kit - Trap, 16-bit assembly handlers for real mode and v8086. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + +%ifndef TMPL_16BIT + %error "16-bit only template" +%endif + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_EXTERN_DATA16 g_bBs3CurrentMode +BS3_EXTERN_DATA16 g_uBs3TrapEipHint +BS3_EXTERN_DATA16 g_uBs3CpuDetected +BS3_EXTERN_DATA16 g_apfnBs3TrapHandlers_c16 +TMPL_BEGIN_TEXT +BS3_EXTERN_CMN Bs3TrapDefaultHandler +BS3_EXTERN_CMN Bs3RegCtxRestore +TMPL_BEGIN_TEXT + + +;; +; Generic entry points for IDT handlers, 8 byte spacing. +; +BS3_PROC_BEGIN _Bs3TrapRmV86GenericEntries +BS3_PROC_BEGIN Bs3TrapRmV86GenericEntries +%macro Bs3TrapRmV86GenericEntryNoErr 1 + push ax ; 1 byte: Reserve space for fake error cd. (BP(+2) + 4) + push ax ; 1 byte: Save AX (BP(+2) + 2) + mov ax, i | 00000h ; 2 bytes: AL = trap/interrupt number; AH=indicate no error code + jmp %1 ; 3 bytes: Jump to handler code + ALIGNCODE(8) +%assign i i+1 +%endmacro + +%macro Bs3TrapRmV86GenericEntryErrCd 1 + Bs3TrapRmV86GenericEntryNoErr %1 ; No error code pushed in real mode or V86 mode. +%endmacro + +%assign i 0 ; start counter. + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 0 + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 1 + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 2 + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 3 + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 4 + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 5 + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 6 + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 7 + Bs3TrapRmV86GenericEntryErrCd bs3TrapRmV86GenericTrapOrInt ; 8 + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 9 + Bs3TrapRmV86GenericEntryErrCd bs3TrapRmV86GenericTrapOrInt ; a + Bs3TrapRmV86GenericEntryErrCd bs3TrapRmV86GenericTrapOrInt ; b + Bs3TrapRmV86GenericEntryErrCd bs3TrapRmV86GenericTrapOrInt ; c + Bs3TrapRmV86GenericEntryErrCd bs3TrapRmV86GenericTrapOrInt ; d + Bs3TrapRmV86GenericEntryErrCd bs3TrapRmV86GenericTrapOrInt ; e + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; f (reserved) + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 10 + Bs3TrapRmV86GenericEntryErrCd bs3TrapRmV86GenericTrapOrInt ; 11 + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 12 + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 13 + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 14 + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 15 (reserved) + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 16 (reserved) + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 17 (reserved) + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 18 (reserved) + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 19 (reserved) + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 1a (reserved) + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 1b (reserved) + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 1c (reserved) + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 1d (reserved) + Bs3TrapRmV86GenericEntryErrCd bs3TrapRmV86GenericTrapOrInt ; 1e + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt ; 1f (reserved) +%rep 224 + Bs3TrapRmV86GenericEntryNoErr bs3TrapRmV86GenericTrapOrInt +%endrep +BS3_PROC_END Bs3TrapRmV86GenericEntries +AssertCompile(Bs3TrapRmV86GenericEntries_EndProc - Bs3TrapRmV86GenericEntries == 8*256) + + +;; +; Trap or interrupt with error code, faked if necessary. +; +; early 386+ stack (movzx ebp, sp): +; [bp + 000h] ebp +; [bp + 004h] ax +; [bp + 006h] errcd [bp'+0] <--- bp at jmp to common code. +; [bp + 008h] cs [bp'+2] +; [bp + 00ah] ip [bp'+4] +; [bp + 00ch] flags [bp'+6] +; ([bp + 00eh] post-iret sp value) [bp'+8] +; +BS3_PROC_BEGIN _bs3TrapRmV86GenericTrapOrInt +BS3_PROC_BEGIN bs3TrapRmV86GenericTrapOrInt +CPU 386 + jmp near bs3TrapRmV86GenericTrapErrCode8086 ; Bs3TrapRmV86Init adjusts this on 80386+ + push ebp + movzx ebp, sp + push ebx ; BP - 04h + pushfd ; BP - 08h + cld + push edx ; BP - 0ch + push ss ; BP - 0eh + push esp ; BP - 12h + + ; Reserve space for the register and trap frame. + mov bx, (BS3TRAPFRAME_size + 7) / 8 +.more_zeroed_space: + push 0 + push 0 + push 0 + push 0 + dec bx + jnz .more_zeroed_space + movzx ebx, sp + + + mov edx, [bp - 12h] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], edx ; high bits + mov [ss:bx + BS3TRAPFRAME.uHandlerRsp], edx ; high bits + mov dx, [bp - 0eh] + mov [ss:bx + BS3TRAPFRAME.uHandlerSs], dx + mov edx, [bp - 0ch] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], edx + mov edx, [bp - 8] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], edx ; high bits + mov [ss:bx + BS3TRAPFRAME.fHandlerRfl], edx + mov edx, [bp - 4] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], edx + mov edx, [bp] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], edx + mov edx, eax ; high bits + mov dx, [bp + 4] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], edx + + mov [ss:bx + BS3TRAPFRAME.bXcpt], al + + test ah, 0ffh + jz .no_error_code + mov dx, [bp + 6] + mov [ss:bx + BS3TRAPFRAME.uErrCd], dx +.no_error_code: + + add bp, 6 ; adjust so it points to the word before the iret frame. + xor dx, dx + jmp bs3TrapRmV86GenericCommon +BS3_PROC_END bs3TrapRmV86GenericTrapErrCode + +;; +; Trap with error code - 8086/V20/80186/80286 code variant. +; +BS3_PROC_BEGIN bs3TrapRmV86GenericTrapErrCode8086 +CPU 8086 + push bp + mov bp, sp + push bx ; BP - 2 + pushf ; BP - 4 + push ax ; BP - 6 + cld + + ; Reserve space for the register and trap frame. + mov bx, (BS3TRAPFRAME_size + 7) / 8 + xor ax, ax +.more_zeroed_space: + push ax + push ax + push ax + push ax + dec bx + jnz .more_zeroed_space + mov bx, sp + + mov [ss:bx + BS3TRAPFRAME.uHandlerSs], ss + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], dx + mov dx, [bp - 4] + mov [ss:bx + BS3TRAPFRAME.fHandlerRfl], dx + mov dx, [bp - 2] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], dx + mov dx, [bp] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], dx + + mov dx, [bp + 2] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], dx + + mov ax, [bp - 6] + mov [ss:bx + BS3TRAPFRAME.bXcpt], al + + test ah, 0ffh + jz .no_error_code + mov dx, [bp + 4] + mov [ss:bx + BS3TRAPFRAME.uErrCd], dx +.no_error_code: + + add bp, 4 ; adjust so it points to the word before the iret frame. + mov dl, 1 + jmp bs3TrapRmV86GenericCommon +BS3_PROC_END bs3TrapRmV86GenericTrapErrCode8086 + + +;; +; Common context saving code and dispatching. +; +; @param ss:bx Pointer to the trap frame, zero filled. The following members +; have been filled in by the previous code: +; - bXcpt +; - uErrCd +; - fHandlerRFL +; - Ctx.eax +; - Ctx.edx +; - Ctx.ebx +; - Ctx.ebp +; - Ctx.rflags - high bits only. +; - Ctx.esp - high bits only. +; - All other bytes are zeroed. +; +; @param bp Pointer to the word before the iret frame, i.e. where bp +; would be saved if this was a normal near call. +; @param dx One (1) if 286, zero (0) if 386+. +; +BS3_PROC_BEGIN bs3TrapRmV86GenericCommon +CPU 8086 + ; + ; Fake EBP frame. + ; + mov ax, [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp] + mov [bp], ax + + ; + ; Save the remaining GPRs and segment registers. + ; + test dx, dx + jnz .save_word_grps +CPU 386 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], ecx + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], edi + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], esi + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fs], fs + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.gs], gs + jmp .save_segment_registers +.save_word_grps: +CPU 8086 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], cx + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], di + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], si +.save_segment_registers: + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ds], ds + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.es], es + mov [ss:bx + BS3TRAPFRAME.uHandlerCs], cs + + ; + ; Load 16-bit BS3KIT_GRPNM_DATA16 into DS and ES so we can access globals. + ; + mov ax, BS3KIT_GRPNM_DATA16 + mov ds, ax + mov es, ax + + ; + ; Copy the mode now that we've got a flat DS. We don't need to update + ; it as it didn't change. + ; + mov al, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bMode], al + + ; + ; Copy iret info. + ; + lea cx, [bp + 2] + mov [ss:bx + BS3TRAPFRAME.uHandlerRsp], cx + mov cx, [bp + 2] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rip], cx + mov cx, [bp + 6] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], cx + mov cx, [bp + 4] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cs], cx + mov cx, ss + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], cx + lea cx, [bp + 8] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], cx + mov byte [ss:bx + BS3TRAPFRAME.cbIretFrame], 3*2 + + ; The VM flag and CPL. + test al, BS3_MODE_CODE_V86 + jz .dont_set_vm + or byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags + 2], X86_EFL_VM >> 16 + mov byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bCpl], 3 +.dont_set_vm: + + + ; + ; Control registers. + ; + ; Since we're in real or v8086 here, we cannot save TR and LDTR. + ; But get MSW (CR0) first since that's always accessible and we + ; need it even on a 386 to check whether we're in v8086 mode or not. + ; + cmp byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80286 + jb .skip_control_registers_because_80186_or_older +CPU 286 + smsw ax + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0], ax + + test dx, dx + jnz .set_flags +.save_386_control_registers: +CPU 386 + ; 386 control registers are not accessible from virtual 8086 mode. + test al, X86_CR0_PE + jnz .skip_crX_because_v8086 + mov eax, cr0 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0], eax + mov eax, cr2 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr2], eax + mov eax, cr3 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr3], eax + + test byte [1 + BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_CPUID >> 8) ; CR4 first appeared in later 486es. + jz .skip_cr4_because_not_there + mov eax, cr4 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr4], eax + jmp .set_flags + +.skip_cr4_because_not_there: + mov byte [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR4 + jmp .set_flags + +CPU 8086 +.skip_control_registers_because_80186_or_older: +.skip_crX_because_v8086: + or byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], \ + BS3REG_CTX_F_NO_CR0_IS_MSW | BS3REG_CTX_F_NO_CR2_CR3 | BS3REG_CTX_F_NO_CR4 +.set_flags: ; The double fault code joins us here. + or byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_AMD64 | BS3REG_CTX_F_NO_TR_LDTR + + ; + ; Dispatch it to C code. + ; +.dispatch_to_handler: + mov di, bx + mov bl, byte [ss:bx + BS3TRAPFRAME.bXcpt] + mov bh, 0 + shl bx, 1 + mov bx, [bx + BS3_DATA16_WRT(_g_apfnBs3TrapHandlers_c16)] + or bx, bx + jnz .call_handler + mov bx, Bs3TrapDefaultHandler +.call_handler: + push ss + push di + call bx + + ; + ; Resume execution using trap frame. + ; + xor ax, ax + push ax + push ss + add di, BS3TRAPFRAME.Ctx + push di + call Bs3RegCtxRestore +.panic: + hlt + jmp .panic +BS3_PROC_END bs3TrapRmV86GenericCommon + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c32-Trap32Generic.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c32-Trap32Generic.asm new file mode 100644 index 00000000..3f25a5f2 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c32-Trap32Generic.asm @@ -0,0 +1,546 @@ +; $Id: bs3-c32-Trap32Generic.asm $ +;; @file +; BS3Kit - Trap, 32-bit assembly handlers. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + +%ifndef TMPL_32BIT + %error "32-bit only template" +%endif + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_EXTERN_DATA16 g_bBs3CurrentMode +BS3_EXTERN_DATA16 g_uBs3CpuDetected +BS3_EXTERN_DATA16 g_apfnBs3TrapHandlers_c32 +BS3_EXTERN_SYSTEM16 Bs3Gdt +TMPL_BEGIN_TEXT +BS3_EXTERN_CMN Bs3TrapDefaultHandler +BS3_EXTERN_CMN Bs3RegCtxRestore +TMPL_BEGIN_TEXT + + +;********************************************************************************************************************************* +;* Global Variables * +;********************************************************************************************************************************* +BS3_BEGIN_DATA16 +;; Easy to access flat address of Bs3Trap32GenericEntries. +BS3_GLOBAL_DATA g_Bs3Trap32GenericEntriesFlatAddr, 4 + dd Bs3Trap32GenericEntries wrt FLAT +;; Easy to access flat address of Bs3Trap32DoubleFaultHandler. +BS3_GLOBAL_DATA g_Bs3Trap32DoubleFaultHandlerFlatAddr, 4 + dd Bs3Trap32DoubleFaultHandler wrt FLAT + + +TMPL_BEGIN_TEXT + +;; +; Generic entry points for IDT handlers, 8 byte spacing. +; +BS3_PROC_BEGIN Bs3Trap32GenericEntries +%macro Bs3Trap32GenericEntryNoErr 1 + push byte 0 ; 2 byte: fake error code. + db 06ah, i ; 2 byte: push imm8 - note that this is a signextended value. + jmp near %1 ; 5 byte + ALIGNCODE(2) +%assign i i+1 +%endmacro + +%macro Bs3Trap32GenericEntryErrCd 1 + db 06ah, i ; 2 byte: push imm8 - note that this is a signextended value. + jmp near %1 ; 5 byte + db 0cch, 0cch ; 2 byte: padding. + ALIGNCODE(2) +%assign i i+1 +%endmacro + +%assign i 0 ; start counter. + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 0 + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 1 + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 2 + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 3 + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 4 + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 5 + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 6 + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 7 + Bs3Trap32GenericEntryErrCd bs3Trap32GenericTrapOrInt ; 8 + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 9 + Bs3Trap32GenericEntryErrCd bs3Trap32GenericTrapOrInt ; a + Bs3Trap32GenericEntryErrCd bs3Trap32GenericTrapOrInt ; b + Bs3Trap32GenericEntryErrCd bs3Trap32GenericTrapOrInt ; c + Bs3Trap32GenericEntryErrCd bs3Trap32GenericTrapOrInt ; d + Bs3Trap32GenericEntryErrCd bs3Trap32GenericTrapOrInt ; e + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; f (reserved) + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 10 + Bs3Trap32GenericEntryErrCd bs3Trap32GenericTrapOrInt ; 11 + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 12 + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 13 + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 14 + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 15 (reserved) + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 16 (reserved) + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 17 (reserved) + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 18 (reserved) + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 19 (reserved) + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 1a (reserved) + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 1b (reserved) + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 1c (reserved) + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 1d (reserved) + Bs3Trap32GenericEntryErrCd bs3Trap32GenericTrapOrInt ; 1e + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 1f (reserved) +%rep 224 + Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt +%endrep +BS3_PROC_END Bs3Trap32GenericEntries +AssertCompile(Bs3Trap32GenericEntries_EndProc - Bs3Trap32GenericEntries == 10*256) + + +;; +; Trap or interrupt with error code, faked if necessary. +; +BS3_PROC_BEGIN bs3Trap32GenericTrapOrInt + push ebp ; 0 + mov ebp, esp + pushfd ; -04h + cld + push eax ; -08h + push edi ; -0ch + lea eax, [esp + (4+1+1)*4] ; 4 pushes above, 1 exception number push, 1 error code. + push eax ; -10h = handler ESP + add eax, 3*4 ; 3 dword iret frame + push eax ; -14h = caller ESP if same CPL + push ss ; -18h + push ds ; -1ch + + ; Make sure we've got a flat DS. It makes everything so much simpler. + mov ax, ss + and al, 3 + AssertCompile(BS3_SEL_RING_SHIFT == 8) + mov ah, al + add ax, BS3_SEL_R0_DS32 + mov ds, ax + + ; + ; We may be comming from 16-bit code with a 16-bit SS. Thunk it as + ; the C code may assume flat SS and we'll mess up by using EBP/ESP/EDI + ; instead of BP/SP/SS:DI. ASSUMES standard GDT selector. + ; + mov ax, ss + lar eax, ax + test eax, X86LAR_F_D + jz .stack_thunk + mov ax, ss + and al, 3 + AssertCompile(BS3_SEL_RING_SHIFT == 8) + mov ah, al + add ax, BS3_SEL_R0_SS32 + mov ss, ax + jmp .stack_flat +.stack_thunk: + mov di, ss + and edi, X86_SEL_MASK_OFF_RPL + mov al, [X86DESCGENERIC_BIT_OFF_BASE_HIGH1 / 8 + edi + Bs3Gdt wrt FLAT] + mov ah, [X86DESCGENERIC_BIT_OFF_BASE_HIGH2 / 8 + edi + Bs3Gdt wrt FLAT] + shl eax, 16 + mov ax, [X86DESCGENERIC_BIT_OFF_BASE_LOW / 8 + edi + Bs3Gdt wrt FLAT] ; eax = SS.base + movzx ebp, bp ; SS:BP -> flat EBP. + add ebp, eax + movzx edi, sp ; SS:SP -> flat ESP in EAX. + add edi, eax + mov ax, ss + and al, 3 + AssertCompile(BS3_SEL_RING_SHIFT == 8) + mov ah, al + add ax, BS3_SEL_R0_SS32 + mov ss, ax + mov esp, edi + sub dword [ebp - 10h], (4+1)*4 ; Recalc handler ESP in case of wraparound. + add word [ebp - 10h], (4+1)*4 + sub dword [ebp - 10h], (4+1+3)*4 ; Recalc caller ESP in case of wraparound. + add word [ebp - 10h], (4+1+3)*4 +.stack_flat: + + ; Reserve space for the register and trap frame. + mov eax, (BS3TRAPFRAME_size + 7) / 8 +AssertCompileSizeAlignment(BS3TRAPFRAME, 8) +.more_zeroed_space: + push dword 0 + push dword 0 + dec eax + jnz .more_zeroed_space + mov edi, esp ; edi points to trapframe structure. + + ; Copy stuff from the stack over. + mov eax, [ebp + 8] +;; @todo Do voodoo checks for 'int xx' or misguided hardware interrupts. + mov [edi + BS3TRAPFRAME.uErrCd], eax + mov al, [ebp + 4] + mov [edi + BS3TRAPFRAME.bXcpt], al + mov eax, [ebp] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], eax + mov eax, [ebp - 04h] + mov [edi + BS3TRAPFRAME.fHandlerRfl], eax + mov eax, [ebp - 08h] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], eax + mov eax, [ebp - 0ch] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], eax + mov eax, [ebp - 10h] + mov [edi + BS3TRAPFRAME.uHandlerRsp], eax + mov eax, [ebp - 14h] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], eax + mov ax, [ebp - 18h] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], ax + mov [edi + BS3TRAPFRAME.uHandlerSs], ax + mov ax, [ebp - 1ch] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ds], ax + + lea ebp, [ebp + 8] ; iret - 4 (i.e. ebp frame chain location) + jmp bs3Trap32GenericCommon +BS3_PROC_END bs3Trap32GenericTrapErrCode + + +;; +; Common context saving code and dispatching. +; +; @param edi Pointer to the trap frame. The following members have been +; filled in by the previous code: +; - bXcpt +; - uErrCd +; - fHandlerRfl +; - uHandlerRsp +; - uHandlerSs +; - Ctx.rax +; - Ctx.rbp +; - Ctx.rdi +; - Ctx.rsp - assuming same CPL +; - Ctx.ds +; - Ctx.ss +; +; @param ebp Pointer to the dword before the iret frame, i.e. where ebp +; would be saved if this was a normal call. +; +; @remarks This is a separate function for hysterical raisins. +; +BS3_PROC_BEGIN bs3Trap32GenericCommon + ; + ; Fake EBP frame. + ; + mov eax, [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp] + mov [ebp], eax + + ; + ; Save the remaining GPRs and segment registers. + ; + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], ecx + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], edx + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], ebx + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], esi + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.es], es + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.fs], fs + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.gs], gs + + ; + ; Load 32-bit data selector for the DPL we're executing at into DS and ES. + ; Save the handler CS value first. + ; + mov ax, cs + mov [edi + BS3TRAPFRAME.uHandlerCs], ax + and al, 3 + AssertCompile(BS3_SEL_RING_SHIFT == 8) + mov ah, al + add ax, BS3_SEL_R0_DS32 + mov ds, ax + mov es, ax + + ; + ; Copy and update the mode now that we've got a flat DS. + ; + mov al, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.bMode], al + and al, ~BS3_MODE_CODE_MASK + or al, BS3_MODE_CODE_32 + mov [BS3_DATA16_WRT(g_bBs3CurrentMode)], al + + ; + ; Copy iret info. + ; + mov ecx, [ebp + 4] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rip], ecx + mov ecx, [ebp + 12] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], ecx + mov cx, [ebp + 8] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.cs], cx + test dword [ebp + 12], X86_EFL_VM + jnz .iret_frame_v8086 + mov ax, ss + and al, 3 + and cl, 3 + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.bCpl], cl + cmp cl, al + je .iret_frame_same_cpl + +.iret_frame_different_cpl: + mov ecx, [ebp + 16] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], ecx + mov cx, [ebp + 20] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], cx + mov byte [edi + BS3TRAPFRAME.cbIretFrame], 5*4 + jmp .iret_frame_done + +.iret_frame_v8086: + mov byte [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.bCpl], 3 + or byte [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.bMode], BS3_MODE_CODE_V86 ; paranoia ^ 2 + mov ecx, [ebp + 16] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], ecx + mov cx, [ebp + 20] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], cx + mov cx, [ebp + 24] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.es], cx + mov cx, [ebp + 28] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ds], cx + mov cx, [ebp + 32] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.fs], cx + mov cx, [ebp + 36] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.gs], cx + mov byte [edi + BS3TRAPFRAME.cbIretFrame], 9*4 + jmp .iret_frame_done + +.iret_frame_same_cpl: ; (caller already set SS:RSP and uHandlerRsp for same CPL iret frames) + mov byte [edi + BS3TRAPFRAME.cbIretFrame], 3*4 + +.iret_frame_done: + ; + ; Control registers. + ; + str ax + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.tr], ax + sldt ax + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ldtr], ax + + mov ax, ss + test al, 3 + jnz .skip_crX_because_cpl_not_0 + + mov eax, cr3 + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.cr3], eax +.save_cr0_cr2_cr4: ; The double fault code joins us here. + mov eax, cr0 + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0], eax + mov eax, cr2 + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.cr2], eax + + test byte [1 + BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_CPUID >> 8) ; CR4 first appeared in later 486es. + jz .skip_cr4_because_not_there + mov eax, cr4 + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.cr4], eax + jmp .set_flags + +.skip_cr4_because_not_there: + mov byte [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR4 + jmp .set_flags + +.skip_crX_because_cpl_not_0: + or byte [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], \ + BS3REG_CTX_F_NO_CR0_IS_MSW | BS3REG_CTX_F_NO_CR2_CR3 | BS3REG_CTX_F_NO_CR4 + smsw [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0] +.set_flags: + or byte [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_AMD64 + + ; + ; Dispatch it to C code. + ; +.dispatch_to_handler: + movzx ebx, byte [edi + BS3TRAPFRAME.bXcpt] + mov eax, [ebx * 4 + BS3_DATA16_WRT(_g_apfnBs3TrapHandlers_c32)] + or eax, eax + jnz .call_handler + mov eax, Bs3TrapDefaultHandler +.call_handler: + push edi + call eax + + ; + ; Resume execution using trap frame. + ; + push 0 + add edi, BS3TRAPFRAME.Ctx + push edi + call Bs3RegCtxRestore +.panic: + hlt + jmp .panic +BS3_PROC_END bs3Trap32GenericCommon + + +;; +; Helper. +; +; @retruns Flat address in eax. +; @param ax +; @uses eax +; +bs3Trap32TssInAxToFlatInEax: + ; Get the GDT base address and find the descriptor address (EAX) + sub esp, 8+2 + sgdt [esp] + and eax, 0fff8h + add eax, [esp + 2] ; GDT base address. + add esp, 8+2 + + ; Get the flat TSS address from the descriptor. + mov al, [eax + (X86DESCGENERIC_BIT_OFF_BASE_HIGH1 / 8)] + mov ah, [eax + (X86DESCGENERIC_BIT_OFF_BASE_HIGH2 / 8)] + shl eax, 16 + mov ax, [eax + (X86DESCGENERIC_BIT_OFF_BASE_LOW / 8)] + ret + +;; +; Double fault handler. +; +; We don't have to load any selectors or clear anything in EFLAGS because the +; TSS specified sane values which got loaded during the task switch. +; +BS3_PROC_BEGIN Bs3Trap32DoubleFaultHandler + push 0 ; We'll copy the rip from the other TSS here later to create a more sensible call chain. + push ebp + mov ebp, esp + + pushfd ; Get handler flags. + pop ecx + + xor edx, edx ; NULL register. + + ; + ; Allocate a zero filled trap frame. + ; + mov eax, (BS3TRAPFRAME_size + 7) / 8 +AssertCompileSizeAlignment(BS3TRAPFRAME, 8) +.more_zeroed_space: + push edx + push edx + dec eax + jz .more_zeroed_space + mov edi, esp + + ; + ; Fill in the non-context trap frame bits. + ; + mov [edi + BS3TRAPFRAME.fHandlerRfl], ecx + mov word [edi + BS3TRAPFRAME.bXcpt], X86_XCPT_DF + mov [edi + BS3TRAPFRAME.uHandlerCs], cs + mov [edi + BS3TRAPFRAME.uHandlerSs], ss + lea ecx, [ebp + 3*4] ; two pushes, one error code. + mov [edi + BS3TRAPFRAME.uHandlerRsp], ecx + mov ecx, [ebp + 8] + mov [edi + BS3TRAPFRAME.uErrCd], ecx + + ; + ; Copy the register state from the previous task segment. + ; + + ; Find our TSS. + str ax + call bs3Trap32TssInAxToFlatInEax + + ; Find the previous TSS. + mov ax, [eax + X86TSS32.selPrev] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.tr], ax + call bs3Trap32TssInAxToFlatInEax + + ; Do the copying. + mov ecx, [eax + X86TSS32.eax] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], ecx + mov ecx, [eax + X86TSS32.ecx] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], ecx + mov ecx, [eax + X86TSS32.edx] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], ecx + mov ecx, [eax + X86TSS32.ebx] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], ecx + mov ecx, [eax + X86TSS32.esp] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], ecx + mov ecx, [eax + X86TSS32.ebp] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], ecx + mov [ebp], ecx ; For better call stacks. + mov ecx, [eax + X86TSS32.esi] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], ecx + mov ecx, [eax + X86TSS32.edi] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], ecx + mov ecx, [eax + X86TSS32.esi] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], ecx + mov ecx, [eax + X86TSS32.eflags] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], ecx + mov ecx, [eax + X86TSS32.eip] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rip], ecx + mov [ebp + 4], ecx ; For better call stacks. + mov cx, [eax + X86TSS32.cs] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.cs], cx + mov cx, [eax + X86TSS32.ds] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ds], cx + mov cx, [eax + X86TSS32.es] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.es], cx + mov cx, [eax + X86TSS32.fs] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.fs], cx + mov cx, [eax + X86TSS32.gs] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.gs], cx + mov cx, [eax + X86TSS32.ss] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], cx + mov cx, [eax + X86TSS32.selLdt] ; Note! This isn't necessarily the ldtr at the time of the fault. + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ldtr], cx + mov cx, [eax + X86TSS32.cr3] ; Note! This isn't necessarily the cr3 at the time of the fault. + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.cr3], ecx + + ; + ; Set CPL; copy and update mode. + ; + mov cl, [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ss] + and cl, 3 + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.bCpl], cl + + mov cl, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.bMode], cl + and cl, ~BS3_MODE_CODE_MASK + or cl, BS3_MODE_CODE_32 + mov [BS3_DATA16_WRT(g_bBs3CurrentMode)], cl + + ; + ; Join code paths with the generic handler code. + ; + jmp bs3Trap32GenericCommon.save_cr0_cr2_cr4 +BS3_PROC_END Bs3Trap32DoubleFaultHandler + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c64-Trap64Generic.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c64-Trap64Generic.asm new file mode 100644 index 00000000..13e0ea27 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c64-Trap64Generic.asm @@ -0,0 +1,337 @@ +; $Id: bs3-c64-Trap64Generic.asm $ +;; @file +; BS3Kit - Trap, 64-bit assembly handlers. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + +%ifndef TMPL_64BIT + %error "64-bit only template" +%endif + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_EXTERN_DATA16 g_bBs3CurrentMode +BS3_EXTERN_DATA16 g_apfnBs3TrapHandlers_c64 +TMPL_BEGIN_TEXT +BS3_EXTERN_CMN Bs3TrapDefaultHandler +BS3_EXTERN_CMN Bs3RegCtxRestore +TMPL_BEGIN_TEXT + + +;********************************************************************************************************************************* +;* Global Variables * +;********************************************************************************************************************************* +BS3_BEGIN_DATA16 +;; Easy to access flat address of Bs3Trap64GenericEntries. +BS3_GLOBAL_DATA g_Bs3Trap64GenericEntriesFlatAddr, 4 + dd Bs3Trap64GenericEntries wrt FLAT + + +TMPL_BEGIN_TEXT + +;; +; Generic entry points for IDT handlers, 8 byte spacing. +; +BS3_PROC_BEGIN Bs3Trap64GenericEntries +%macro Bs3Trap64GenericEntry 1 + db 06ah, i ; push imm8 - note that this is a signextended value. + jmp %1 + ALIGNCODE(8) +%assign i i+1 +%endmacro + +%assign i 0 ; start counter. + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 0 + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 1 + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 2 + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 3 + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 4 + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 5 + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 6 + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 7 + Bs3Trap64GenericEntry Bs3Trap64GenericTrapErrCode ; 8 + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 9 + Bs3Trap64GenericEntry Bs3Trap64GenericTrapErrCode ; a + Bs3Trap64GenericEntry Bs3Trap64GenericTrapErrCode ; b + Bs3Trap64GenericEntry Bs3Trap64GenericTrapErrCode ; c + Bs3Trap64GenericEntry Bs3Trap64GenericTrapErrCode ; d + Bs3Trap64GenericEntry Bs3Trap64GenericTrapErrCode ; e + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; f (reserved) + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 10 + Bs3Trap64GenericEntry Bs3Trap64GenericTrapErrCode ; 11 + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 12 + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 13 + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 14 + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 15 (reserved) + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 16 (reserved) + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 17 (reserved) + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 18 (reserved) + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 19 (reserved) + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 1a (reserved) + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 1b (reserved) + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 1c (reserved) + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 1d (reserved) + Bs3Trap64GenericEntry Bs3Trap64GenericTrapErrCode ; 1e + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt ; 1f (reserved) +%rep 224 + Bs3Trap64GenericEntry Bs3Trap64GenericTrapOrInt +%endrep +BS3_PROC_END Bs3Trap64GenericEntries + + + + +;; +; Trap or interrupt (no error code). +; +BS3_PROC_BEGIN Bs3Trap64GenericTrapOrInt + push rbp ; 0 + mov rbp, rsp + pushfq ; -08h + cld + push rdi + + ; Reserve space for the register and trap frame. + mov edi, (BS3TRAPFRAME_size + 15) / 16 +.more_zeroed_space: + push qword 0 + push qword 0 + dec edi + jnz .more_zeroed_space + mov rdi, rsp ; rdi points to trapframe structure. + + ; Free up rax. + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], rax + + ; Copy stuff from the stack over. + mov al, [rbp + 08h] + mov [rdi + BS3TRAPFRAME.bXcpt], al + mov rax, [rbp] + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], rax + mov rax, [rbp - 08h] + mov [rdi + BS3TRAPFRAME.fHandlerRfl], rax + mov rax, [rbp - 10h] + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], rax + + lea rbp, [rbp + 08h] ; iret - 8 (i.e. rbp frame chain location) + jmp Bs3Trap64GenericCommon +BS3_PROC_END Bs3Trap64GenericTrapOrInt + + +;; +; Trap with error code. +; +BS3_PROC_BEGIN Bs3Trap64GenericTrapErrCode + push rbp ; 0 + mov rbp, rsp + pushfq ; -08h + cld + push rdi + + ; Reserve space for the register and trap frame. + mov edi, (BS3TRAPFRAME_size + 15) / 16 +.more_zeroed_space: + push qword 0 + push qword 0 + dec edi + jnz .more_zeroed_space + mov rdi, rsp ; rdi points to trapframe structure. + + ; Free up rax. + mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], rax + + ; Copy stuff from the stack over. + mov rax, [rbp + 10h] + mov [rdi + BS3TRAPFRAME.uErrCd], rax + mov al, [rbp + 08h] + mov [rdi + BS3TRAPFRAME.bXcpt], al + mov rax, [rbp] + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], rax + mov rax, [rbp - 08h] + mov [rdi + BS3TRAPFRAME.fHandlerRfl], rax + mov rax, [rbp - 10h] + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], rax + + lea rbp, [rbp + 10h] ; iret - 8 (i.e. rbp frame chain location) + jmp Bs3Trap64GenericCommon +BS3_PROC_END Bs3Trap64GenericTrapErrCode + + +;; +; Common context saving code and dispatching. +; +; @param rdi Pointer to the trap frame. The following members have been +; filled in by the previous code: +; - bXcpt +; - uErrCd +; - fHandlerRfl +; - Ctx.rax +; - Ctx.rbp +; - Ctx.rdi +; +; @param rbp Pointer to the dword before the iret frame, i.e. where rbp +; would be saved if this was a normal call. +; +BS3_PROC_BEGIN Bs3Trap64GenericCommon + ; + ; Fake RBP frame. + ; + mov rax, [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp] + mov [rbp], rax + + ; + ; Save the remaining GPRs and segment registers. + ; + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], rcx + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], rdx + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], rbx + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], rsi + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.r8 ], r8 + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.r9 ], r9 + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.r10], r10 + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.r11], r11 + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.r12], r12 + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.r13], r13 + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.r14], r14 + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.r15], r15 + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.ds], ds + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.es], es + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.fs], fs + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.gs], gs + lea rax, [rbp + 8h] + mov [rdi + BS3TRAPFRAME.uHandlerRsp], rax + mov [rdi + BS3TRAPFRAME.uHandlerSs], ss + + ; + ; Load 32-bit data selector for the DPL we're executing at into DS, ES and SS. + ; Save the handler CS value first. + ; + mov ax, cs + mov [rdi + BS3TRAPFRAME.uHandlerCs], ax + AssertCompile(BS3_SEL_RING_SHIFT == 8) + and al, 3 + mov ah, al + add ax, BS3_SEL_R0_DS64 + mov ds, ax + mov es, ax + mov ss, ax + + ; + ; Copy and update the mode. + ; + mov al, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.bMode], al + and al, ~BS3_MODE_CODE_MASK + or al, BS3_MODE_CODE_64 + mov [BS3_DATA16_WRT(g_bBs3CurrentMode)], al + + ; + ; Copy iret info. Bless AMD for only doing one 64-bit iret frame layout. + ; + mov rcx, [rbp + 08] + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.rip], rcx + mov cx, [rbp + 10h] + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.cs], cx + and cl, 3 + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.bCpl], cl + mov rcx, [rbp + 18h] + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], rcx + mov rcx, [rbp + 20h] + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], rcx + mov cx, [rbp + 28h] + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], cx + mov byte [rdi + BS3TRAPFRAME.cbIretFrame], 5*8 + + ; + ; Control registers. + ; + str ax + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.tr], ax + sldt ax + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.ldtr], ax + + mov ax, ss + test al, 3 + jnz .skip_crX_because_cpl_not_0 + + mov rax, cr0 + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0], rax + mov rax, cr2 + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.cr2], rax + mov rax, cr3 + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.cr3], rax + mov rax, cr4 + mov [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.cr4], rax + jmp .dispatch_to_handler + +.skip_crX_because_cpl_not_0: + or byte [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], \ + BS3REG_CTX_F_NO_CR0_IS_MSW | BS3REG_CTX_F_NO_CR2_CR3 | BS3REG_CTX_F_NO_CR4 + smsw [rdi + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0] + + ; + ; Dispatch it to C code. + ; +.dispatch_to_handler: ; The double fault code joins us here. + movzx ebx, byte [rdi + BS3TRAPFRAME.bXcpt] + lea rax, [BS3_DATA16_WRT(_g_apfnBs3TrapHandlers_c64)] + mov rax, [rax + rbx * 8] + or rax, rax + jnz .call_handler + lea rax, [BS3_WRT_RIP(Bs3TrapDefaultHandler)] +.call_handler: + sub rsp, 20h + mov [rsp], rdi + mov rcx, rdi + call rax + + ; + ; Resume execution using trap frame. + ; + xor edx, edx ; fFlags + mov [rsp + 8], rdx + lea rcx, [rdi + BS3TRAPFRAME.Ctx] ; pCtx + mov [rsp], rcx + call Bs3RegCtxRestore +.panic: + hlt + jmp .panic +BS3_PROC_END Bs3Trap64GenericCommon + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-A20Disable.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-A20Disable.asm new file mode 100644 index 00000000..f4caca1d --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-A20Disable.asm @@ -0,0 +1,115 @@ +; $Id: bs3-cmn-A20Disable.asm $ +;; @file +; BS3Kit - Bs3A20Disable. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3KbdWait +BS3_EXTERN_CMN Bs3KbdRead +BS3_EXTERN_CMN Bs3KbdWrite + + +;; +; Disables the A20 gate. +; +; @uses Nothing. +; +BS3_PROC_BEGIN_CMN Bs3A20Disable, BS3_PBC_HYBRID_0_ARGS + ; Must call both because they may be ORed together on real HW. +BONLY64 sub rsp, 20h + call BS3_CMN_NM(Bs3A20DisableViaKbd) + call BS3_CMN_NM(Bs3A20DisableViaPortA) +BONLY64 add rsp, 20h + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3A20Disable + + +;; +; Disables the A20 gate via control port A (PS/2 style). +; +; @uses Nothing. +; +BS3_PROC_BEGIN_CMN Bs3A20DisableViaPortA, BS3_PBC_HYBRID_0_ARGS + push xAX + + ; Use Control port A, assuming a PS/2 style system. + in al, 092h + test al, 02h + jz .done ; avoid trouble writing back the same value. + and al, 0fdh ; disable the A20 gate. + out 092h, al + +.done: + pop xAX + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3A20DisableViaPortA + + +;; +; Disables the A20 gate via the keyboard controller. +; +; @uses Nothing. +; +BS3_PROC_BEGIN_CMN Bs3A20DisableViaKbd, BS3_PBC_HYBRID_0_ARGS + push xBP + mov xBP, xSP + push xAX + pushf + cli +BONLY64 sub rsp, 20h + + call Bs3KbdWait + push 0d0h ; KBD_CCMD_READ_OUTPORT + call Bs3KbdRead + + and al, 0fdh ; ~2 + push xAX + push 0d1h ; KBD_CCMD_WRITE_OUTPORT + call Bs3KbdWrite + + add xSP, xCB*3 ; Clean up both the above calls. + + mov al, 0ffh ; KBD_CMD_RESET + out 64h, al + call Bs3KbdWait + +BONLY64 add rsp, 20h + popf + pop xAX + pop xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3A20DisableViaKbd + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-A20Enable.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-A20Enable.asm new file mode 100644 index 00000000..bd4406d1 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-A20Enable.asm @@ -0,0 +1,122 @@ +; $Id: bs3-cmn-A20Enable.asm $ +;; @file +; BS3Kit - Bs3A20Enable. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3KbdWait +BS3_EXTERN_CMN Bs3KbdRead +BS3_EXTERN_CMN Bs3KbdWrite + + +;; +; Enables the A20 gate. +; +; @uses Nothing. +; +BS3_PROC_BEGIN_CMN Bs3A20Enable, BS3_PBC_HYBRID_0_ARGS + push xBP + mov xBP, xSP +BONLY64 sub rsp, 20h + + call BS3_CMN_NM(Bs3A20EnableViaPortA) +;; @todo real 286 support +; call BS3_CMN_NM(Bs3A20EnableViaKbd) + + pop xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3A20Enable + + +;; +; Enables the A20 gate via the keyboard controller. +; +; @uses Nothing. +; +BS3_PROC_BEGIN_CMN Bs3A20EnableViaKbd, BS3_PBC_HYBRID_0_ARGS + push xBP + mov xBP, xSP + push xAX + pushf + cli +BONLY64 sub rsp, 20h + + call Bs3KbdWait + push 0d0h ; KBD_CCMD_READ_OUTPORT + call Bs3KbdRead + + or al, 002h + push xAX + push 0d1h ; KBD_CCMD_WRITE_OUTPORT + call Bs3KbdWrite + + add xSP, xCB*3 ; both the above calls + + mov al, 0ffh ; KBD_CMD_RESET + out 64h, al + call Bs3KbdWait + +BONLY64 add rsp, 20h + popf + pop xAX + pop xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3A20EnableViaKbd + + +;; +; Enables the A20 gate via control port A (PS/2 style). +; +; @uses Nothing. +; +BS3_PROC_BEGIN_CMN Bs3A20EnableViaPortA, BS3_PBC_HYBRID_0_ARGS + push xBP + mov xBP, xSP + push xAX + + ; Use Control port A, assuming a PS/2 style system. + in al, 092h + test al, 02h + jnz .done ; avoid trouble writing back the same value. + or al, 2 ; enable the A20 gate. + out 092h, al + +.done: + pop xAX + pop xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3A20EnableViaPortA + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ConvertRMStackToP16UsingCxReturnToAx.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ConvertRMStackToP16UsingCxReturnToAx.asm new file mode 100644 index 00000000..d12f0f4b --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ConvertRMStackToP16UsingCxReturnToAx.asm @@ -0,0 +1,88 @@ +; $Id: bs3-cmn-ConvertRMStackToP16UsingCxReturnToAx.asm $ +;; @file +; BS3Kit - Bs3ConvertRMStackToP16UsingCxReturnToAx. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +%if TMPL_BITS != 16 + %error 16-bit only! +%endif + +;; +; An internal helper for converting a real-mode stack into a 16-bit protected +; mode stack. +; +; This is used by the mode switchers that ends up in 16-bit mode. It is +; assumed that we're in ring-0. +; +; @param ax The return address. +; +; @uses cx, ss, esp +; +BS3_PROC_BEGIN_CMN Bs3ConvertRMStackToP16UsingCxReturnToAx, BS3_PBC_NEAR + + ; + ; Check if it looks like the normal stack, if use BS3_SEL_R0_SS16. + ; + mov cx, ss + cmp cx, 0 + jne .stack_tiled + mov cx, BS3_SEL_R0_SS16 + mov ss, cx + jmp ax + + ; + ; Some custom stack address, just use the 16-bit tiled mappings + ; +.stack_tiled: +int3 ; debug this, shouldn't happen yet. Bs3EnteredMode_xxx isn't prepared. + shl cx, 4 + add sp, cx + mov cx, ss + jc .stack_carry + shr cx, 12 + jmp .stack_join_up_again +.stack_carry: + shr cx, 12 + inc cx +.stack_join_up_again: + shl cx, 3 + adc cx, BS3_SEL_TILED + mov ss, cx + jmp ax + +BS3_PROC_END_CMN Bs3ConvertRMStackToP16UsingCxReturnToAx + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-CpuDetectData.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-CpuDetectData.c new file mode 100644 index 00000000..11cc2b7a --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-CpuDetectData.c @@ -0,0 +1,54 @@ +/* $Id: bs3-cmn-CpuDetectData.c $ */ +/** @file + * BS3Kit - Detected CPU data. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-test.h" + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +#if ARCH_BITS == 16 + +uint16_t g_uBs3CpuDetected = BS3CPU_TYPE_MASK | BS3CPU_F_CPUID | BS3CPU_F_CPUID_EXT_LEAVES + | BS3CPU_F_PAE | BS3CPU_F_PSE | BS3CPU_F_LONG_MODE; + +#endif /* ARCH_BITS == 16 */ + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxAlloc.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxAlloc.c new file mode 100644 index 00000000..2f648134 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxAlloc.c @@ -0,0 +1,54 @@ +/* $Id: bs3-cmn-ExtCtxAlloc.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxAlloc + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3ExtCtxAlloc +BS3_CMN_DEF(PBS3EXTCTX, Bs3ExtCtxAlloc,(BS3MEMKIND enmKind)) +{ + uint64_t fFlags; + uint16_t cbExtCtx = Bs3ExtCtxGetSize(&fFlags); + PBS3EXTCTX pExtCtx = (PBS3EXTCTX)Bs3MemAlloc(enmKind, cbExtCtx); + if (pExtCtx) + return Bs3ExtCtxInit(pExtCtx, cbExtCtx, fFlags); + return NULL; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxCopy.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxCopy.c new file mode 100644 index 00000000..4eff8574 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxCopy.c @@ -0,0 +1,53 @@ +/* $Id: bs3-cmn-ExtCtxCopy.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxCopy + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include <iprt/asm-amd64-x86.h> + + +#undef Bs3ExtCtxCopy +BS3_CMN_DEF(PBS3EXTCTX, Bs3ExtCtxCopy,(PBS3EXTCTX pDst, PCBS3EXTCTX pSrc)) +{ + BS3_ASSERT(pDst->cb == pSrc->cb && pDst->enmMethod == pSrc->enmMethod && pDst->fXcr0Nominal == pSrc->fXcr0Nominal); + Bs3MemCpy(&pDst->Ctx, &pSrc->Ctx, pDst->cb - RT_UOFFSETOF(BS3EXTCTX, Ctx)); + pDst->fXcr0Saved = pSrc->fXcr0Saved; + return pDst; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxFree.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxFree.c new file mode 100644 index 00000000..fcc35c78 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxFree.c @@ -0,0 +1,56 @@ +/* $Id: bs3-cmn-ExtCtxFree.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxFree + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3ExtCtxFree +BS3_CMN_DEF(void, Bs3ExtCtxFree,(PBS3EXTCTX pExtCtx)) +{ + if (pExtCtx) + { + if (pExtCtx->u16Magic == BS3EXTCTX_MAGIC) + { + pExtCtx->u16Magic = ~BS3EXTCTX_MAGIC; + Bs3MemFree(pExtCtx, pExtCtx->cb); + } + } +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetAbridgedFtw.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetAbridgedFtw.c new file mode 100644 index 00000000..6092f88b --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetAbridgedFtw.c @@ -0,0 +1,71 @@ +/* $Id: bs3-cmn-ExtCtxGetAbridgedFtw.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxGetAbridgedFtw + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3ExtCtxGetAbridgedFtw +BS3_CMN_DEF(uint16_t, Bs3ExtCtxGetAbridgedFtw,(PCBS3EXTCTX pExtCtx)) +{ + AssertCompileMembersAtSameOffset(BS3EXTCTX, Ctx.x87.FTW, BS3EXTCTX, Ctx.x.x87.FTW); + switch (pExtCtx->enmMethod) + { + case BS3EXTCTXMETHOD_FXSAVE: + case BS3EXTCTXMETHOD_XSAVE: + return pExtCtx->Ctx.x87.FTW; + + case BS3EXTCTXMETHOD_ANCIENT: + { + /* iemFpuCompressFtw: */ + uint16_t u16FullFtw = pExtCtx->Ctx.Ancient.FTW; + uint8_t u8Ftw = 0; + unsigned i; + for (i = 0; i < 8; i++) + { + if ((u16FullFtw & 3) != 3 /*empty*/) + u8Ftw |= RT_BIT(i); + u16FullFtw >>= 2; + } + return u8Ftw; + } + } + return 0; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetFcw.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetFcw.c new file mode 100644 index 00000000..efbbf2ec --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetFcw.c @@ -0,0 +1,59 @@ +/* $Id: bs3-cmn-ExtCtxGetFcw.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxGetFcw + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3ExtCtxGetFcw +BS3_CMN_DEF(uint16_t, Bs3ExtCtxGetFcw,(PCBS3EXTCTX pExtCtx)) +{ + AssertCompileMembersAtSameOffset(BS3EXTCTX, Ctx.x87.FCW, BS3EXTCTX, Ctx.x.x87.FCW); + switch (pExtCtx->enmMethod) + { + case BS3EXTCTXMETHOD_FXSAVE: + case BS3EXTCTXMETHOD_XSAVE: + return pExtCtx->Ctx.x87.FCW; + + case BS3EXTCTXMETHOD_ANCIENT: + return pExtCtx->Ctx.Ancient.FCW; + } + return 0; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetFsw.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetFsw.c new file mode 100644 index 00000000..a7ebff46 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetFsw.c @@ -0,0 +1,59 @@ +/* $Id: bs3-cmn-ExtCtxGetFsw.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxGetFsw + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3ExtCtxGetFsw +BS3_CMN_DEF(uint16_t, Bs3ExtCtxGetFsw,(PCBS3EXTCTX pExtCtx)) +{ + AssertCompileMembersAtSameOffset(BS3EXTCTX, Ctx.x87.FSW, BS3EXTCTX, Ctx.x.x87.FSW); + switch (pExtCtx->enmMethod) + { + case BS3EXTCTXMETHOD_FXSAVE: + case BS3EXTCTXMETHOD_XSAVE: + return pExtCtx->Ctx.x87.FSW; + + case BS3EXTCTXMETHOD_ANCIENT: + return pExtCtx->Ctx.Ancient.FSW; + } + return 0; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetMm.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetMm.c new file mode 100644 index 00000000..7ad104a6 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetMm.c @@ -0,0 +1,60 @@ +/* $Id: bs3-cmn-ExtCtxGetMm.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxGetMm + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3ExtCtxGetMm +BS3_CMN_DEF(uint64_t, Bs3ExtCtxGetMm,(PCBS3EXTCTX pExtCtx, uint8_t iReg)) +{ + AssertCompileMembersAtSameOffset(BS3EXTCTX, Ctx.x87.aRegs, BS3EXTCTX, Ctx.x.x87.aRegs); + if (iReg < RT_ELEMENTS(pExtCtx->Ctx.x87.aRegs)) + switch (pExtCtx->enmMethod) + { + case BS3EXTCTXMETHOD_FXSAVE: + case BS3EXTCTXMETHOD_XSAVE: + return pExtCtx->Ctx.x87.aRegs[iReg].mmx; + + case BS3EXTCTXMETHOD_ANCIENT: + return pExtCtx->Ctx.Ancient.regs[iReg].mmx; + } + return 0; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetMxCsr.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetMxCsr.c new file mode 100644 index 00000000..72c78be5 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetMxCsr.c @@ -0,0 +1,53 @@ +/* $Id: bs3-cmn-ExtCtxGetMxCsr.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxGetMxCsr + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3ExtCtxGetMxCsr +BS3_CMN_DEF(uint32_t, Bs3ExtCtxGetMxCsr,(PCBS3EXTCTX pExtCtx)) +{ + AssertCompileMembersAtSameOffset(BS3EXTCTX, Ctx.x87.MXCSR, BS3EXTCTX, Ctx.x.x87.MXCSR); + if ( pExtCtx->enmMethod == BS3EXTCTXMETHOD_FXSAVE + || pExtCtx->enmMethod == BS3EXTCTXMETHOD_XSAVE) + return pExtCtx->Ctx.x87.MXCSR; + return 0; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetMxCsrMask.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetMxCsrMask.c new file mode 100644 index 00000000..ead905d2 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetMxCsrMask.c @@ -0,0 +1,53 @@ +/* $Id: bs3-cmn-ExtCtxGetMxCsrMask.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxGetMxCsrMask + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3ExtCtxGetMxCsrMask +BS3_CMN_DEF(uint32_t, Bs3ExtCtxGetMxCsrMask,(PCBS3EXTCTX pExtCtx)) +{ + AssertCompileMembersAtSameOffset(BS3EXTCTX, Ctx.x87.MXCSR_MASK, BS3EXTCTX, Ctx.x.x87.MXCSR_MASK); + if ( pExtCtx->enmMethod == BS3EXTCTXMETHOD_FXSAVE + || pExtCtx->enmMethod == BS3EXTCTXMETHOD_XSAVE) + return pExtCtx->Ctx.x87.MXCSR_MASK; + return 0; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetSize.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetSize.c new file mode 100644 index 00000000..69b9bf46 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetSize.c @@ -0,0 +1,69 @@ +/* $Id: bs3-cmn-ExtCtxGetSize.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxGetSize + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include <iprt/asm-amd64-x86.h> + + +#undef Bs3ExtCtxGetSize +BS3_CMN_DEF(uint16_t, Bs3ExtCtxGetSize,(uint64_t BS3_FAR *pfFlags)) +{ + uint32_t fEcx, fEdx; + *pfFlags = 0; + + ASMCpuIdExSlow(1, 0, 0, 0, NULL, NULL, &fEcx, &fEdx); +#if 1 /* To disable xsave/xrstor till IEM groks it... */ + if (fEcx & X86_CPUID_FEATURE_ECX_XSAVE) + { + uint32_t fEax; + ASMCpuIdExSlow(13, 0, 0, 0, &fEax, NULL, &fEcx, &fEdx); + if ( fEcx >= sizeof(X86FXSTATE) + sizeof(X86XSAVEHDR) + && fEcx < _32K) + { + *pfFlags = fEax | ((uint64_t)fEdx << 32); + return RT_UOFFSETOF(BS3EXTCTX, Ctx) + RT_ALIGN(fEcx, 256); + } + } +#endif + if (fEdx & X86_CPUID_FEATURE_EDX_FXSR) + return RT_UOFFSETOF(BS3EXTCTX, Ctx) + sizeof(X86FXSTATE); + return RT_UOFFSETOF(BS3EXTCTX, Ctx) + sizeof(X86FPUSTATE); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetXmm.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetXmm.c new file mode 100644 index 00000000..99b37e97 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetXmm.c @@ -0,0 +1,64 @@ +/* $Id: bs3-cmn-ExtCtxGetXmm.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxGetXmm + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3ExtCtxGetXmm +BS3_CMN_DEF(PRTUINT128U, Bs3ExtCtxGetXmm,(PCBS3EXTCTX pExtCtx, uint8_t iReg, PRTUINT128U pValue)) +{ + AssertCompileMembersAtSameOffset(BS3EXTCTX, Ctx.x87.aXMM, BS3EXTCTX, Ctx.x.x87.aXMM); + switch (pExtCtx->enmMethod) + { + case BS3EXTCTXMETHOD_FXSAVE: + case BS3EXTCTXMETHOD_XSAVE: + if (iReg < RT_ELEMENTS(pExtCtx->Ctx.x87.aXMM)) + { + pValue->u = pExtCtx->Ctx.x87.aXMM[iReg].xmm; + return pValue; + } + break; + } + + pValue->au64[0] = 0; + pValue->au64[1] = 0; + return pValue; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetYmm.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetYmm.c new file mode 100644 index 00000000..10e1066a --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetYmm.c @@ -0,0 +1,70 @@ +/* $Id: bs3-cmn-ExtCtxGetYmm.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxGetYmm + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3ExtCtxGetYmm +BS3_CMN_DEF(PRTUINT256U, Bs3ExtCtxGetYmm,(PCBS3EXTCTX pExtCtx, uint8_t iReg, PRTUINT256U pValue)) +{ + pValue->au128[0].au64[0] = 0; + pValue->au128[0].au64[1] = 0; + pValue->au128[1].au64[0] = 0; + pValue->au128[1].au64[1] = 0; + + switch (pExtCtx->enmMethod) + { + case BS3EXTCTXMETHOD_FXSAVE: + if (iReg < RT_ELEMENTS(pExtCtx->Ctx.x87.aXMM)) + pValue->au128[0] = pExtCtx->Ctx.x87.aXMM[iReg].uXmm; + break; + + case BS3EXTCTXMETHOD_XSAVE: + if (iReg < RT_ELEMENTS(pExtCtx->Ctx.x.x87.aXMM)) + { + pValue->au128[0] = pExtCtx->Ctx.x87.aXMM[iReg].uXmm; + if (pExtCtx->fXcr0Nominal & XSAVE_C_YMM) + pValue->au128[1] = pExtCtx->Ctx.x.u.YmmHi.aYmmHi[iReg].uXmm; + } + break; + } + return pValue; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxInit.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxInit.c new file mode 100644 index 00000000..944f6d45 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxInit.c @@ -0,0 +1,84 @@ +/* $Id: bs3-cmn-ExtCtxInit.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxInit + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include <iprt/asm-amd64-x86.h> + + +#undef Bs3ExtCtxInit +BS3_CMN_DEF(PBS3EXTCTX, Bs3ExtCtxInit,(PBS3EXTCTX pExtCtx, uint16_t cbExtCtx, uint64_t fFlags)) +{ + Bs3MemSet(pExtCtx, 0, cbExtCtx); + + if (cbExtCtx >= RT_UOFFSETOF(BS3EXTCTX, Ctx) + sizeof(X86FXSTATE) + sizeof(X86XSAVEHDR)) + { + BS3_ASSERT(fFlags & XSAVE_C_X87); + pExtCtx->enmMethod = BS3EXTCTXMETHOD_XSAVE; + pExtCtx->Ctx.x.Hdr.bmXState = fFlags; + + /* Setting bit 6 (0x40) here as it kept sneaking in when loading/saving state in 16-bit and v8086 mode. */ + pExtCtx->Ctx.x.x87.FCW = X86_FCW_RC_NEAREST | X86_FCW_PC_64 /* go figure:*/ | RT_BIT(6); + pExtCtx->Ctx.x.x87.MXCSR = X86_MXCSR_RC_NEAREST; + pExtCtx->Ctx.x.x87.MXCSR_MASK = 0xffff; + } + else if (cbExtCtx >= RT_UOFFSETOF(BS3EXTCTX, Ctx) + sizeof(X86FXSTATE)) + { + BS3_ASSERT(fFlags == 0); + pExtCtx->enmMethod = BS3EXTCTXMETHOD_FXSAVE; + pExtCtx->Ctx.x87.FCW = X86_FCW_RC_NEAREST | X86_FCW_PC_64 /* go figure:*/ | RT_BIT(6); + pExtCtx->Ctx.x87.MXCSR = X86_MXCSR_RC_NEAREST; + pExtCtx->Ctx.x87.MXCSR_MASK = 0xffff; + } + else + { + BS3_ASSERT(fFlags == 0); + BS3_ASSERT(cbExtCtx >= RT_UOFFSETOF(BS3EXTCTX, Ctx) + sizeof(X86FPUSTATE)); + pExtCtx->enmMethod = BS3EXTCTXMETHOD_ANCIENT; + pExtCtx->Ctx.Ancient.FCW = X86_FCW_RC_NEAREST | X86_FCW_PC_64 /* go figure:*/ | RT_BIT(6); + pExtCtx->Ctx.Ancient.FTW = UINT16_MAX; /* all registers empty */ + } + + pExtCtx->cb = cbExtCtx; + pExtCtx->u16Magic = BS3EXTCTX_MAGIC; + pExtCtx->fXcr0Nominal = fFlags; + pExtCtx->fXcr0Saved = fFlags; + return pExtCtx; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxRestore.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxRestore.asm new file mode 100644 index 00000000..a24dedd4 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxRestore.asm @@ -0,0 +1,155 @@ +; $Id: bs3-cmn-ExtCtxRestore.asm $ +;; @file +; BS3Kit - Bs3ExtCtxRestore. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +extern BS3_CMN_NM(Bs3RegSetXcr0) + + +;; +; Restores the extended CPU context (FPU, SSE, AVX, ++). +; +; @param pExtCtx +; +BS3_PROC_BEGIN_CMN Bs3ExtCtxRestore, BS3_PBC_NEAR + push xBP + mov xBP, xSP + push sAX + push sCX + push sDX + push xBX +BONLY16 push es + +%if ARCH_BITS == 16 + les bx, [xBP + xCB + cbCurRetAddr] + mov al, [es:bx + BS3EXTCTX.enmMethod] + cmp al, BS3EXTCTXMETHOD_XSAVE + je .do_16_xsave + cmp al, BS3EXTCTXMETHOD_FXSAVE + je .do_16_fxsave + cmp al, BS3EXTCTXMETHOD_ANCIENT + je .do_16_ancient + int3 + +.do_16_ancient: + frstor [es:bx + BS3EXTCTX.Ctx] + jmp .return + +.do_16_fxsave: + fxrstor [es:bx + BS3EXTCTX.Ctx] + jmp .return + +.do_16_xsave: + push dword [es:bx + BS3EXTCTX.fXcr0Nominal + 4] + push dword [es:bx + BS3EXTCTX.fXcr0Nominal] + call BS3_CMN_NM(Bs3RegSetXcr0) + + mov eax, [es:bx + BS3EXTCTX.fXcr0Nominal] + mov edx, [es:bx + BS3EXTCTX.fXcr0Nominal + 4] + xrstor [es:bx + BS3EXTCTX.Ctx] + + push dword [es:bx + BS3EXTCTX.fXcr0Saved + 4] + push dword [es:bx + BS3EXTCTX.fXcr0Saved] + call BS3_CMN_NM(Bs3RegSetXcr0) + + add xSP, 4 * 2 * 2 ; clean up both calls + ;jmp .return + +%else +BONLY32 mov ebx, [xBP + xCB + cbCurRetAddr] +BONLY64 mov rbx, rcx + + mov al, [xBX + BS3EXTCTX.enmMethod] + cmp al, BS3EXTCTXMETHOD_XSAVE + je .do_xsave + cmp al, BS3EXTCTXMETHOD_FXSAVE + je .do_fxsave + cmp al, BS3EXTCTXMETHOD_ANCIENT + je .do_ancient + int3 + +.do_ancient: + frstor [xBX + BS3EXTCTX.Ctx] + jmp .return + +.do_fxsave: +BONLY32 fxrstor [xBX + BS3EXTCTX.Ctx] +BONLY64 fxrstor64 [xBX + BS3EXTCTX.Ctx] + jmp .return + +.do_xsave: + %if ARCH_BITS == 32 + push dword [xBX + BS3EXTCTX.fXcr0Nominal + 4] + push dword [xBX + BS3EXTCTX.fXcr0Nominal] + call BS3_CMN_NM(Bs3RegSetXcr0) + + mov eax, [xBX + BS3EXTCTX.fXcr0Nominal] + mov edx, [xBX + BS3EXTCTX.fXcr0Nominal + 4] + xrstor [xBX + BS3EXTCTX.Ctx] + + push dword [xBX + BS3EXTCTX.fXcr0Saved + 4] + push dword [xBX + BS3EXTCTX.fXcr0Saved] + call BS3_CMN_NM(Bs3RegSetXcr0) + + add xSP, 4 * 2 * 2 ; clean up both calls + %else + mov rcx, [xBX + BS3EXTCTX.fXcr0Nominal] + push rcx ; just for reserving parameter dumping space needed by Bs3RegSetXcr0 + call BS3_CMN_NM(Bs3RegSetXcr0) + + mov eax, [xBX + BS3EXTCTX.fXcr0Nominal] + mov edx, [xBX + BS3EXTCTX.fXcr0Nominal + 4] + xrstor64 [xBX + BS3EXTCTX.Ctx] + + mov rcx, [xBX + BS3EXTCTX.fXcr0Saved] + call BS3_CMN_NM(Bs3RegSetXcr0) + + add xSP, 8 ; clean up parameter space + ;jmp .return + %endif +%endif + +.return: +BONLY16 pop es + pop xBX + pop sDX + pop sCX + pop sAX + mov xSP, xBP + pop xBP + ret +BS3_PROC_END_CMN Bs3ExtCtxRestore + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxRestoreEx.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxRestoreEx.asm new file mode 100644 index 00000000..46f86ced --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxRestoreEx.asm @@ -0,0 +1,136 @@ +; $Id: bs3-cmn-ExtCtxRestoreEx.asm $ +;; @file +; BS3Kit - Bs3ExtCtxRestoreEx. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +%if ARCH_BITS != 64 +BS3_EXTERN_DATA16 g_bBs3CurrentMode + +BS3_BEGIN_TEXT64 +extern _Bs3ExtCtxRestore_c64 + %if ARCH_BITS == 16 +extern BS3_CMN_NM(Bs3SelProtFar16DataToFlat) +extern _Bs3SwitchTo16Bit_c64 + %else +extern _Bs3SwitchTo32Bit_c64 + %endif + +TMPL_BEGIN_TEXT +extern BS3_CMN_NM(Bs3SwitchTo64Bit) + %if ARCH_BITS == 16 +extern BS3_CMN_NM(Bs3SelProtFar16DataToFlat) + %endif +%endif + +extern BS3_CMN_NM(Bs3ExtCtxRestore) + + + +;; +; Restores the extended CPU context (FPU, SSE, AVX, ++), full 64-bit +; when in long mode. +; +; @param pExtCtx +; +BS3_PROC_BEGIN_CMN Bs3ExtCtxRestoreEx, BS3_PBC_NEAR +%if ARCH_BITS == 64 + jmp BS3_CMN_NM(Bs3ExtCtxRestore) +%else + push xBP + mov xBP, xSP + push sAX + + ; + ; Check if we're in long mode. + ; + mov al, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + and al, BS3_MODE_SYS_MASK + cmp al, BS3_MODE_SYS_LM + je .in_long_mode + + ; + ; Not in long mode, so do normal restore. + ; + pop sAX + leave + jmp BS3_CMN_NM(Bs3ExtCtxRestore) + + ; + ; Switch to 64-bit to do the restoring so we can restore 64-bit only state. + ; +.in_long_mode: + push sCX +BONLY16 push sDX + + ; Load ecx with the flat pExtCtx address. + mov ecx, [xBP + xCB + cbCurRetAddr] + + %if ARCH_BITS == 16 + push ecx + call BS3_CMN_NM(Bs3SelProtFar16DataToFlat) + mov ecx, edx + shl ecx, 16 + mov cx, ax + %endif + + ; Switch to 64-bit mode. + call BS3_CMN_NM(Bs3SwitchTo64Bit) + BITS 64 + + ; Do the restore. + sub rsp, 20h + call _Bs3ExtCtxRestore_c64 + add rsp, 20h + + ; Switch back to the original mode. + %if ARCH_BITS == 16 + call _Bs3SwitchTo16Bit_c64 + %else + call _Bs3SwitchTo32Bit_c64 + %endif + BITS ARCH_BITS + + ; Restore context and return. +BONLY16 pop sDX + pop sCX + + pop sAX + leave + ret +%endif +BS3_PROC_END_CMN Bs3ExtCtxRestoreEx + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSave.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSave.asm new file mode 100644 index 00000000..e6cbbd67 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSave.asm @@ -0,0 +1,166 @@ +; $Id: bs3-cmn-ExtCtxSave.asm $ +;; @file +; BS3Kit - Bs3ExtCtxSave. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +extern BS3_CMN_NM(Bs3RegSetXcr0) + +;; +; Saves the extended CPU context (FPU, SSE, AVX, ++). +; +; @param pExtCtx +; +BS3_PROC_BEGIN_CMN Bs3ExtCtxSave, BS3_PBC_NEAR + push xBP + mov xBP, xSP + push sAX + push sCX + push sDX + push xBX +BONLY16 push es + +%if ARCH_BITS == 16 + les bx, [xBP + xCB + cbCurRetAddr] + mov al, [es:bx + BS3EXTCTX.enmMethod] + cmp al, BS3EXTCTXMETHOD_XSAVE + je .do_16_xsave + cmp al, BS3EXTCTXMETHOD_FXSAVE + je .do_16_fxsave + cmp al, BS3EXTCTXMETHOD_ANCIENT + je .do_16_ancient + int3 + +.do_16_ancient: + fnsave [es:bx + BS3EXTCTX.Ctx] + jmp .return + +.do_16_fxsave: + fxsave [es:bx + BS3EXTCTX.Ctx] + jmp .return + +.do_16_xsave: + ; xgetbv can be used in any ring! + xor ecx, ecx + xgetbv + mov [es:bx + BS3EXTCTX.fXcr0Saved], eax + mov [es:bx + BS3EXTCTX.fXcr0Saved + 4], edx + + push dword [es:bx + BS3EXTCTX.fXcr0Nominal + 4] + push dword [es:bx + BS3EXTCTX.fXcr0Nominal] + call BS3_CMN_NM(Bs3RegSetXcr0) + + mov eax, [es:bx + BS3EXTCTX.fXcr0Nominal] + mov edx, [es:bx + BS3EXTCTX.fXcr0Nominal + 4] + xsave [es:bx + BS3EXTCTX.Ctx] + + push dword [es:bx + BS3EXTCTX.fXcr0Saved + 4] + push dword [es:bx + BS3EXTCTX.fXcr0Saved] + call BS3_CMN_NM(Bs3RegSetXcr0) + + add xSP, 4 * 2 * 2 ; clean up both calls + ;jmp .return + +%else +BONLY32 mov ebx, [xBP + xCB + cbCurRetAddr] +BONLY64 mov rbx, rcx + + mov al, [xBX + BS3EXTCTX.enmMethod] + cmp al, BS3EXTCTXMETHOD_XSAVE + je .do_xsave + cmp al, BS3EXTCTXMETHOD_FXSAVE + je .do_fxsave + cmp al, BS3EXTCTXMETHOD_ANCIENT + je .do_ancient + int3 + +.do_ancient: + fnsave [xBX + BS3EXTCTX.Ctx] + jmp .return + +.do_fxsave: +BONLY32 fxsave [xBX + BS3EXTCTX.Ctx] +BONLY64 fxsave64 [xBX + BS3EXTCTX.Ctx] + jmp .return + +.do_xsave: + xor ecx, ecx + xgetbv + mov [xBX + BS3EXTCTX.fXcr0Saved], eax + mov [xBX + BS3EXTCTX.fXcr0Saved + 4], edx + + %if ARCH_BITS == 32 + push dword [xBX + BS3EXTCTX.fXcr0Nominal + 4] + push dword [xBX + BS3EXTCTX.fXcr0Nominal] + call BS3_CMN_NM(Bs3RegSetXcr0) + + mov eax, [xBX + BS3EXTCTX.fXcr0Nominal] + mov edx, [xBX + BS3EXTCTX.fXcr0Nominal + 4] + xsave [xBX + BS3EXTCTX.Ctx] + + push dword [xBX + BS3EXTCTX.fXcr0Saved + 4] + push dword [xBX + BS3EXTCTX.fXcr0Saved] + call BS3_CMN_NM(Bs3RegSetXcr0) + + add xSP, 4 * 2 * 2 ; clean up both calls + %else + mov rcx, [xBX + BS3EXTCTX.fXcr0Nominal] + push rcx ; only to reserve necessary stack space for the Bs3RegSetXcr0 param dump. + call BS3_CMN_NM(Bs3RegSetXcr0) + + mov eax, [xBX + BS3EXTCTX.fXcr0Nominal] + mov edx, [xBX + BS3EXTCTX.fXcr0Nominal + 4] + xsave64 [xBX + BS3EXTCTX.Ctx] + + mov rcx, [xBX + BS3EXTCTX.fXcr0Saved] + call BS3_CMN_NM(Bs3RegSetXcr0) + + add xSP, 8h ; clean up + %endif + ;jmp .return + +%endif + +.return: +BONLY16 pop es + pop xBX + pop sDX + pop sCX + pop sAX + mov xSP, xBP + pop xBP + ret +BS3_PROC_END_CMN Bs3ExtCtxSave + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSaveEx.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSaveEx.asm new file mode 100644 index 00000000..ca1cbe9f --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSaveEx.asm @@ -0,0 +1,136 @@ +; $Id: bs3-cmn-ExtCtxSaveEx.asm $ +;; @file +; BS3Kit - Bs3ExtCtxSaveEx. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +%if ARCH_BITS != 64 +BS3_EXTERN_DATA16 g_bBs3CurrentMode + +BS3_BEGIN_TEXT64 +extern _Bs3ExtCtxSave_c64 + %if ARCH_BITS == 16 +extern BS3_CMN_NM(Bs3SelProtFar16DataToFlat) +extern _Bs3SwitchTo16Bit_c64 + %else +extern _Bs3SwitchTo32Bit_c64 + %endif + +TMPL_BEGIN_TEXT +extern BS3_CMN_NM(Bs3SwitchTo64Bit) + %if ARCH_BITS == 16 +extern BS3_CMN_NM(Bs3SelProtFar16DataToFlat) + %endif +%endif + +extern BS3_CMN_NM(Bs3ExtCtxSave) + + + +;; +; Saves the extended CPU context (FPU, SSE, AVX, ++), full 64-bit +; when in long mode. +; +; @param pExtCtx +; +BS3_PROC_BEGIN_CMN Bs3ExtCtxSaveEx, BS3_PBC_NEAR +%if ARCH_BITS == 64 + jmp BS3_CMN_NM(Bs3ExtCtxSave) +%else + push xBP + mov xBP, xSP + push sAX + + ; + ; Check if we're in long mode. + ; + mov al, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + and al, BS3_MODE_SYS_MASK + cmp al, BS3_MODE_SYS_LM + je .in_long_mode + + ; + ; Not in long mode, so do normal save. + ; + pop sAX + leave + jmp BS3_CMN_NM(Bs3ExtCtxSave) + + ; + ; Switch to 64-bit to do the restoring so we can save the 64-bit only state. + ; +.in_long_mode: + push sCX +BONLY16 push sDX + + ; Load ecx with the flat pExtCtx address. + mov ecx, [xBP + xCB + cbCurRetAddr] + + %if ARCH_BITS == 16 + push ecx + call BS3_CMN_NM(Bs3SelProtFar16DataToFlat) + mov ecx, edx + shl ecx, 16 + mov cx, ax + %endif + + ; Switch to 64-bit mode. + call BS3_CMN_NM(Bs3SwitchTo64Bit) + BITS 64 + + ; Do the save. + sub rsp, 20h + call _Bs3ExtCtxSave_c64 + add rsp, 20h + + ; Switch back to the original mode. + %if ARCH_BITS == 16 + call _Bs3SwitchTo16Bit_c64 + %else + call _Bs3SwitchTo32Bit_c64 + %endif + BITS ARCH_BITS + + ; Save context and return. +BONLY16 pop sDX + pop sCX + + pop sAX + leave + ret +%endif +BS3_PROC_END_CMN Bs3ExtCtxSaveEx + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetAbridgedFtw.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetAbridgedFtw.c new file mode 100644 index 00000000..263817d0 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetAbridgedFtw.c @@ -0,0 +1,61 @@ +/* $Id: bs3-cmn-ExtCtxSetAbridgedFtw.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxSetAbridgedFtw + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3ExtCtxSetAbridgedFtw +BS3_CMN_DEF(bool, Bs3ExtCtxSetAbridgedFtw,(PBS3EXTCTX pExtCtx, uint16_t uValue)) +{ + AssertCompileMembersAtSameOffset(BS3EXTCTX, Ctx.x87.FTW, BS3EXTCTX, Ctx.x.x87.FTW); + switch (pExtCtx->enmMethod) + { + case BS3EXTCTXMETHOD_FXSAVE: + case BS3EXTCTXMETHOD_XSAVE: + pExtCtx->Ctx.x87.FTW = uValue; + return true; + + case BS3EXTCTXMETHOD_ANCIENT: + /* Could do iemFpuCalcFullFtw here, but too much work for now... */ + break; + } + return false; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetFcw.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetFcw.c new file mode 100644 index 00000000..a51259be --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetFcw.c @@ -0,0 +1,60 @@ +/* $Id: bs3-cmn-ExtCtxSetFcw.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxSetFcw + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3ExtCtxSetFcw +BS3_CMN_DEF(void, Bs3ExtCtxSetFcw,(PBS3EXTCTX pExtCtx, uint16_t uValue)) +{ + AssertCompileMembersAtSameOffset(BS3EXTCTX, Ctx.x87.FCW, BS3EXTCTX, Ctx.x.x87.FCW); + switch (pExtCtx->enmMethod) + { + case BS3EXTCTXMETHOD_FXSAVE: + case BS3EXTCTXMETHOD_XSAVE: + pExtCtx->Ctx.x87.FCW = uValue; + break; + + case BS3EXTCTXMETHOD_ANCIENT: + pExtCtx->Ctx.Ancient.FCW = uValue; + break; + } +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetFsw.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetFsw.c new file mode 100644 index 00000000..e49e9781 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetFsw.c @@ -0,0 +1,60 @@ +/* $Id: bs3-cmn-ExtCtxSetFsw.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxSetFsw + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3ExtCtxSetFsw +BS3_CMN_DEF(void, Bs3ExtCtxSetFsw,(PBS3EXTCTX pExtCtx, uint16_t uValue)) +{ + AssertCompileMembersAtSameOffset(BS3EXTCTX, Ctx.x87.FSW, BS3EXTCTX, Ctx.x.x87.FSW); + switch (pExtCtx->enmMethod) + { + case BS3EXTCTXMETHOD_FXSAVE: + case BS3EXTCTXMETHOD_XSAVE: + pExtCtx->Ctx.x87.FSW = uValue; + break; + + case BS3EXTCTXMETHOD_ANCIENT: + pExtCtx->Ctx.Ancient.FSW = uValue; + break; + } +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetMm.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetMm.c new file mode 100644 index 00000000..17dc583a --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetMm.c @@ -0,0 +1,66 @@ +/* $Id: bs3-cmn-ExtCtxSetMm.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxSetMm + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3ExtCtxSetMm +BS3_CMN_DEF(bool, Bs3ExtCtxSetMm,(PBS3EXTCTX pExtCtx, uint8_t iReg, uint64_t uValue, BS3EXTCTXTOPMM enmTop)) +{ + AssertCompileMembersAtSameOffset(BS3EXTCTX, Ctx.x87.aRegs, BS3EXTCTX, Ctx.x.x87.aRegs); + if (iReg < RT_ELEMENTS(pExtCtx->Ctx.x87.aRegs)) + switch (pExtCtx->enmMethod) + { + case BS3EXTCTXMETHOD_FXSAVE: + case BS3EXTCTXMETHOD_XSAVE: + pExtCtx->Ctx.x87.aRegs[iReg].mmx = uValue; + if (enmTop == BS3EXTCTXTOPMM_SET || enmTop == BS3EXTCTXTOPMM_ZERO) + pExtCtx->Ctx.x87.aRegs[iReg].au16[4] = enmTop == BS3EXTCTXTOPMM_SET ? UINT16_MAX : 0; + return true; + + case BS3EXTCTXMETHOD_ANCIENT: + pExtCtx->Ctx.Ancient.regs[iReg].mmx = uValue; + if (enmTop == BS3EXTCTXTOPMM_SET || enmTop == BS3EXTCTXTOPMM_ZERO) + pExtCtx->Ctx.Ancient.regs[iReg].au16[4] = enmTop == BS3EXTCTXTOPMM_SET ? UINT16_MAX : 0; + return true; + } + return false; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetMxCsr.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetMxCsr.c new file mode 100644 index 00000000..15184a1b --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetMxCsr.c @@ -0,0 +1,56 @@ +/* $Id: bs3-cmn-ExtCtxSetMxCsr.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxSetMxCsr + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3ExtCtxSetMxCsr +BS3_CMN_DEF(bool, Bs3ExtCtxSetMxCsr,(PBS3EXTCTX pExtCtx, uint32_t uValue)) +{ + AssertCompileMembersAtSameOffset(BS3EXTCTX, Ctx.x87.MXCSR, BS3EXTCTX, Ctx.x.x87.MXCSR); + if ( pExtCtx->enmMethod == BS3EXTCTXMETHOD_FXSAVE + || pExtCtx->enmMethod == BS3EXTCTXMETHOD_XSAVE) + { + pExtCtx->Ctx.x87.MXCSR = uValue; + return true; + } + return false; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetMxCsrMask.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetMxCsrMask.c new file mode 100644 index 00000000..64079d07 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetMxCsrMask.c @@ -0,0 +1,56 @@ +/* $Id: bs3-cmn-ExtCtxSetMxCsrMask.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxSetMxCsrMask + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3ExtCtxSetMxCsrMask +BS3_CMN_DEF(bool, Bs3ExtCtxSetMxCsrMask,(PBS3EXTCTX pExtCtx, uint32_t uValue)) +{ + AssertCompileMembersAtSameOffset(BS3EXTCTX, Ctx.x87.MXCSR, BS3EXTCTX, Ctx.x.x87.MXCSR); + if ( pExtCtx->enmMethod == BS3EXTCTXMETHOD_FXSAVE + || pExtCtx->enmMethod == BS3EXTCTXMETHOD_XSAVE) + { + pExtCtx->Ctx.x87.MXCSR_MASK = uValue; + return true; + } + return false; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetXmm.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetXmm.c new file mode 100644 index 00000000..d758cc91 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetXmm.c @@ -0,0 +1,61 @@ +/* $Id: bs3-cmn-ExtCtxSetXmm.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxSetXmm + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3ExtCtxSetXmm +BS3_CMN_DEF(bool, Bs3ExtCtxSetXmm,(PBS3EXTCTX pExtCtx, uint8_t iReg, PCRTUINT128U pValue)) +{ + AssertCompileMembersAtSameOffset(BS3EXTCTX, Ctx.x87.aXMM, BS3EXTCTX, Ctx.x.x87.aXMM); + switch (pExtCtx->enmMethod) + { + case BS3EXTCTXMETHOD_FXSAVE: + case BS3EXTCTXMETHOD_XSAVE: + if (iReg < RT_ELEMENTS(pExtCtx->Ctx.x87.aXMM)) + { + pExtCtx->Ctx.x87.aXMM[iReg].xmm = pValue->u; + return true; + } + break; + } + return false; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetYmm.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetYmm.c new file mode 100644 index 00000000..7ff2732f --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetYmm.c @@ -0,0 +1,79 @@ +/* $Id: bs3-cmn-ExtCtxSetYmm.c $ */ +/** @file + * BS3Kit - Bs3ExtCtxSetYmm + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3ExtCtxSetYmm +BS3_CMN_DEF(bool, Bs3ExtCtxSetYmm,(PBS3EXTCTX pExtCtx, uint8_t iReg, PCRTUINT256U pValue, uint8_t cbValue)) +{ + BS3_ASSERT(cbValue == 16 || cbValue == 32); + switch (pExtCtx->enmMethod) + { + case BS3EXTCTXMETHOD_FXSAVE: + if (iReg < RT_ELEMENTS(pExtCtx->Ctx.x87.aXMM)) + { + pExtCtx->Ctx.x87.aXMM[iReg].uXmm = pValue->DQWords.dqw0; + return true; + } + break; + + case BS3EXTCTXMETHOD_XSAVE: + if (iReg < RT_ELEMENTS(pExtCtx->Ctx.x.x87.aXMM)) + { + pExtCtx->Ctx.x87.aXMM[iReg].uXmm = pValue->DQWords.dqw0; + if (pExtCtx->fXcr0Nominal & XSAVE_C_YMM) + { + if (cbValue >= 32) + pExtCtx->Ctx.x.u.YmmHi.aYmmHi[iReg].uXmm = pValue->DQWords.dqw1; + else + { + pExtCtx->Ctx.x.u.YmmHi.aYmmHi[iReg].au64[0] = 0; + pExtCtx->Ctx.x.u.YmmHi.aYmmHi[iReg].au64[1] = 0; + } + /** @todo zero high ZMM part. */ + } + return true; + } + break; + } + return false; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-GetCpuVendor.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-GetCpuVendor.c new file mode 100644 index 00000000..982108cb --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-GetCpuVendor.c @@ -0,0 +1,63 @@ +/* $Id: bs3-cmn-GetCpuVendor.c $ */ +/** @file + * BS3Kit - Bs3GetCpuVendor + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit-template-header.h" + +#include <iprt/asm-amd64-x86.h> + + +#undef Bs3GetCpuVendor +BS3_CMN_DEF(BS3CPUVENDOR, Bs3GetCpuVendor,(void)) +{ + if (g_uBs3CpuDetected & BS3CPU_F_CPUID) + { + uint32_t uEbx, uEcx, uEdx; + ASMCpuIdExSlow(0, 0, 0, 0, NULL, &uEbx, &uEcx, &uEdx); + if (RTX86IsIntelCpu(uEbx, uEcx, uEdx)) + return BS3CPUVENDOR_INTEL; + if (RTX86IsAmdCpu(uEbx, uEcx, uEdx)) + return BS3CPUVENDOR_AMD; + if (RTX86IsViaCentaurCpu(uEbx, uEcx, uEdx)) + return BS3CPUVENDOR_VIA; + if (RTX86IsShanghaiCpu(uEbx, uEcx, uEdx)) + return BS3CPUVENDOR_SHANGHAI; + if (RTX86IsHygonCpu(uEbx, uEcx, uEdx)) + return BS3CPUVENDOR_HYGON; + return BS3CPUVENDOR_UNKNOWN; + } + return BS3CPUVENDOR_INTEL; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-GetModeName.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-GetModeName.c new file mode 100644 index 00000000..b8dcedab --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-GetModeName.c @@ -0,0 +1,72 @@ +/* $Id: bs3-cmn-GetModeName.c $ */ +/** @file + * BS3Kit - Bs3GetModeName + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit-template-header.h" + + + +#undef Bs3GetModeName +BS3_CMN_DEF(const char BS3_FAR *, Bs3GetModeName,(uint8_t bMode)) +{ + switch (bMode) + { + case BS3_MODE_RM: return g_szBs3ModeName_rm; + case BS3_MODE_PE16: return g_szBs3ModeName_pe16; + case BS3_MODE_PE16_32: return g_szBs3ModeName_pe16_32; + case BS3_MODE_PE16_V86: return g_szBs3ModeName_pe16_v86; + case BS3_MODE_PE32: return g_szBs3ModeName_pe32; + case BS3_MODE_PE32_16: return g_szBs3ModeName_pe32_16; + case BS3_MODE_PEV86: return g_szBs3ModeName_pev86; + case BS3_MODE_PP16: return g_szBs3ModeName_pp16; + case BS3_MODE_PP16_32: return g_szBs3ModeName_pp16_32; + case BS3_MODE_PP16_V86: return g_szBs3ModeName_pp16_v86; + case BS3_MODE_PP32: return g_szBs3ModeName_pp32; + case BS3_MODE_PP32_16: return g_szBs3ModeName_pp32_16; + case BS3_MODE_PPV86: return g_szBs3ModeName_ppv86; + case BS3_MODE_PAE16: return g_szBs3ModeName_pae16; + case BS3_MODE_PAE16_32: return g_szBs3ModeName_pae16_32; + case BS3_MODE_PAE16_V86: return g_szBs3ModeName_pae16_v86; + case BS3_MODE_PAE32: return g_szBs3ModeName_pae32; + case BS3_MODE_PAE32_16: return g_szBs3ModeName_pae32_16; + case BS3_MODE_PAEV86: return g_szBs3ModeName_paev86; + case BS3_MODE_LM16: return g_szBs3ModeName_lm16; + case BS3_MODE_LM32: return g_szBs3ModeName_lm32; + case BS3_MODE_LM64: return g_szBs3ModeName_lm64; + case BS3_MODE_INVALID: return "invalid"; + default: return "unknow"; + } +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-GetModeNameShortLower.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-GetModeNameShortLower.c new file mode 100644 index 00000000..a7488aa8 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-GetModeNameShortLower.c @@ -0,0 +1,72 @@ +/* $Id: bs3-cmn-GetModeNameShortLower.c $ */ +/** @file + * BS3Kit - Bs3GetModeNameShortLower + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit-template-header.h" + + + +#undef Bs3GetModeNameShortLower +BS3_CMN_DEF(const char BS3_FAR *, Bs3GetModeNameShortLower,(uint8_t bMode)) +{ + switch (bMode) + { + case BS3_MODE_RM: return g_szBs3ModeNameShortLower_rm; + case BS3_MODE_PE16: return g_szBs3ModeNameShortLower_pe16; + case BS3_MODE_PE16_32: return g_szBs3ModeNameShortLower_pe16_32; + case BS3_MODE_PE16_V86: return g_szBs3ModeNameShortLower_pe16_v86; + case BS3_MODE_PE32: return g_szBs3ModeNameShortLower_pe32; + case BS3_MODE_PE32_16: return g_szBs3ModeNameShortLower_pe32_16; + case BS3_MODE_PEV86: return g_szBs3ModeNameShortLower_pev86; + case BS3_MODE_PP16: return g_szBs3ModeNameShortLower_pp16; + case BS3_MODE_PP16_32: return g_szBs3ModeNameShortLower_pp16_32; + case BS3_MODE_PP16_V86: return g_szBs3ModeNameShortLower_pp16_v86; + case BS3_MODE_PP32: return g_szBs3ModeNameShortLower_pp32; + case BS3_MODE_PP32_16: return g_szBs3ModeNameShortLower_pp32_16; + case BS3_MODE_PPV86: return g_szBs3ModeNameShortLower_ppv86; + case BS3_MODE_PAE16: return g_szBs3ModeNameShortLower_pae16; + case BS3_MODE_PAE16_32: return g_szBs3ModeNameShortLower_pae16_32; + case BS3_MODE_PAE16_V86: return g_szBs3ModeNameShortLower_pae16_v86; + case BS3_MODE_PAE32: return g_szBs3ModeNameShortLower_pae32; + case BS3_MODE_PAE32_16: return g_szBs3ModeNameShortLower_pae32_16; + case BS3_MODE_PAEV86: return g_szBs3ModeNameShortLower_paev86; + case BS3_MODE_LM16: return g_szBs3ModeNameShortLower_lm16; + case BS3_MODE_LM32: return g_szBs3ModeNameShortLower_lm32; + case BS3_MODE_LM64: return g_szBs3ModeNameShortLower_lm64; + case BS3_MODE_INVALID: return "inv"; + default: return "unk"; + } +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-KbdRead.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-KbdRead.asm new file mode 100644 index 00000000..de74bdef --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-KbdRead.asm @@ -0,0 +1,75 @@ +; $Id: bs3-cmn-KbdRead.asm $ +;; @file +; BS3Kit - Bs3KbdRead. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Sends a read command to the keyboard controller and gets the result. +; +; The caller is responsible for making sure the keyboard controller is ready +; for a command (call Bs3KbdWait if unsure). +; +; @returns The value read is returned (in al). +; @param bCmd The read command. +; @uses al (obviously) +; +; @cproto BS3_DECL(uint8_t) Bs3KbdRead_c16(uint8_t bCmd); +; +BS3_PROC_BEGIN_CMN Bs3KbdRead, BS3_PBC_NEAR + push xBP + mov xBP, xSP + + mov al, [xBP + xCB*2] + out 64h, al ; Write the command. + +.check_status: + in al, 64h + test al, 1 ; KBD_STAT_OBF + jz .check_status + + in al, 60h ; Read the data. + + pop xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3KbdRead + +; +; We may be using the near code in some critical code paths, so don't +; penalize it. +; +BS3_CMN_FAR_STUB Bs3KbdRead, 2 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-KbdWait.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-KbdWait.asm new file mode 100644 index 00000000..e63fcb99 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-KbdWait.asm @@ -0,0 +1,64 @@ +; $Id: bs3-cmn-KbdWait.asm $ +;; @file +; BS3Kit - Bs3KbdWait. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +;; +; Waits for the keyboard controller to become ready. +; +; @cproto BS3_DECL(void) Bs3KbdWait_c16(void); +; +BS3_PROC_BEGIN_CMN Bs3KbdWait, BS3_PBC_HYBRID_0_ARGS + push xBP + mov xBP, xSP + push xAX + +.check_status: + in al, 64h + test al, 1 ; KBD_STAT_OBF + jnz .read_data_and_status + test al, 2 ; KBD_STAT_IBF + jnz .check_status + + pop xAX + pop xBP + BS3_HYBRID_RET + +.read_data_and_status: + in al, 60h + jmp .check_status +BS3_PROC_END_CMN Bs3KbdWait + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-KbdWrite.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-KbdWrite.asm new file mode 100644 index 00000000..f2ae9525 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-KbdWrite.asm @@ -0,0 +1,82 @@ +; $Id: bs3-cmn-KbdWrite.asm $ +;; @file +; BS3Kit - Bs3KbdRead. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3KbdWait + + +;; +; Sends a write command to the keyboard controller and then sends the data. +; +; The caller is responsible for making sure the keyboard controller is ready +; for a command (call Bs3KbdWait if unsure). +; +; @param bCmd The write command. +; @param bData The data to write. +; @uses Nothing. +; +; @todo Return status? +; +; @cproto BS3_DECL(void) Bs3KbdWait_c16(uint8_t bCmd, uint8_t bData); +; +BS3_PROC_BEGIN_CMN Bs3KbdWrite, BS3_PBC_NEAR + push xBP + mov xBP, xSP + push xAX +BONLY64 sub rsp, 20h + + mov al, [xBP + xCB*2] + out 64h, al ; Write the command. + call Bs3KbdWait + + mov al, [xBP + xCB*3] + out 60h, al ; Write the data + call Bs3KbdWait + +BONLY64 add rsp, 20h + pop xAX + pop xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3KbdWrite + +; +; We may be using the near code in some critical code paths, so don't +; penalize it. +; +BS3_CMN_FAR_STUB Bs3KbdWrite, 4 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemAlloc.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemAlloc.c new file mode 100644 index 00000000..851ddc26 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemAlloc.c @@ -0,0 +1,111 @@ +/* $Id: bs3-cmn-MemAlloc.c $ */ +/** @file + * BS3Kit - Bs3MemAlloc + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-memory.h" +#include <iprt/asm.h> + + +#undef Bs3MemAlloc +BS3_CMN_DEF(void BS3_FAR *, Bs3MemAlloc,(BS3MEMKIND enmKind, size_t cb)) +{ + void BS3_FAR *pvRet; + uint8_t idxSlabList; + +#if ARCH_BITS == 16 + /* Don't try allocate memory which address we cannot return. */ + if ( enmKind != BS3MEMKIND_REAL + && BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode)) + enmKind = BS3MEMKIND_REAL; +#endif + + idxSlabList = bs3MemSizeToSlabListIndex(cb); + if (idxSlabList < BS3_MEM_SLAB_LIST_COUNT) + { + /* + * Try allocate a chunk from the list. + */ + PBS3SLABHEAD pHead = enmKind == BS3MEMKIND_REAL + ? &g_aBs3LowSlabLists[idxSlabList] + : &g_aBs3UpperTiledSlabLists[idxSlabList]; + + BS3_ASSERT(g_aBs3LowSlabLists[idxSlabList].cbChunk >= cb); + pvRet = Bs3SlabListAlloc(pHead); + if (pvRet) + { /* likely */ } + else + { + /* + * Grow the list. + */ + PBS3SLABCTL pNew = (PBS3SLABCTL)Bs3SlabAlloc( enmKind == BS3MEMKIND_REAL + ? &g_Bs3Mem4KLow.Core + : &g_Bs3Mem4KUpperTiled.Core); + BS3_ASSERT(((uintptr_t)pNew & 0xfff) == 0); + if (pNew) + { + uint16_t const cbHdr = g_cbBs3SlabCtlSizesforLists[idxSlabList]; + BS3_XPTR_AUTO(void, pvNew); + BS3_XPTR_SET(void, pvNew, pNew); + + Bs3SlabInit(pNew, cbHdr, BS3_XPTR_GET_FLAT(void, pvNew) + cbHdr, _4K - cbHdr, pHead->cbChunk); + Bs3SlabListAdd(pHead, pNew); + + pvRet = Bs3SlabListAlloc(pHead); + } + } + } + else + { + /* + * Allocate one or more pages. + */ + size_t const cbAligned = RT_ALIGN_Z(cb, _4K); + uint16_t const cPages = cbAligned >> 12 /* div _4K */; + PBS3SLABCTL pSlabCtl = enmKind == BS3MEMKIND_REAL + ? &g_Bs3Mem4KLow.Core : &g_Bs3Mem4KUpperTiled.Core; + + pvRet = Bs3SlabAllocEx(pSlabCtl, + cPages, + cPages <= _64K / _4K ? BS3_SLAB_ALLOC_F_SAME_TILE : 0); + } + return pvRet; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemAllocZ.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemAllocZ.c new file mode 100644 index 00000000..a7beb560 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemAllocZ.c @@ -0,0 +1,53 @@ +/* $Id: bs3-cmn-MemAllocZ.c $ */ +/** @file + * BS3Kit - Bs3MemAllocZ + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-memory.h" + + +#undef Bs3MemAllocZ +BS3_CMN_DEF(void BS3_FAR *, Bs3MemAllocZ,(BS3MEMKIND enmKind, size_t cb)) +{ + void BS3_FAR *pvRet = Bs3MemAlloc(enmKind, cb); + if (pvRet) + Bs3MemZero(pvRet, cb); + return pvRet; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemChr.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemChr.asm new file mode 100644 index 00000000..82015c7e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemChr.asm @@ -0,0 +1,88 @@ +; $Id: bs3-cmn-MemChr.asm $ +;; @file +; BS3Kit - Bs3MemChr. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +;; +; @cproto BS3_CMN_PROTO_NOSB(void BS3_FAR *, Bs3MemChr,(void BS3_FAR const *pvHaystack, uint8_t bNeedle, size_t cbHaystack)); +; +BS3_PROC_BEGIN_CMN Bs3MemChr, BS3_PBC_HYBRID + push xBP + mov xBP, xSP + push xDI +TONLY16 push es + +%if TMPL_BITS == 64 + + mov rdi, rcx ; rdi = pvHaystack + mov rcx, r8 ; rcx = cbHaystack + mov al, dl ; bNeedle + mov rcx, r8 + +%elif TMPL_BITS == 16 + mov di, [bp + 2 + cbCurRetAddr] ; pvHaystack.off + mov es, [bp + 2 + cbCurRetAddr + 2] ; pvHaystack.sel + mov al, [bp + 2 + cbCurRetAddr + 4] ; bNeedle + mov cx, [bp + 2 + cbCurRetAddr + 6] ; cbHaystack + +%elif TMPL_BITS == 32 + mov edi, [ebp + 8] ; pvHaystack + mov al, byte [ebp + 4 + cbCurRetAddr + 4] ; bNeedle + mov ecx, [ebp + 4 + cbCurRetAddr + 8] ; cbHaystack +%else + %error "TMPL_BITS!" +%endif + + cld + repne scasb + je .found + + xor xAX, xAX +TONLY16 xor dx, dx + +.return: +TONLY16 pop es + pop xDI + pop xBP + BS3_HYBRID_RET + +.found: + lea xAX, [xDI - 1] +TONLY16 mov dx, es + jmp .return + +BS3_PROC_END_CMN Bs3MemChr + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemCmp.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemCmp.asm new file mode 100644 index 00000000..1f032010 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemCmp.asm @@ -0,0 +1,99 @@ +; $Id: bs3-cmn-MemCmp.asm $ +;; @file +; BS3Kit - Bs3MemCmp. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +;; +; @cproto BS3_CMN_PROTO_NOSB(int, Bs3MemCmp,(void const BS3_FAR *pv1, void const BS3_FAR *pv2, size_t cb)); +; +BS3_PROC_BEGIN_CMN Bs3MemCmp, BS3_PBC_HYBRID +TONLY16 CPU 8086 + push xBP + mov xBP, xSP + push xDI + push xSI +TNOT64 push es +TONLY16 push ds + cld + + ; + ; To save complexity and space, do straight forward byte compares. + ; +%if TMPL_BITS == 16 + mov di, [bp + 2 + cbCurRetAddr] ; pv1.off + mov es, [bp + 2 + cbCurRetAddr + 2] ; pv1.sel + mov si, [bp + 2 + cbCurRetAddr + 4] ; pv2.off + mov ds, [bp + 2 + cbCurRetAddr + 6] ; pv2.sel + mov cx, [bp + 2 + cbCurRetAddr + 8] ; cbDst + xor ax, ax + repe cmpsb + je .return + + mov al, [es:di - 1] + xor dx, dx + mov dl, [esi - 1] + sub ax, dx + +%else + %if TMPL_BITS == 64 + mov rdi, rcx ; rdi = pv1 + mov rsi, rdx ; rdi = pv2 + mov rcx, r8 ; rcx = cbDst + %else + mov ax, ds + mov es, ax ; paranoia + mov edi, [ebp + 4 + cbCurRetAddr] ; pv1 + mov esi, [ebp + 4 + cbCurRetAddr + 4] ; pv2 + mov ecx, [ebp + 4 + cbCurRetAddr + 8] ; cbDst + %endif + xor eax, eax + repe cmpsb + je .return + + mov al, [xDI - 1] + movzx edx, byte [xSI - 1] + sub eax, edx +%endif + +.return: +TONLY16 pop ds +TNOT64 pop es + pop xSI + pop xDI + pop xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3MemCmp + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemCpy.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemCpy.c new file mode 100644 index 00000000..9bbbe3c6 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemCpy.c @@ -0,0 +1,85 @@ +/* $Id: bs3-cmn-MemCpy.c $ */ +/** @file + * BS3Kit - Bs3MemCpy + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit-template-header.h" + +#undef Bs3MemCpy +BS3_CMN_DEF(void BS3_FAR *, Bs3MemCpy,(void BS3_FAR *pvDst, const void BS3_FAR *pvSrc, size_t cbToCopy)) +{ +#if 1 + const size_t BS3_FAR *pBigSrc = (const size_t BS3_FAR *)pvSrc; + size_t BS3_FAR *pBigDst = (size_t *)pvDst; + size_t cBig = cbToCopy / sizeof(size_t); + while (cBig-- > 0) + *pBigDst++ = *pBigSrc++; + + switch (cbToCopy % sizeof(size_t)) + { +#if TMPL_BITS >= 64 + case 7: ((uint8_t BS3_FAR *)pBigDst)[6] = ((const uint8_t BS3_FAR *)pBigSrc)[6]; + case 6: ((uint8_t BS3_FAR *)pBigDst)[5] = ((const uint8_t BS3_FAR *)pBigSrc)[5]; + case 5: ((uint8_t BS3_FAR *)pBigDst)[4] = ((const uint8_t BS3_FAR *)pBigSrc)[4]; + case 4: ((uint8_t BS3_FAR *)pBigDst)[3] = ((const uint8_t BS3_FAR *)pBigSrc)[3]; +#endif +#if TMPL_BITS >= 32 + case 3: ((uint8_t BS3_FAR *)pBigDst)[2] = ((const uint8_t BS3_FAR *)pBigSrc)[2]; + case 2: ((uint8_t BS3_FAR *)pBigDst)[1] = ((const uint8_t BS3_FAR *)pBigSrc)[1]; +#endif + case 1: ((uint8_t BS3_FAR *)pBigDst)[0] = ((const uint8_t BS3_FAR *)pBigSrc)[0]; + case 0: + break; + } + +#else + size_t cLargeRounds; + BS3CPTRUNION uSrc; + BS3PTRUNION uDst; + uSrc.pv = pvSrc; + uDst.pv = pvDst; + + cLargeRounds = cbToCopy / sizeof(*uSrc.pcb); + while (cLargeRounds-- > 0) + *uDst.pcb++ = *uSrc.pcb++; + + cbToCopy %= sizeof(*uSrc.pcb); + while (cbToCopy-- > 0) + *uDst.pb++ = *uSrc.pb++; + +#endif + + return pvDst; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemFree.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemFree.c new file mode 100644 index 00000000..f7592832 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemFree.c @@ -0,0 +1,73 @@ +/* $Id: bs3-cmn-MemFree.c $ */ +/** @file + * BS3Kit - Bs3MemFree + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-memory.h" + + +#undef Bs3MemFree +BS3_CMN_DEF(void, Bs3MemFree,(void BS3_FAR *pv, size_t cb)) +{ + if (pv != NULL) + { + uint16_t cChunks; + PBS3SLABCTL pCtl; + BS3_XPTR_AUTO(void, pvFlat); + BS3_XPTR_SET(void, pvFlat, pv); + + if (BS3_XPTR_GET_FLAT(void, pvFlat) & 0xfffU) + { + /* Use an XPTR here in case we're in real mode and the caller has + messed around with the pointer. */ + BS3_XPTR_AUTO(BS3SLABCTL, pTmp); + BS3_XPTR_SET_FLAT(BS3SLABCTL, pTmp, BS3_XPTR_GET_FLAT(void, pvFlat) & ~(uint32_t)0xfff); + pCtl = BS3_XPTR_GET(BS3SLABCTL, pTmp); + BS3_ASSERT(pCtl->cbChunk >= cb); + cChunks = 1; + } + else + { + pCtl = BS3_XPTR_GET_FLAT(void, pvFlat) < _1M ? &g_Bs3Mem4KLow.Core : &g_Bs3Mem4KUpperTiled.Core; + cChunks = RT_ALIGN_Z(cb, _4K) >> 12; + } + Bs3SlabFree(pCtl, BS3_XPTR_GET_FLAT(void, pvFlat), cChunks); + } +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemGuardedTestPage.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemGuardedTestPage.c new file mode 100644 index 00000000..7d5eb28c --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemGuardedTestPage.c @@ -0,0 +1,109 @@ +/* $Id: bs3-cmn-MemGuardedTestPage.c $ */ +/** @file + * BS3Kit - Bs3MemGuardedTestPageAlloc, Bs3MemGuardedTestPageFree + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "iprt/asm.h" + + +#undef Bs3MemGuardedTestPageAllocEx +BS3_CMN_PROTO_STUB(void BS3_FAR *, Bs3MemGuardedTestPageAllocEx,(BS3MEMKIND enmKind, uint64_t fPte)) +{ + uint8_t BS3_FAR *pb = (uint8_t BS3_FAR *)Bs3MemAlloc(enmKind, X86_PAGE_4K_SIZE * 3); + if (pb) + { + int rc; + + Bs3MemSet(pb, 0xcc, X86_PAGE_4K_SIZE); + Bs3MemSet(&pb[X86_PAGE_4K_SIZE], 0x00, X86_PAGE_4K_SIZE); + Bs3MemSet(&pb[X86_PAGE_4K_SIZE*2], 0xaa, X86_PAGE_4K_SIZE); + + rc = Bs3PagingProtectPtr(pb, X86_PAGE_4K_SIZE, fPte, UINT64_MAX & ~fPte); + if (RT_SUCCESS(rc)) + { + rc = Bs3PagingProtectPtr(&pb[X86_PAGE_4K_SIZE*2], X86_PAGE_4K_SIZE, fPte, UINT64_MAX & ~fPte); + if (RT_SUCCESS(rc)) + return pb + X86_PAGE_4K_SIZE; + + Bs3TestPrintf("warning: Bs3MemGuardedTestPageAlloc - Tail protect error %d (mode %#x)\n", rc, g_bBs3CurrentMode); + Bs3PagingProtectPtr(pb, X86_PAGE_4K_SIZE, X86_PTE_P, 0); + } + else + Bs3TestPrintf("warning: Bs3MemGuardedTestPageAlloc - Head protect error %d (mode %#x)\n", rc, g_bBs3CurrentMode); + Bs3MemFree(pb, X86_PAGE_4K_SIZE * 3); + } + else + Bs3TestPrintf("warning: Bs3MemGuardedTestPageAlloc - out of memory (mode %#x)\n", g_bBs3CurrentMode); + return NULL; +} + + +#undef Bs3MemGuardedTestPageAlloc +BS3_CMN_DEF(void BS3_FAR *, Bs3MemGuardedTestPageAlloc,(BS3MEMKIND enmKind)) +{ + return BS3_CMN_FAR_NM(Bs3MemGuardedTestPageAllocEx)(enmKind, 0); +} + + +#undef Bs3MemGuardedTestPageFree +BS3_CMN_DEF(void, Bs3MemGuardedTestPageFree,(void BS3_FAR *pvGuardedPage)) +{ + if (pvGuardedPage) + { + uint8_t BS3_FAR *pbGuardViolation; + uint8_t BS3_FAR *pb = (uint8_t BS3_FAR *)pvGuardedPage - X86_PAGE_4K_SIZE; + Bs3PagingProtectPtr(pb, X86_PAGE_4K_SIZE, + X86_PTE_P | X86_PTE_RW | X86_PTE_US | X86_PTE_A | X86_PTE_D, UINT64_MAX); + Bs3PagingProtectPtr(&pb[X86_PAGE_4K_SIZE*2], X86_PAGE_4K_SIZE, + X86_PTE_P | X86_PTE_RW | X86_PTE_US | X86_PTE_A | X86_PTE_D, UINT64_MAX); + + pbGuardViolation = ASMMemFirstMismatchingU8(pb, X86_PAGE_4K_SIZE, 0xcc); + if (pbGuardViolation) + Bs3TestFailedF("Leading guard page touched: byte %#05x is %#04x instead of 0xcc\n", + (unsigned)(uintptr_t)(pbGuardViolation - pb), *pbGuardViolation); + + pbGuardViolation = ASMMemFirstMismatchingU8(&pb[X86_PAGE_4K_SIZE*2], X86_PAGE_4K_SIZE, 0xaa); + if (pbGuardViolation) + Bs3TestFailedF("Trailing guard page touched: byte %#05x is %#04x instead of 0xaa\n", + (unsigned)(uintptr_t)(pbGuardViolation - &pb[X86_PAGE_4K_SIZE*2]), *pbGuardViolation); + + Bs3MemFree(pb, X86_PAGE_4K_SIZE * 3); + } +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemMove.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemMove.c new file mode 100644 index 00000000..7ac92e4e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemMove.c @@ -0,0 +1,88 @@ +/* $Id: bs3-cmn-MemMove.c $ */ +/** @file + * BS3Kit - Bs3MemMove + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit-template-header.h" + +#undef Bs3MemMove +BS3_CMN_DEF(void BS3_FAR *, Bs3MemMove,(void BS3_FAR *pvDst, const void BS3_FAR *pvSrc, size_t cbToCopy)) +{ + size_t cLargeRounds; + BS3CVPTRUNION uSrc; + BS3PTRUNION uDst; + uSrc.pv = pvSrc; + uDst.pv = pvDst; + + /* We don't care about segment wrapping here. */ + if ((uintptr_t)pvDst > (uintptr_t)pvSrc + cbToCopy) + { + /* Reverse copy. */ + uSrc.pb += cbToCopy; + uDst.pb += cbToCopy; + + cLargeRounds = cbToCopy / sizeof(*uSrc.pcb); + while (cLargeRounds-- > 0) + { + size_t uTmp = *--uSrc.pcb; + *--uDst.pcb = uTmp; + } + + cbToCopy %= sizeof(*uSrc.pcb); + while (cbToCopy-- > 0) + { + uint8_t b = *--uSrc.pb; + *--uDst.pb = b; + } + } + else + { + /* Forward copy. */ + cLargeRounds = cbToCopy / sizeof(*uSrc.pcb); + while (cLargeRounds-- > 0) + { + size_t uTmp = *uSrc.pcb++; + *uDst.pcb++ = uTmp; + } + + cbToCopy %= sizeof(*uSrc.pcb); + while (cbToCopy-- > 0) + { + uint8_t b = *uSrc.pb++; + *uDst.pb++ = b; + } + } + return pvDst; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemPCpy.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemPCpy.c new file mode 100644 index 00000000..ac23e7f2 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemPCpy.c @@ -0,0 +1,58 @@ +/* $Id: bs3-cmn-MemPCpy.c $ */ +/** @file + * BS3Kit - Bs3MemPCpy + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit-template-header.h" + +#undef Bs3MemPCpy +BS3_CMN_DEF(void BS3_FAR *, Bs3MemPCpy,(void BS3_FAR *pvDst, const void BS3_FAR *pvSrc, size_t cbToCopy)) +{ + size_t cLargeRounds; + BS3CPTRUNION uSrc; + BS3PTRUNION uDst; + uSrc.pv = pvSrc; + uDst.pv = pvDst; + + cLargeRounds = cbToCopy / sizeof(*uSrc.pcb); + while (cLargeRounds-- > 0) + *uDst.pcb++ = *uSrc.pcb++; + + cbToCopy %= sizeof(*uSrc.pcb); + while (cbToCopy-- > 0) + *uDst.pb++ = *uSrc.pb++; + + return uDst.pv; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemPrintInfo.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemPrintInfo.c new file mode 100644 index 00000000..a6f5b6f6 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemPrintInfo.c @@ -0,0 +1,95 @@ +/* $Id: bs3-cmn-MemPrintInfo.c $ */ +/** @file + * BS3Kit - Bs3MemPrintInfo + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-memory.h" +#include <iprt/asm.h> + + +/** + * Prints a slab control structure with allocation map. + * + * @param pCtl The slab control structure to print. + * @param pszPrefix The output prefix. + */ +static void Bs3MemPrintInfoSlabCtl(PBS3SLABCTL pCtl, const char BS3_FAR *pszPrefix) +{ + unsigned iChunk; + Bs3TestPrintf("%s / %#06x: %u of %u chunks free", pszPrefix, pCtl->cbChunk, pCtl->cFreeChunks, pCtl->cChunks); + for (iChunk = 0; iChunk < pCtl->cChunks; iChunk++) + { + if ((iChunk & 63) == 0) + Bs3TestPrintf("\n%s:", pszPrefix); + if (ASMBitTest(pCtl->bmAllocated, iChunk)) + Bs3TestPrintf((iChunk & 7) != 0 ? "x" : " x"); + else + Bs3TestPrintf((iChunk & 7) != 0 ? "-" : " -"); + } + Bs3TestPrintf("\n"); +} + + + +/** + * Prints a summary of a slab allocation list (i.e. the heap). + * + * @param paLists Array of BS3_MEM_SLAB_LIST_COUNT lists. + * @param pszPrefix The output prefix. + */ +static void Bs3MemPrintInfoSlabList(PBS3SLABHEAD paLists, const char BS3_FAR *pszPrefix) +{ + unsigned iSlab; + for (iSlab = 0; iSlab < BS3_MEM_SLAB_LIST_COUNT; iSlab++) + if (paLists[iSlab].cSlabs) + Bs3TestPrintf("%s / %#06x: %u slabs, %RU32 of %RU32 chunks free\n", + pszPrefix, paLists[iSlab].cbChunk, paLists[iSlab].cSlabs, + paLists[iSlab].cFreeChunks, paLists[iSlab].cChunks); +} + + +#undef Bs3MemPrintInfo +BS3_CMN_DEF(void, Bs3MemPrintInfo,(void)) +{ + Bs3MemPrintInfoSlabList(g_aBs3LowSlabLists, "Lower"); + Bs3MemPrintInfoSlabList(g_aBs3LowSlabLists, "Upper"); + Bs3MemPrintInfoSlabCtl(&g_Bs3Mem4KLow.Core, "4KLow"); + Bs3MemPrintInfoSlabCtl(&g_Bs3Mem4KUpperTiled.Core, "Tiled"); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemSet.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemSet.asm new file mode 100644 index 00000000..513a63d0 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemSet.asm @@ -0,0 +1,102 @@ +; $Id: bs3-cmn-MemSet.asm $ +;; @file +; BS3Kit - Bs3MemSet. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +;; +; @cproto BS3_CMN_PROTO_NOSB(void, Bs3MemSet,(void BS3_FAR *pvDst, uint8_t bFiller, size_t cbDst)); +; +BS3_PROC_BEGIN_CMN Bs3MemSet, BS3_PBC_HYBRID + push xBP + mov xBP, xSP + push xDI +%ifdef RT_ARCH_AMD64 + + mov rdi, rcx ; rdi = pvDst + mov rcx, r8 ; rcx = cbDst + movzx edx, dl ; bFiller + mov rax, 0101010101010101h + mul rdx + mov rcx, r8 + shr rcx, 3 ; calc qword count. + cld + rep stosq + + mov rcx, r8 ; cbDst + and rcx, 7 ; calc trailing byte count. + rep stosb + +%elif ARCH_BITS == 16 + push es + + mov di, [bp + 2 + cbCurRetAddr] ; pvDst.off + mov es, [bp + 2 + cbCurRetAddr + 2] ; pvDst.sel + mov al, [bp + 2 + cbCurRetAddr + 4] ; bFiller + mov ah, al + mov cx, [bp + 2 + cbCurRetAddr + 6] ; cbDst + shr cx, 1 ; calc dword count. + rep stosw + + mov cx, [bp + 2 + cbCurRetAddr + 6] ; cbDst + and cx, 1 ; calc tailing byte count. + rep stosb + + pop es + +%elif ARCH_BITS == 32 + mov edi, [ebp + 8] ; pvDst + mov al, byte [ebp + 4 + cbCurRetAddr + 4] ; bFiller + mov ah, al + mov dx, ax + shl eax, 16 + mov ax, dx ; eax = RT_MAKE_U32_FROM_U8(bFiller, bFiller, bFiller, bFiller) + mov ecx, [ebp + 4 + cbCurRetAddr + 8] ; cbDst + shr cx, 2 ; calc dword count. + rep stosd + + mov ecx, [ebp + 4 + cbCurRetAddr + 8] ; cbDst + and ecx, 3 ; calc tailing byte count. + rep stosb + +%else + %error "Unknown bitness." +%endif + + pop xDI + pop xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3MemSet + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemZero.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemZero.asm new file mode 100644 index 00000000..4e254020 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemZero.asm @@ -0,0 +1,103 @@ +; $Id: bs3-cmn-MemZero.asm $ +;; @file +; BS3Kit - Bs3MemZero. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +;; +; @cproto BS3_DECL(void) Bs3MemZero_c16(void BS3_FAR *pvDst, size_t cbDst); +; +BS3_PROC_BEGIN_CMN Bs3MemZero, BS3_PBC_HYBRID +%ifdef RT_ARCH_AMD64 + push rdi + + mov rdi, rcx ; rdi = pvDst + mov rcx, rdx ; rcx = cbDst + shr rcx, 3 ; calc qword count. + xor eax, eax ; rax = 0 (filler qword) + cld + rep stosq + + mov rcx, rdx ; cbDst + and rcx, 7 ; calc trailing byte count. + rep stosb + + pop rdi + BS3_HYBRID_RET + +%elif ARCH_BITS == 16 + push bp + mov bp, sp + push di + push es + + mov di, [bp + 2 + cbCurRetAddr] ; pvDst.off + mov dx, [bp + 2 + cbCurRetAddr + 2] ; pvDst.sel + mov es, dx + mov cx, [bp + 2 + cbCurRetAddr + 4] ; cbDst + shr cx, 1 ; calc dword count. + xor ax, ax + rep stosw + + mov cx, [bp + 2 + cbCurRetAddr + 4] ; cbDst + and cx, 1 ; calc tailing byte count. + rep stosb + + pop es + pop di + pop bp + BS3_HYBRID_RET + +%elif ARCH_BITS == 32 + push edi + + mov edi, [esp + 8] ; pvDst + mov ecx, [esp + 8 + 4] ; cbDst + shr cx, 2 ; calc dword count. + xor eax, eax + rep stosd + + mov ecx, [esp + 8 + 4] ; cbDst + and ecx, 3 ; calc tailing byte count. + rep stosb + + pop edi + BS3_HYBRID_RET + +%else + %error "Unknown bitness." +%endif +BS3_PROC_END_CMN Bs3MemZero + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingAlias.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingAlias.c new file mode 100644 index 00000000..a529e50c --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingAlias.c @@ -0,0 +1,193 @@ +/* $Id: bs3-cmn-PagingAlias.c $ */ +/** @file + * BS3Kit - Bs3PagingAlias, Bs3PagingUnalias + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-paging.h" +#include "iprt/asm-amd64-x86.h" + + +#undef Bs3PagingAlias +BS3_CMN_DEF(int, Bs3PagingAlias,(uint64_t uDst, uint64_t uPhysToAlias, uint32_t cbHowMuch, uint64_t fPte)) +{ +#if ARCH_BITS == 16 + if (!BS3_MODE_IS_V86(g_bBs3CurrentMode)) +#endif + { + RTCCUINTXREG cr3 = ASMGetCR3(); + uint32_t cPages; + int rc; + + /* + * Validate and adjust the input a little. + */ + if (uDst & X86_PAGE_OFFSET_MASK) + { + cbHowMuch += X86_PAGE_SIZE - (uDst & X86_PAGE_OFFSET_MASK); + uDst &= ~(uint64_t)X86_PAGE_OFFSET_MASK; + } + uPhysToAlias &= X86_PTE_PAE_PG_MASK; + fPte &= ~(X86_PTE_PAE_MBZ_MASK_NX | X86_PTE_PAE_PG_MASK); + cbHowMuch = RT_ALIGN_32(cbHowMuch, X86_PAGE_SIZE); + cPages = cbHowMuch >> X86_PAGE_SHIFT; + //Bs3TestPrintf("Bs3PagingAlias: adjusted: uDst=%RX64 uPhysToAlias=%RX64 cbHowMuch=%RX32 fPte=%Rx64 cPages=%RX32\n", uDst, uPhysToAlias, cbHowMuch, fPte, cPages); + if (BS3_MODE_IS_LEGACY_PAGING(g_bBs3CurrentMode)) + { + X86PTE BS3_FAR *pPteLegacy; + uint32_t uDst32 = (uint32_t)uDst; + uint32_t uPhysToAlias32 = (uint32_t)uPhysToAlias; + if (uDst32 != uDst) + { + Bs3TestPrintf("warning: Bs3PagingAlias - uDst=%RX64 is out of range for legacy paging!\n", uDst); + return VERR_INVALID_PARAMETER; + } + if (uPhysToAlias32 != uPhysToAlias) + { + Bs3TestPrintf("warning: Bs3PagingAlias - uPhysToAlias=%RX64 is out of range for legacy paging!\n", uPhysToAlias); + return VERR_INVALID_PARAMETER; + } + + /* + * Trigger page table splitting first. + */ + while (cPages > 0) + { + pPteLegacy = bs3PagingGetLegacyPte(cr3, uDst32, false, &rc); + if (pPteLegacy) + { + uint32_t cLeftInPt = X86_PG_ENTRIES - ((uDst32 >> X86_PT_SHIFT) & X86_PT_MASK); + if (cPages <= cLeftInPt) + break; + uDst32 += cLeftInPt << X86_PAGE_SHIFT; + cPages -= cLeftInPt; + } + else + { + Bs3TestPrintf("warning: Bs3PagingAlias - bs3PagingGetLegacyPte failed: rc=%d\n", rc); + return rc; + } + } + + /* + * Make the changes. + */ + cPages = cbHowMuch >> X86_PAGE_SHIFT; + uDst32 = (uint32_t)uDst; + while (cPages > 0) + { + uint32_t cLeftInPt = X86_PG_ENTRIES - ((uDst32 >> X86_PT_SHIFT) & X86_PT_MASK); + pPteLegacy = bs3PagingGetLegacyPte(cr3, uDst32, false, &rc); + while (cLeftInPt > 0 && cPages > 0) + { + pPteLegacy->u = uPhysToAlias32 | (uint32_t)fPte; + pPteLegacy++; + uDst32 += X86_PAGE_SIZE; + uPhysToAlias32 += X86_PAGE_SIZE; + cPages--; + cLeftInPt--; + } + } + } + else + { + X86PTEPAE BS3_FAR *pPtePae; + uint64_t const uDstSaved = uDst; + + /* + * Trigger page table splitting first. + */ + while (cPages > 0) + { + pPtePae = bs3PagingGetPaePte(cr3, g_bBs3CurrentMode, uDst, false, &rc); + if (pPtePae) + { + uint32_t cLeftInPt = X86_PG_PAE_ENTRIES - ((uDst >> X86_PT_PAE_SHIFT) & X86_PT_PAE_MASK); + if (cPages <= cLeftInPt) + break; + cPages -= cLeftInPt; + uDst += cLeftInPt << X86_PAGE_SHIFT; + } + else + { + Bs3TestPrintf("warning: Bs3PagingAlias - bs3PagingGetLegacyPte failed: rc=%d\n", rc); + return rc; + } + } + + /* + * Make the changes. + */ + cPages = cbHowMuch >> X86_PAGE_SHIFT; + uDst = uDstSaved; + while (cPages > 0) + { + uint32_t cLeftInPt = X86_PG_PAE_ENTRIES - ((uDst >> X86_PT_PAE_SHIFT) & X86_PT_PAE_MASK); + pPtePae = bs3PagingGetPaePte(cr3, g_bBs3CurrentMode, uDst, false, &rc); + while (cLeftInPt > 0 && cPages > 0) + { + pPtePae->u = uPhysToAlias | fPte; + pPtePae++; + uDst += X86_PAGE_SIZE; + uPhysToAlias += X86_PAGE_SIZE; + cPages--; + cLeftInPt--; + } + } + } + + ASMReloadCR3(); + } +#if ARCH_BITS == 16 + /* + * We can't do this stuff in v8086 mode, so switch to 16-bit prot mode and do it there. + */ + else + return Bs3SwitchFromV86To16BitAndCallC((FPFNBS3FAR)Bs3PagingAlias_f16, sizeof(uint64_t)*3 + sizeof(uint32_t), + uDst, uPhysToAlias, cbHowMuch, fPte); +#endif + return VINF_SUCCESS; +} + + +#undef Bs3PagingUnalias +BS3_CMN_DEF(int, Bs3PagingUnalias,(uint64_t uDst, uint32_t cbHowMuch)) +{ + return BS3_CMN_NM(Bs3PagingAlias)(uDst, uDst, cbHowMuch, X86_PTE_P | X86_PTE_RW | X86_PTE_US | X86_PTE_A | X86_PTE_D); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingData.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingData.c new file mode 100644 index 00000000..a6ab4f5b --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingData.c @@ -0,0 +1,59 @@ +/* $Id: bs3-cmn-PagingData.c $ */ +/** @file + * BS3Kit - Paging Data. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-paging.h" + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +#if ARCH_BITS == 16 + +uint32_t g_PhysPagingRootPP = UINT32_MAX; +uint32_t g_PhysPagingRootPAE = UINT32_MAX; +uint32_t g_PhysPagingRootLM = UINT32_MAX; + +uint32_t g_uBs3PagingCanonicalTrapsAddr = UINT32_MAX; +uint16_t g_cbBs3PagingCanonicalTraps = 0; +uint16_t g_cbBs3PagingOneCanonicalTrap = 0; + +#endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingInitRootForLM.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingInitRootForLM.c new file mode 100644 index 00000000..7a57dc1d --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingInitRootForLM.c @@ -0,0 +1,115 @@ +/* $Id: bs3-cmn-PagingInitRootForLM.c $ */ +/** @file + * BS3Kit - Bs3PagingInitRootForLM + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-paging.h" + + +#undef Bs3PagingInitRootForLM +BS3_CMN_DEF(int, Bs3PagingInitRootForLM,(void)) +{ + X86PML4 BS3_FAR *pPml4; + + BS3_ASSERT(g_PhysPagingRootLM == UINT32_MAX); + + /* + * The default is an identity mapping of the first 4GB repeated for the + * whole 48-bit virtual address space. So, we need one level more than PAE. + */ + pPml4 = (X86PML4 BS3_FAR *)Bs3MemAlloc(BS3MEMKIND_TILED, _4K); + if (pPml4) + { + X86PDPT BS3_FAR *pPdPtr = (X86PDPT BS3_FAR *)Bs3MemAlloc(BS3MEMKIND_TILED, _4K); + BS3_ASSERT((uintptr_t)pPdPtr != (uintptr_t)pPml4); + if (pPdPtr) + { + X86PDPAE BS3_FAR *paPgDirs = (X86PDPAE BS3_FAR *)Bs3MemAlloc(BS3MEMKIND_TILED, _4K * 4U); + BS3_ASSERT((uintptr_t)paPgDirs != (uintptr_t)pPml4); + if (paPgDirs) + { + unsigned i; + BS3_XPTR_AUTO(X86PML4, XPtrPml4); + BS3_XPTR_AUTO(X86PDPT, XPtrPdPtr); + BS3_XPTR_AUTO(X86PDPAE, XPtrPgDirs); + + /* Set up the 2048 2MB pages first. */ + for (i = 0; i < RT_ELEMENTS(paPgDirs->a) * 4U; i++) + paPgDirs->a[i].u = ((uint32_t)i << X86_PD_PAE_SHIFT) + | X86_PDE4M_P | X86_PDE4M_RW | X86_PDE4M_US | X86_PDE4M_PS | X86_PDE4M_A | X86_PDE4M_D; + + /* Set up the page directory pointer table next (4GB replicated, remember). */ + BS3_XPTR_SET(X86PDPAE, XPtrPgDirs, paPgDirs); + pPdPtr->a[0].u = BS3_XPTR_GET_FLAT(X86PDPAE, XPtrPgDirs) + | X86_PDPE_P | X86_PDPE_RW | X86_PDPE_US | X86_PDPE_A; + pPdPtr->a[1].u = pPdPtr->a[0].u + _4K; + pPdPtr->a[2].u = pPdPtr->a[1].u + _4K; + pPdPtr->a[3].u = pPdPtr->a[2].u + _4K; + + for (i = 4; i < RT_ELEMENTS(pPdPtr->a); i += 4) + { + pPdPtr->a[i + 0].u = pPdPtr->a[0].u; + pPdPtr->a[i + 1].u = pPdPtr->a[1].u; + pPdPtr->a[i + 2].u = pPdPtr->a[2].u; + pPdPtr->a[i + 3].u = pPdPtr->a[3].u; + } + + /* Set up the page map level 4 (all entries are the same). */ + BS3_XPTR_SET(X86PDPT, XPtrPdPtr, pPdPtr); + pPml4->a[0].u = BS3_XPTR_GET_FLAT(X86PDPT, XPtrPdPtr) + | X86_PML4E_P | X86_PML4E_RW | X86_PML4E_US | X86_PML4E_A; + for (i = 1; i < RT_ELEMENTS(pPml4->a); i++) + pPml4->a[i].u = pPml4->a[0].u; + + /* Set the global root pointer and we're done. */ + BS3_XPTR_SET(X86PML4, XPtrPml4, pPml4); + g_PhysPagingRootLM = BS3_XPTR_GET_FLAT(X86PML4, XPtrPml4); + return VINF_SUCCESS; + } + + BS3_ASSERT(false); + Bs3MemFree(pPdPtr, _4K); + } + BS3_ASSERT(false); + Bs3MemFree(pPml4, _4K); + } + BS3_ASSERT(false); + return VERR_NO_MEMORY; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingInitRootForPAE.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingInitRootForPAE.c new file mode 100644 index 00000000..4e376109 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingInitRootForPAE.c @@ -0,0 +1,102 @@ +/* $Id: bs3-cmn-PagingInitRootForPAE.c $ */ +/** @file + * BS3Kit - Bs3PagingInitRootForPAE + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-paging.h" + + +#undef Bs3PagingInitRootForPAE +BS3_CMN_DEF(int, Bs3PagingInitRootForPAE,(void)) +{ + X86PDPT BS3_FAR *pPdPtr; + + BS3_ASSERT(g_PhysPagingRootPAE == UINT32_MAX); + + /* + * By default we do a identity mapping of the entire address space + * using 2 GB pages. So, we need four page directories and one page + * directory pointer table with 4 entries. (We cannot share the PDPT with + * long mode because of reserved bit which will cause fatal trouble.) + * + * We assume that the availability of PAE means that PSE is available too. + */ +/** @todo testcase: loading invalid PDPTREs will tripple fault the CPU, won't it? We guru with invalid guest state. */ + pPdPtr = (X86PDPT BS3_FAR *)Bs3MemAlloc(BS3MEMKIND_TILED, sizeof(X86PDPE) * 4U); + if (pPdPtr) + { + X86PDPAE BS3_FAR *paPgDirs; + BS3_ASSERT(((uintptr_t)pPdPtr & 0x3f) == 0); + + paPgDirs = (X86PDPAE BS3_FAR *)Bs3MemAlloc(BS3MEMKIND_TILED, _4K * 4U); + if (paPgDirs) + { + unsigned i; + BS3_XPTR_AUTO(X86PDPT, XPtrPdPtr); + BS3_XPTR_AUTO(X86PDPAE, XPtrPgDirs); + + /* Set up the 2048 2MB pages first. */ + for (i = 0; i < RT_ELEMENTS(paPgDirs->a) * 4U; i++) + paPgDirs->a[i].u = ((uint32_t)i << X86_PD_PAE_SHIFT) + | X86_PDE4M_P | X86_PDE4M_RW | X86_PDE4M_US | X86_PDE4M_PS | X86_PDE4M_A | X86_PDE4M_D; + + /* Set up the four page directory pointer table entries. */ + BS3_XPTR_SET(X86PDPAE, XPtrPgDirs, paPgDirs); + pPdPtr->a[0].u = BS3_XPTR_GET_FLAT(X86PDPAE, XPtrPgDirs) | X86_PDPE_P; + pPdPtr->a[1].u = pPdPtr->a[0].u + _4K; + pPdPtr->a[2].u = pPdPtr->a[1].u + _4K; + pPdPtr->a[3].u = pPdPtr->a[2].u + _4K; + + /* Free up 8 consequtive entries for raw-mode hypervisor code. */ + if (1) /** @todo detect raw-mode and only do this then. */ + for (i = 0; i < 8; i++) + paPgDirs->a[i + (UINT32_C(0xc0000000) >> X86_PD_PAE_SHIFT)].b.u1Present = 0; + + /* Set the global root pointer and we're done. */ + BS3_XPTR_SET(X86PDPT, XPtrPdPtr, pPdPtr); + g_PhysPagingRootPAE = BS3_XPTR_GET_FLAT(X86PDPT, XPtrPdPtr); + return VINF_SUCCESS; + } + BS3_ASSERT(false); + Bs3MemFree(pPdPtr, _4K); + } + BS3_ASSERT(false); + return VERR_NO_MEMORY; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingInitRootForPP.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingInitRootForPP.c new file mode 100644 index 00000000..1701edb1 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingInitRootForPP.c @@ -0,0 +1,163 @@ +/* $Id: bs3-cmn-PagingInitRootForPP.c $ */ +/** @file + * BS3Kit - Bs3PagingInitRootForPP + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-paging.h" +#include "bs3-cmn-memory.h" /* bad bird */ +#include <iprt/param.h> + + +/** + * Creates page tables for a section of the page directory. + * + * @returns VINF_SUCCESS or VERR_NO_MEMORY. + * @param pPgDir The page directory. + * @param iFirst The first PD entry. + * @param cEntries How many PD entries to create pages tables for. + */ +static int Bs3PagingInitPageTablesForPgDir(X86PD BS3_FAR *pPgDir, unsigned iFirst, unsigned cEntries) +{ + uint32_t uCurPhys = (uint32_t)iFirst << X86_PD_SHIFT; + + while (cEntries--) + { + X86PT BS3_FAR *pPt = (X86PT BS3_FAR *)Bs3MemAlloc(BS3MEMKIND_TILED, _4K); + if (pPt) + { + unsigned j = 0; + for (j = 0; j < RT_ELEMENTS(pPt->a); j++, uCurPhys += PAGE_SIZE) + { + pPt->a[j].u = uCurPhys; + pPt->a[j].u |= X86_PTE_P | X86_PTE_RW | X86_PTE_US | X86_PTE_A | X86_PTE_D; + } + pPgDir->a[iFirst].u = Bs3SelPtrToFlat(pPt); + pPgDir->a[iFirst].u |= X86_PDE_P | X86_PDE_RW | X86_PDE_US | X86_PDE_A; + iFirst++; + } + else + return VERR_NO_MEMORY; + } + return VINF_SUCCESS; +} + + +#undef Bs3PagingInitRootForPP +BS3_CMN_DEF(int, Bs3PagingInitRootForPP,(void)) +{ + X86PD BS3_FAR *pPgDir; + + BS3_ASSERT(g_PhysPagingRootPP == UINT32_MAX); + + + /* + * By default we do a identity mapping of the entire address space + * using 4 GB pages. So, we only really need one page directory, + * that's all. + * + * ASSUMES page size extension available, i.e. pentium+. + */ + pPgDir = (X86PD BS3_FAR *)Bs3MemAllocZ(BS3MEMKIND_TILED, _4K); + if (pPgDir) + { + BS3_XPTR_AUTO(X86PD, XptrPgDir); + unsigned i; + int rc = VINF_SUCCESS; + + if (g_uBs3CpuDetected & BS3CPU_F_PSE) + { + for (i = 0; i < RT_ELEMENTS(pPgDir->a); i++) + { + pPgDir->a[i].u = (uint32_t)i << X86_PD_SHIFT; + pPgDir->a[i].u |= X86_PDE4M_P | X86_PDE4M_RW | X86_PDE4M_US | X86_PDE4M_PS | X86_PDE4M_A | X86_PDE4M_D; + } + + /* Free up 4 consequtive entries for raw-mode hypervisor code. */ + if (1) /** @todo detect raw-mode and only do this then. */ + for (i = 0; i < 4; i++) + pPgDir->a[i + (UINT32_C(0xc0000000) >> X86_PD_SHIFT)].b.u1Present = 0; + } + else + { + /* + * This requires 4MB of page tables if we map everything. + * So, we check how much memory we have available and make sure we + * don't use all of it for page tables. + */ + unsigned cMax = RT_ELEMENTS(pPgDir->a); + uint32_t cFreePages = g_Bs3Mem4KUpperTiled.Core.cFreeChunks + g_Bs3Mem4KLow.Core.cFreeChunks; + if (cFreePages >= cMax + 128) + Bs3PagingInitPageTablesForPgDir(pPgDir, 0, cMax); + else + { + unsigned cTop; + if (cMax >= 256 /*1MB*/) + { + cMax = cFreePages - 128; + cTop = 32; + } + else if (cMax >= 128) + { + cMax = cFreePages - 48; + cTop = 16; + } + else + { + cMax = cFreePages - 16; + cTop = RT_MIN(16, cMax / 4); + } + Bs3TestPrintf("Bs3PagingInitRootForPP: Warning! insufficient memory for mapping all 4GB!\n" + " Will only map 0x00000000-%#010RX32 and %#010RX32-0xffffffff.\n", + (uint32_t)(cMax - cTop) << PAGE_SHIFT, UINT32_MAX - ((uint32_t)cTop << PAGE_SHIFT) + 1); + rc = Bs3PagingInitPageTablesForPgDir(pPgDir, 0, cMax - cTop); + if (RT_SUCCESS(rc)) + rc = Bs3PagingInitPageTablesForPgDir(pPgDir, RT_ELEMENTS(pPgDir->a) - cTop, cTop); + } + } + + BS3_XPTR_SET(X86PD, XptrPgDir, pPgDir); + g_PhysPagingRootPP = BS3_XPTR_GET_FLAT(X86PD, XptrPgDir); + return rc; + } + + Bs3Printf("Bs3PagingInitRootForPP: No memory!\n"); + BS3_ASSERT(false); + return VERR_NO_MEMORY; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingMapRamAbove4GForLM.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingMapRamAbove4GForLM.c new file mode 100644 index 00000000..3ce4cbe8 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingMapRamAbove4GForLM.c @@ -0,0 +1,120 @@ +/* $Id: bs3-cmn-PagingMapRamAbove4GForLM.c $ */ +/** @file + * BS3Kit - Bs3PagingInitMapAbove4GForLM + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-paging.h" + +#if ARCH_BITS == 16 +# error "This does not work in 16-bit mode, only 32-bit and 64-bit" +#endif + +#undef Bs3PagingMapRamAbove4GForLM +BS3_CMN_DEF(int, Bs3PagingMapRamAbove4GForLM,(uint64_t *puFailurePoint)) +{ + X86PML4 * const pPml4 = (X86PML4 *)((uintptr_t)g_PhysPagingRootLM); + unsigned iPml4 = 0; + unsigned iPdpt = 4; + uint64_t uAddr = _4G; + X86PDPT * pPdpt; + + if (puFailurePoint) + *puFailurePoint = 0; + + /* Must call Bs3PagingInitRootForLM first! */ + if (g_PhysPagingRootLM == UINT32_MAX) + return VERR_WRONG_ORDER; + + /* Done already? */ + if (pPml4->a[0].u != pPml4->a[4].u) + return VINF_ALREADY_INITIALIZED; + + /* + * Map RAM pages up to g_uBs3EndOfRamAbove4G. + */ + pPdpt = (X86PDPT *)(pPml4->a[0].u & X86_PML4E_PG_MASK); + while (uAddr < g_uBs3EndOfRamAbove4G) + { + X86PDPAE *pPd; + unsigned i; + + /* Do we need a new PDPT? */ + if (iPdpt >= RT_ELEMENTS(pPdpt->a)) + { + if (iPml4 >= RT_ELEMENTS(pPml4->a) / 2) + { + if (puFailurePoint) + *puFailurePoint = uAddr; + return VERR_OUT_OF_RANGE; + } + pPdpt = (X86PDPT *)Bs3MemAllocZ(BS3MEMKIND_FLAT32, X86_PAGE_SIZE); + if (!pPdpt || ((uintptr_t)pPdpt & X86_PAGE_OFFSET_MASK)) + { + if (puFailurePoint) + *puFailurePoint = uAddr; + return !pPdpt ? VERR_NO_MEMORY : VERR_UNSUPPORTED_ALIGNMENT; + } + pPml4->a[++iPml4].u = X86_PML4E_P | X86_PML4E_RW | X86_PML4E_US | X86_PML4E_A + | (uintptr_t)pPdpt; + iPdpt = 0; + } + + /* Allocate a new page directory. */ + pPd = (X86PDPAE *)Bs3MemAlloc(BS3MEMKIND_FLAT32, X86_PAGE_SIZE); + if (!pPd || ((uintptr_t)pPd & X86_PAGE_OFFSET_MASK)) + { + if (puFailurePoint) + *puFailurePoint = uAddr; + return !pPd ? VERR_NO_MEMORY : VERR_UNSUPPORTED_ALIGNMENT; + } + + /* Initialize it. */ + for (i = 0; i < RT_ELEMENTS(pPd->a); i++) + { + pPd->a[i].u = uAddr | X86_PDE4M_P | X86_PDE4M_RW | X86_PDE4M_US | X86_PDE4M_PS | X86_PDE4M_A | X86_PDE4M_D; + uAddr += _2M; + } + + /* Insert it into the page directory pointer table. */ + pPdpt->a[iPdpt++].u = (uintptr_t)pPd | X86_PDPE_P | X86_PDPE_RW | X86_PDPE_US | X86_PDPE_A; + } + + return VINF_SUCCESS; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingProtect.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingProtect.c new file mode 100644 index 00000000..347fd3fd --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingProtect.c @@ -0,0 +1,392 @@ +/* $Id: bs3-cmn-PagingProtect.c $ */ +/** @file + * BS3Kit - Bs3PagingProtect + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-paging.h" +#include <iprt/asm-amd64-x86.h> +#include <iprt/param.h> + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +#if 0 +# define BS3PAGING_DPRINTF1(a) Bs3TestPrintf a +#else +# define BS3PAGING_DPRINTF1(a) do { } while (0) +#endif +#if 0 +# define BS3PAGING_DPRINTF2(a) Bs3TestPrintf a +#else +# define BS3PAGING_DPRINTF2(a) do { } while (0) +#endif + + +static void *bs3PagingBuildPaeTable(uint64_t uTmpl, uint64_t cbIncrement, BS3MEMKIND enmKind, int *prc) +{ + uint64_t BS3_FAR *pau64 = (uint64_t BS3_FAR *)Bs3MemAlloc(enmKind, _4K); + if (pau64) + { + unsigned i; + for (i = 0; i < _4K / sizeof(uint64_t); i++, uTmpl += cbIncrement) + pau64[i] = uTmpl; + } + else + *prc = VERR_NO_MEMORY; + return pau64; +} + + +#undef bs3PagingGetLegacyPte +BS3_CMN_DEF(X86PTE BS3_FAR *, bs3PagingGetLegacyPte,(RTCCUINTXREG cr3, uint32_t uFlat, bool fUseInvlPg, int *prc)) +{ + X86PTE BS3_FAR *pPTE = NULL; +#if TMPL_BITS == 16 + uint32_t const uMaxAddr = BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode) ? _1M - 1 : BS3_SEL_TILED_AREA_SIZE - 1; +#else + uint32_t const uMaxAddr = UINT32_MAX; +#endif + BS3PAGING_DPRINTF2(("bs3PagingGetLegacyPte: cr3=%RX32 uFlat=%RX32 uMaxAddr=%RX32\n", (uint32_t)cr3, uFlat, uMaxAddr)); + + *prc = VERR_OUT_OF_RANGE; + if (cr3 <= uMaxAddr) + { + unsigned const iPde = (uFlat >> X86_PD_SHIFT) & X86_PD_MASK; + PX86PD const pPD = (PX86PD)Bs3XptrFlatToCurrent(cr3 & X86_CR3_PAGE_MASK); + + BS3_ASSERT(pPD->a[iPde].b.u1Present); + if (pPD->a[iPde].b.u1Present) + { + unsigned const iPte = (uFlat >> X86_PT_SHIFT) & X86_PT_MASK; + + BS3_ASSERT(pPD->a[iPde].b.u1Present); + BS3PAGING_DPRINTF2(("bs3PagingGetLegacyPte: pPD=%p iPde=%#x: %#RX32\n", pPD, iPde, pPD->a[iPde])); + if (pPD->a[iPde].b.u1Present) + { + if (!pPD->a[iPde].b.u1Size) + { + if (pPD->a[iPde].u <= uMaxAddr) + pPTE = &((X86PT BS3_FAR *)Bs3XptrFlatToCurrent(pPD->a[iPde].u & ~(uint32_t)PAGE_OFFSET_MASK))->a[iPte]; + else + BS3PAGING_DPRINTF1(("bs3PagingGetLegacyPte: out of range! iPde=%#x: %#x\n", iPde, pPD->a[iPde].u)); + } + else + { + X86PT BS3_FAR *pPT; + uint32_t uPte = (pPD->a[iPde].u & ~(uint32_t)(X86_PDE4M_PS | X86_PDE4M_G | X86_PDE4M_PG_HIGH_MASK)) \ + | X86_PTE_D; + if (pPD->a[iPde].b.u1Global) + uPte |= X86_PTE_G; + if (pPD->a[iPde].b.u1PAT) + uPte |= X86_PTE_PAT; + + pPT = (X86PT BS3_FAR *)bs3PagingBuildPaeTable(RT_MAKE_U64(uPte, uPte | PAGE_SIZE), + RT_MAKE_U64(PAGE_SIZE*2, PAGE_SIZE*2), + uMaxAddr > _1M ? BS3MEMKIND_TILED : BS3MEMKIND_REAL, prc); + + BS3PAGING_DPRINTF2(("bs3PagingGetLegacyPte: Built pPT=%p uPte=%RX32\n", pPT, uPte)); + if (pPT) + { + ASMAtomicUoWriteU32(&pPD->a[iPde].u, + Bs3SelPtrToFlat(pPT) + | ( pPD->a[iPde].u + & ~(uint32_t)(X86_PTE_PG_MASK | X86_PDE4M_PS | X86_PDE4M_G | X86_PDE4M_D))); + BS3PAGING_DPRINTF2(("bs3PagingGetLegacyPte: iPde=%#x: %#RX32\n", iPde, pPD->a[iPde].u)); + if (fUseInvlPg) + ASMInvalidatePage(uFlat); + pPTE = &pPT->a[iPte]; + } + } + } + } + } + else + BS3PAGING_DPRINTF1(("bs3PagingGetLegacyPte: out of range! cr3=%#x\n", cr3)); + return pPTE; +} + + +/** + * Get the PTE for an address, given a PAE or long mode CR3. + * + * @returns Pointer to the PTE on success, NULL on failure. + * @param cr3 The CR3. + * @param bMode Indicates whether it's PAE or long mode. + * @param uFlat The address for which we want the PTE. + * @param fUseInvlPg Whether we can use invalidate page when + * replacing large pages. + * @param prc Updated only on failure. + */ +#undef bs3PagingGetPaePte +BS3_CMN_DEF(X86PTEPAE BS3_FAR *, bs3PagingGetPaePte,(RTCCUINTXREG cr3, uint8_t bMode, uint64_t uFlat, bool fUseInvlPg, int *prc)) +{ + X86PTEPAE BS3_FAR *pPTE = NULL; +#if TMPL_BITS == 16 + uint32_t const uMaxAddr = BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode) ? _1M - 1 : BS3_SEL_TILED_AREA_SIZE - 1; +#else + uintptr_t const uMaxAddr = ~(uintptr_t)0; +#endif + + *prc = VERR_OUT_OF_RANGE; + if ((cr3 & X86_CR3_AMD64_PAGE_MASK) <= uMaxAddr) + { + X86PDPAE BS3_FAR *pPD; + if (BS3_MODE_IS_64BIT_SYS(bMode)) + { + unsigned const iPml4e = (uFlat >> X86_PML4_SHIFT) & X86_PML4_MASK; + X86PML4 BS3_FAR *pPml4 = (X86PML4 BS3_FAR *)Bs3XptrFlatToCurrent(cr3 & X86_CR3_AMD64_PAGE_MASK); + BS3_ASSERT(pPml4->a[iPml4e].n.u1Present); + if ((pPml4->a[iPml4e].u & X86_PML4E_PG_MASK) <= uMaxAddr) + { + unsigned const iPdpte = (uFlat >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64; + X86PDPT BS3_FAR *pPdpt = (X86PDPT BS3_FAR *)Bs3XptrFlatToCurrent(pPml4->a[iPml4e].u & X86_PML4E_PG_MASK); + BS3_ASSERT(pPdpt->a[iPdpte].n.u1Present); + if (!pPdpt->a[iPdpte].b.u1Size) + { + if ((pPdpt->a[iPdpte].u & X86_PDPE_PG_MASK) <= uMaxAddr) + pPD = (X86PDPAE BS3_FAR *)Bs3XptrFlatToCurrent(pPdpt->a[iPdpte].u & ~(uint64_t)PAGE_OFFSET_MASK); + else + BS3PAGING_DPRINTF1(("bs3PagingGetPaePte: out of range! iPdpte=%#x: %RX64 max=%RX32\n", + iPdpte, pPdpt->a[iPdpte].u, (uint32_t)uMaxAddr)); + } + else + { + /* Split 1GB page. */ + pPD = (X86PDPAE BS3_FAR *)bs3PagingBuildPaeTable(pPdpt->a[iPdpte].u, _2M, + uMaxAddr > _1M ? BS3MEMKIND_TILED : BS3MEMKIND_REAL, prc); + if (pPD) + { + ASMAtomicUoWriteU64(&pPdpt->a[iPdpte].u, + Bs3SelPtrToFlat(pPD) + | ( pPdpt->a[iPdpte].u + & ~(uint64_t)(X86_PDPE_PG_MASK | X86_PDE4M_PS | X86_PDE4M_G | X86_PDE4M_D))); + if (fUseInvlPg) + ASMInvalidatePage(uFlat); + } + } + } + } + //else if (uFlat <= UINT32_MAX) - fixme! + else if (!(uFlat >> 32)) + { + unsigned const iPdpte = ((uint32_t)uFlat >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE; + X86PDPT BS3_FAR *pPdpt = (X86PDPT BS3_FAR *)Bs3XptrFlatToCurrent(cr3 & X86_CR3_PAE_PAGE_MASK); + BS3_ASSERT(pPdpt->a[iPdpte].n.u1Present); + if ((pPdpt->a[iPdpte].u & X86_PDPE_PG_MASK) <= uMaxAddr) + pPD = (X86PDPAE BS3_FAR *)Bs3XptrFlatToCurrent(pPdpt->a[iPdpte].u & X86_PDPE_PG_MASK); + else + BS3PAGING_DPRINTF1(("bs3PagingGetPaePte: out of range! iPdpte=%#x: %RX64 max=%RX32\n", + iPdpte, pPdpt->a[iPdpte].u, (uint32_t)uMaxAddr)); + } + else + { + pPD = NULL; + BS3PAGING_DPRINTF1(("bs3PagingGetPaePte: out of range! uFlat=%#RX64 max=%RX32\n", uFlat, (uint32_t)uMaxAddr)); + } + if (pPD) + { + unsigned const iPte = (uFlat >> X86_PT_PAE_SHIFT) & X86_PT_PAE_MASK; + unsigned const iPde = (uFlat >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK; + if (!pPD->a[iPde].b.u1Size) + { + if ((pPD->a[iPde].u & X86_PDE_PAE_PG_MASK) <= uMaxAddr) + pPTE = &((X86PTPAE BS3_FAR *)Bs3XptrFlatToCurrent(pPD->a[iPde].u & ~(uint64_t)PAGE_OFFSET_MASK))->a[iPte]; + else + BS3PAGING_DPRINTF1(("bs3PagingGetPaePte: out of range! iPde=%#x: %RX64 max=%RX32\n", + iPde, pPD->a[iPde].u, (uint32_t)uMaxAddr)); + } + else + { + /* Split 2MB page. */ + X86PTPAE BS3_FAR *pPT; + uint64_t uTmpl = pPD->a[iPde].u & ~(uint64_t)(X86_PDE4M_G | X86_PDE4M_PS | X86_PDE4M_PAT); + if (!pPD->a[iPde].b.u1Global) + uTmpl |= X86_PTE_G; + if (!pPD->a[iPde].b.u1PAT) + uTmpl |= X86_PTE_PAT; + + pPT = (X86PTPAE BS3_FAR *)bs3PagingBuildPaeTable(uTmpl, PAGE_SIZE, + uMaxAddr > _1M ? BS3MEMKIND_TILED : BS3MEMKIND_REAL, prc); + if (pPT) + { + ASMAtomicUoWriteU64(&pPD->a[iPde].u, + Bs3SelPtrToFlat(pPT) + | ( pPD->a[iPde].u + & ~(uint64_t)(X86_PTE_PAE_PG_MASK | X86_PDE4M_PS | X86_PDE4M_G | X86_PDE4M_D))); + if (fUseInvlPg) + ASMInvalidatePage(uFlat); + pPTE = &pPT->a[iPte]; + } + } + } + } + else + BS3PAGING_DPRINTF1(("bs3PagingGetPaePte: out of range! cr3=%#RX32 uMaxAddr=%#RX32\n", (uint32_t)cr3, (uint32_t)uMaxAddr)); + return pPTE; +} + + +#undef Bs3PagingProtect +BS3_CMN_DEF(int, Bs3PagingProtect,(uint64_t uFlat, uint64_t cb, uint64_t fSet, uint64_t fClear)) +{ +#if ARCH_BITS == 16 + if (!BS3_MODE_IS_V86(g_bBs3CurrentMode)) +#endif + { + RTCCUINTXREG const cr3 = ASMGetCR3(); + RTCCUINTXREG const cr4 = g_uBs3CpuDetected & BS3CPU_F_CPUID ? ASMGetCR4() : 0; + bool const fLegacyPTs = !(cr4 & X86_CR4_PAE); + bool const fUseInvlPg = (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80486 + && ( cb < UINT64_C(16)*PAGE_SIZE + || (cr4 & X86_CR4_PGE)); + unsigned cEntries; + int rc; + + /* + * Adjust the range parameters. + */ + cb += uFlat & PAGE_OFFSET_MASK; + cb = RT_ALIGN_64(cb, PAGE_SIZE); + uFlat &= ~(uint64_t)PAGE_OFFSET_MASK; + + fSet &= ~X86_PTE_PAE_PG_MASK; + fClear &= ~X86_PTE_PAE_PG_MASK; + + BS3PAGING_DPRINTF1(("Bs3PagingProtect: uFlat=%RX64 cb=%RX64 fSet=%RX64 fClear=%RX64 %s %s\n", uFlat, cb, fSet, fClear, + fLegacyPTs ? "legacy" : "pae/amd64", fUseInvlPg ? "invlpg" : "reload-cr3")); + if (fLegacyPTs) + { + /* + * Legacy page tables. + */ + while ((uint32_t)cb > 0) + { + PX86PTE pPte = BS3_CMN_FAR_NM(bs3PagingGetLegacyPte)(cr3, (uint32_t)uFlat, fUseInvlPg, &rc); + if (!pPte) + return rc; + + cEntries = X86_PG_ENTRIES - ((uFlat >> X86_PT_SHIFT) & X86_PT_MASK); + while (cEntries-- > 0 && cb > 0) + { + pPte->u &= ~(uint32_t)fClear; + pPte->u |= (uint32_t)fSet; + if (fUseInvlPg) + ASMInvalidatePage(uFlat); + + pPte++; + uFlat += PAGE_SIZE; + cb -= PAGE_SIZE; + } + } + } + else + { + /* + * Long mode or PAE page tables (at this level they are the same). + */ + while (cb > 0) + { + PX86PTEPAE pPte = BS3_CMN_FAR_NM(bs3PagingGetPaePte)(cr3, g_bBs3CurrentMode, uFlat, fUseInvlPg, &rc); + if (!pPte) + return rc; + + cEntries = X86_PG_ENTRIES - ((uFlat >> X86_PT_PAE_SHIFT) & X86_PT_PAE_MASK); + while (cEntries-- > 0 && cb > 0) + { + pPte->u &= ~fClear; + pPte->u |= fSet; + if (fUseInvlPg) + ASMInvalidatePage(uFlat); + + pPte++; + uFlat += PAGE_SIZE; + cb -= PAGE_SIZE; + } + } + } + + /* + * Flush the TLB if we didn't use INVLPG above. + */ + BS3PAGING_DPRINTF2(("Bs3PagingProtect: reloading cr3=%RX32\n", (uint32_t)cr3)); + //if (!fUseInvlPg) + ASMSetCR3(cr3); + BS3PAGING_DPRINTF2(("Bs3PagingProtect: reloaded cr3=%RX32\n", (uint32_t)cr3)); + } +#if ARCH_BITS == 16 + /* + * We can do this stuff in v8086 mode. + */ + else + return Bs3SwitchFromV86To16BitAndCallC((FPFNBS3FAR)Bs3PagingProtect_f16, sizeof(uint64_t) * 4, uFlat, cb, fSet, fClear); +#endif + return VINF_SUCCESS; +} + + +#undef Bs3PagingProtectPtr +BS3_CMN_DEF(int, Bs3PagingProtectPtr,(void *pv, size_t cb, uint64_t fSet, uint64_t fClear)) +{ +#if ARCH_BITS == 16 + return BS3_CMN_NM(Bs3PagingProtect)(Bs3SelPtrToFlat(pv), cb, fSet, fClear); +#else + return BS3_CMN_NM(Bs3PagingProtect)((uintptr_t)pv, cb, fSet, fClear); +#endif +} + + +#undef Bs3PagingGetPte +BS3_CMN_DEF(void BS3_FAR *, Bs3PagingGetPte,(uint64_t uFlat, int *prc)) +{ + RTCCUINTXREG const cr3 = ASMGetCR3(); + RTCCUINTXREG const cr4 = g_uBs3CpuDetected & BS3CPU_F_CPUID ? ASMGetCR4() : 0; + bool const fLegacyPTs = !(cr4 & X86_CR4_PAE); + bool const fUseInvlPg = (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80486; + int rc; + if (!prc) + prc = &rc; + if (!fLegacyPTs) + return BS3_CMN_FAR_NM(bs3PagingGetPaePte)(cr3, g_bBs3CurrentMode, uFlat, fUseInvlPg, prc); + if (uFlat < _4G) + return BS3_CMN_FAR_NM(bs3PagingGetLegacyPte)(cr3, (uint32_t)uFlat, fUseInvlPg, prc); + *prc = VERR_OUT_OF_RANGE; + return NULL; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingQueryAddressInfo.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingQueryAddressInfo.c new file mode 100644 index 00000000..b846b248 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingQueryAddressInfo.c @@ -0,0 +1,159 @@ +/* $Id: bs3-cmn-PagingQueryAddressInfo.c $ */ +/** @file + * BS3Kit - Bs3PagingQueryAddressInfo + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <bs3kit.h> +#include <iprt/asm-amd64-x86.h> +#include <VBox/err.h> + + +#undef Bs3PagingQueryAddressInfo +BS3_CMN_DEF(int, Bs3PagingQueryAddressInfo,(uint64_t uFlat, PBS3PAGINGINFO4ADDR pPgInfo)) +{ + RTCCUINTXREG const cr3 = ASMGetCR3(); + RTCCUINTXREG const cr4 = g_uBs3CpuDetected & BS3CPU_F_CPUID ? ASMGetCR4() : 0; + bool const fLegacyPTs = !(cr4 & X86_CR4_PAE); + int rc = VERR_OUT_OF_RANGE; + + + pPgInfo->fFlags = 0; + pPgInfo->u.apbEntries[0] = NULL; + pPgInfo->u.apbEntries[1] = NULL; + pPgInfo->u.apbEntries[2] = NULL; + pPgInfo->u.apbEntries[3] = NULL; + + if (!fLegacyPTs) + { +#if TMPL_BITS == 16 + uint32_t const uMaxAddr = BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode) ? _1M - 1 : BS3_SEL_TILED_AREA_SIZE - 1; +#else + uintptr_t const uMaxAddr = ~(uintptr_t)0; +#endif + uint64_t const fEfer = g_uBs3CpuDetected & BS3CPU_F_LONG_MODE ? ASMRdMsr(MSR_K6_EFER) : 0; + + pPgInfo->cEntries = fEfer & MSR_K6_EFER_LMA ? 4 : 3; + pPgInfo->cbEntry = sizeof(X86PTEPAE); + if ((cr3 & X86_CR3_AMD64_PAGE_MASK) <= uMaxAddr) + { + if ( (fEfer & MSR_K6_EFER_LMA) + && X86_IS_CANONICAL(uFlat)) + { + /* 48-bit long mode paging. */ + pPgInfo->u.Pae.pPml4e = (X86PML4E BS3_FAR *)Bs3XptrFlatToCurrent(cr3 & X86_CR3_AMD64_PAGE_MASK); + pPgInfo->u.Pae.pPml4e += (uFlat >> X86_PML4_SHIFT) & X86_PML4_MASK; + if (!pPgInfo->u.Pae.pPml4e->n.u1Present) + rc = VERR_PAGE_NOT_PRESENT; + else if ((pPgInfo->u.Pae.pPml4e->u & X86_PML4E_PG_MASK) <= uMaxAddr) + { + pPgInfo->u.Pae.pPdpe = (X86PDPE BS3_FAR *)Bs3XptrFlatToCurrent(pPgInfo->u.Pae.pPml4e->u & X86_PML4E_PG_MASK); + pPgInfo->u.Pae.pPdpe += (uFlat >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64; + if (!pPgInfo->u.Pae.pPdpe->n.u1Present) + rc = VERR_PAGE_NOT_PRESENT; + else if (pPgInfo->u.Pae.pPdpe->b.u1Size) + rc = VINF_SUCCESS; + else + rc = VINF_TRY_AGAIN; + } + } + else if ( !(fEfer & MSR_K6_EFER_LMA) + && uFlat <= _4G) + { + /* 32-bit PAE paging. */ + pPgInfo->u.Pae.pPdpe = (X86PDPE BS3_FAR *)Bs3XptrFlatToCurrent(cr3 & X86_CR3_PAE_PAGE_MASK); + pPgInfo->u.Pae.pPdpe += ((uint32_t)uFlat >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE; + if (!pPgInfo->u.Pae.pPdpe->n.u1Present) + rc = VERR_PAGE_NOT_PRESENT; + else + rc = VINF_TRY_AGAIN; + } + + /* Common code for the PD and PT levels. */ + if ( rc == VINF_TRY_AGAIN + && (pPgInfo->u.Pae.pPdpe->u & X86_PDPE_PG_MASK) <= uMaxAddr) + { + rc = VERR_OUT_OF_RANGE; + pPgInfo->u.Pae.pPde = (X86PDEPAE BS3_FAR *)Bs3XptrFlatToCurrent(pPgInfo->u.Pae.pPdpe->u & X86_PDPE_PG_MASK); + pPgInfo->u.Pae.pPde += (uFlat >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK; + if (!pPgInfo->u.Pae.pPde->n.u1Present) + rc = VERR_PAGE_NOT_PRESENT; + else if (pPgInfo->u.Pae.pPde->b.u1Size) + rc = VINF_SUCCESS; + else if ((pPgInfo->u.Pae.pPde->u & X86_PDE_PAE_PG_MASK) <= uMaxAddr) + { + pPgInfo->u.Pae.pPte = (X86PTEPAE BS3_FAR *)Bs3XptrFlatToCurrent(pPgInfo->u.Pae.pPde->u & X86_PDE_PAE_PG_MASK); + rc = VINF_SUCCESS; + } + } + else if (rc == VINF_TRY_AGAIN) + rc = VERR_OUT_OF_RANGE; + } + } + else + { +#if TMPL_BITS == 16 + uint32_t const uMaxAddr = BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode) ? _1M - 1 : BS3_SEL_TILED_AREA_SIZE - 1; +#else + uint32_t const uMaxAddr = UINT32_MAX; +#endif + + pPgInfo->cEntries = 2; + pPgInfo->cbEntry = sizeof(X86PTE); + if ( uFlat < _4G + && cr3 <= uMaxAddr) + { + pPgInfo->u.Legacy.pPde = (X86PDE BS3_FAR *)Bs3XptrFlatToCurrent(cr3 & X86_CR3_PAGE_MASK); + pPgInfo->u.Legacy.pPde += ((uint32_t)uFlat >> X86_PD_SHIFT) & X86_PD_MASK; + if (!pPgInfo->u.Legacy.pPde->b.u1Present) + rc = VERR_PAGE_NOT_PRESENT; + else if (pPgInfo->u.Legacy.pPde->b.u1Size) + rc = VINF_SUCCESS; + else if (pPgInfo->u.Legacy.pPde->u <= uMaxAddr) + { + pPgInfo->u.Legacy.pPte = (X86PTE BS3_FAR *)Bs3XptrFlatToCurrent(pPgInfo->u.Legacy.pPde->u & X86_PDE_PG_MASK); + pPgInfo->u.Legacy.pPte += ((uint32_t)uFlat >> X86_PT_SHIFT) & X86_PT_MASK; + if (pPgInfo->u.Legacy.pPte->n.u1Present) + rc = VINF_SUCCESS; + else + rc = VERR_PAGE_NOT_PRESENT; + } + } + } + return rc; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingSetupCanonicalTraps.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingSetupCanonicalTraps.c new file mode 100644 index 00000000..3343819f --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingSetupCanonicalTraps.c @@ -0,0 +1,123 @@ +/* $Id: bs3-cmn-PagingSetupCanonicalTraps.c $ */ +/** @file + * BS3Kit - Bs3PagingSetupCanonicalTraps + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-paging.h" +#include "iprt/asm-amd64-x86.h" + + +#undef Bs3PagingSetupCanonicalTraps +BS3_CMN_PROTO_STUB(void BS3_FAR *, Bs3PagingSetupCanonicalTraps,(void)) +{ + if (g_uBs3CpuDetected & BS3CPU_F_LONG_MODE) + { +#if ARCH_BITS == 16 + if (!BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode)) +#endif + { + uint8_t BS3_FAR *pb; + X86PTEPAE BS3_FAR *paLoPtes; + X86PTEPAE BS3_FAR *paHiPtes; + int rc; + + /* Already initialized? Likely. */ + if (g_cbBs3PagingCanonicalTraps != 0) + return Bs3XptrFlatToCurrent(g_uBs3PagingCanonicalTrapsAddr); + + /* Initialize AMD64 page tables if necessary (unlikely). */ + if (g_PhysPagingRootLM == UINT32_MAX) + { + rc = Bs3PagingInitRootForLM(); + if (RT_FAILURE(rc)) + return NULL; + } + + /* + * Get the page table entries first to avoid having to unmap things. + */ + paLoPtes = bs3PagingGetPaePte(g_PhysPagingRootLM, BS3_MODE_LM64, UINT64_C(0x00007fffffffe000), false, &rc); + paHiPtes = bs3PagingGetPaePte(g_PhysPagingRootLM, BS3_MODE_LM64, UINT64_C(0xffff800000000000), false, &rc); + if (!paHiPtes || !paLoPtes) + { + Bs3TestPrintf("warning: Bs3PagingSetupCanonicalTraps - failed to get PTEs!\n"); + return NULL; + } + + /* + * Allocate the buffer. Currently using 8KB on each side. + */ + pb = (uint8_t BS3_FAR *)Bs3MemAlloc(BS3MEMKIND_TILED, X86_PAGE_SIZE * 4); + if (pb) + { + RTCCUINTXREG uFlat = Bs3SelPtrToFlat(pb); + + /* + * Inject it into the page tables. + */ + paLoPtes[0].u &= ~X86_PTE_PAE_PG_MASK; + paLoPtes[0].u |= uFlat + X86_PAGE_SIZE * 0; + paLoPtes[1].u &= ~X86_PTE_PAE_PG_MASK; + paLoPtes[1].u |= uFlat + X86_PAGE_SIZE * 1; + + paHiPtes[0].u &= ~X86_PTE_PAE_PG_MASK; + paHiPtes[0].u |= uFlat + X86_PAGE_SIZE * 2; + paHiPtes[1].u &= ~X86_PTE_PAE_PG_MASK; + paHiPtes[1].u |= uFlat + X86_PAGE_SIZE * 3; + ASMReloadCR3(); + + /* + * Update globals and return successfully. + */ + g_uBs3PagingCanonicalTrapsAddr = uFlat; + g_cbBs3PagingCanonicalTraps = X86_PAGE_SIZE * 4; + g_cbBs3PagingOneCanonicalTrap = X86_PAGE_SIZE * 2; + return pb; + } + + Bs3TestPrintf("warning: Bs3PagingSetupCanonicalTraps - out of memory (mode %#x)\n", g_bBs3CurrentMode); + } +#if ARCH_BITS == 16 + else + Bs3TestPrintf("warning: Bs3PagingSetupCanonicalTraps was called in RM or V86 mode (%#x)!\n", g_bBs3CurrentMode); +#endif + } + return NULL; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Panic.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Panic.asm new file mode 100644 index 00000000..e4d286c8 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Panic.asm @@ -0,0 +1,48 @@ +; $Id: bs3-cmn-Panic.asm $ +;; @file +; BS3Kit - Bs3Panic, Common. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_PROC_BEGIN_CMN Bs3Panic, BS3_PBC_HYBRID_0_ARGS + push xBP + mov xBP, xSP + cli +.panic_again: + hlt + jmp .panic_again +BS3_PROC_END_CMN Bs3Panic + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PerCpuData.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PerCpuData.c new file mode 100644 index 00000000..9ebe7096 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PerCpuData.c @@ -0,0 +1,74 @@ +/* $Id: bs3-cmn-PerCpuData.c $ */ +/** @file + * BS3Kit - Per CPU Data. + * + * @remarks Not quite sure how to do per-cpu data yet, but this is stuff + * that eventually needs to be per CPU. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-test.h" + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +#if ARCH_BITS == 16 + +/** Hint for 16-bit trap handlers regarding the high word of EIP. */ +uint32_t g_uBs3TrapEipHint = 0; + +/** Flat pointer to a BS3TRAPFRAME registered by Bs3TrapSetJmp. + * When this is non-zero, the setjmp is considered armed. */ +uint32_t g_pBs3TrapSetJmpFrame = 0; + +/** The current CPU mode. */ +uint8_t g_bBs3CurrentMode = BS3_MODE_RM; + +uint8_t g_bStupidUnalignedCompiler1 = 0xfe; + +/** Set to disable special V8086 \#GP and \#UD handling in Bs3TrapDefaultHandler. + * This is useful for getting */ +bool volatile g_fBs3TrapNoV86Assist = false; + +/** The context of the last Bs3TrapSetJmp call. + * This will have eax set to 1 and need only be restored when it triggers. */ +BS3REGCTX g_Bs3TrapSetJmpCtx; + +#endif /* ARCH_BITS == 16 */ + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PicMaskAll.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PicMaskAll.c new file mode 100644 index 00000000..19946af6 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PicMaskAll.c @@ -0,0 +1,51 @@ +/* $Id: bs3-cmn-PicMaskAll.c $ */ +/** @file + * BS3Kit - Masks all IRQs on the PIC. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include <iprt/asm-amd64-x86.h> + + +#undef Bs3PicMaskAll +BS3_CMN_DEF(void, Bs3PicMaskAll,(void)) +{ + ASMOutU8(0xa1, 0xff); + ASMOutU8(0x21, 0xff); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PicSetup.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PicSetup.c new file mode 100644 index 00000000..7db73469 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PicSetup.c @@ -0,0 +1,90 @@ +/* $Id: bs3-cmn-PicSetup.c $ */ +/** @file + * BS3Kit - PIC Setup. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include <iprt/asm-amd64-x86.h> +#include "bs3-cmn-pic.h" + + + +/** + * Configures the PIC, once only. + * + * Subsequent calls to this function will not do anything. + * + * The PIC will be programmed to use IDT/IVT vectors 0x70 thru 0x7f, auto + * end-of-interrupt, and all IRQs masked. The individual PIC users will have to + * use #Bs3PicUpdateMask unmask their IRQ once they've got all the handlers + * installed. + */ +#undef Bs3PicSetup +BS3_CMN_DEF(void, Bs3PicSetup,(bool fForcedReInit)) +{ + /* + * The first call configures the PIC to send interrupts to vectors 0x70 thru 0x7f, + * masking all of them. Things producing IRQs is responsible for configure their + * handlers and then(!) use Bs3PicUpdateMask to unmask the IRQ. + */ + if (!g_fBs3PicConfigured || fForcedReInit) + { + g_fBs3PicConfigured = true; + + /* Start init. */ + ASMOutU8(BS3_PIC_PORT_MASTER, BS3_PIC_CMD_INIT | BS3_PIC_CMD_INIT_F_4STEP); + ASMOutU8(BS3_PIC_PORT_SLAVE, BS3_PIC_CMD_INIT | BS3_PIC_CMD_INIT_F_4STEP); + + /* Set IRQ base. */ + ASMOutU8(BS3_PIC_PORT_MASTER + 1, 0x70); + ASMOutU8(BS3_PIC_PORT_SLAVE + 1, 0x78); + + /* Dunno. */ + ASMOutU8(BS3_PIC_PORT_MASTER + 1, 4); + ASMOutU8(BS3_PIC_PORT_SLAVE + 1, 2); + + /* Set IRQ base. */ + ASMOutU8(BS3_PIC_PORT_MASTER + 1, BS3_PIC_I4_F_AUTO_EOI); + ASMOutU8(BS3_PIC_PORT_SLAVE + 1, BS3_PIC_I4_F_AUTO_EOI); + + /* Mask everything. */ + ASMOutU8(BS3_PIC_PORT_MASTER + 1, UINT8_MAX); + ASMOutU8(BS3_PIC_PORT_SLAVE + 1, UINT8_MAX); + } +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PicUpdateMask.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PicUpdateMask.c new file mode 100644 index 00000000..6485a236 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PicUpdateMask.c @@ -0,0 +1,55 @@ +/* $Id: bs3-cmn-PicUpdateMask.c $ */ +/** @file + * BS3Kit - PIC Setup. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include <iprt/asm-amd64-x86.h> +#include "bs3-cmn-pic.h" + + +#undef Bs3PicUpdateMask +BS3_CMN_DEF(uint16_t, Bs3PicUpdateMask,(uint16_t fAndMask, uint16_t fOrMask)) +{ + uint8_t bPic0Mask = (ASMInU8(BS3_PIC_PORT_MASTER + 1) & (uint8_t)fAndMask) | (uint8_t)fOrMask; + uint8_t bPic1Mask = (ASMInU8(BS3_PIC_PORT_SLAVE + 1) & (fAndMask >> 8)) | (fOrMask >> 8); + ASMOutU8(BS3_PIC_PORT_SLAVE + 1, bPic1Mask); + ASMOutU8(BS3_PIC_PORT_MASTER + 1, bPic0Mask); + return RT_MAKE_U16(bPic0Mask, bPic1Mask); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PitIrqHandler.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PitIrqHandler.c new file mode 100644 index 00000000..b296bb11 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PitIrqHandler.c @@ -0,0 +1,76 @@ +/* $Id: bs3-cmn-PitIrqHandler.c $ */ +/** @file + * BS3Kit - The PIT IRQ Handler and associated data. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include <iprt/asm-amd64-x86.h> + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +#if ARCH_BITS == 16 +/** Nano seconds (approx) since last the PIT timer was started. */ +uint64_t volatile g_cBs3PitNs = 0; +/** Milliseconds seconds (very approx) since last the PIT timer was started. */ +uint64_t volatile g_cBs3PitMs = 0; +/** Number of ticks since last the PIT timer was started. */ +uint32_t volatile g_cBs3PitTicks = 0; +/** The current interval in nanon seconds. */ +uint32_t g_cBs3PitIntervalNs = 0; +/** The current interval in milliseconds (approximately). + * This is 0 if not yet started (used for checking the state internally). */ +uint16_t g_cBs3PitIntervalMs = 0; +/** The current PIT frequency (approximately). 0 if not yet started. */ +uint16_t volatile g_cBs3PitIntervalHz = 0; +#endif + + +BS3_DECL_NEAR_CALLBACK(void) BS3_CMN_NM(bs3PitIrqHandler)(PBS3TRAPFRAME pTrapFrame) +{ + if (g_cBs3PitIntervalHz) + { + g_cBs3PitMs += g_cBs3PitIntervalMs; + g_cBs3PitNs += g_cBs3PitIntervalNs; + g_cBs3PitTicks++; + } + NOREF(pTrapFrame); + ASMOutU8(0x20, 0x20); /** @todo function! */ +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintChr.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintChr.asm new file mode 100644 index 00000000..90c7d6c1 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintChr.asm @@ -0,0 +1,115 @@ +; $Id: bs3-cmn-PrintChr.asm $ +;; @file +; BS3Kit - Bs3PrintChr. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +BS3_EXTERN_CMN Bs3Syscall + + +TMPL_BEGIN_TEXT + +;; +; @cproto BS3_DECL(void) Bs3PrintChr_c16(char ch); +; +BS3_PROC_BEGIN_CMN Bs3PrintChr, BS3_PBC_NEAR + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push xAX + push xCX + push xBX + +%if TMPL_BITS == 16 + ; If we're in real mode or v8086 mode, call the VGA BIOS directly. + mov bl, [g_bBs3CurrentMode] + cmp bl, BS3_MODE_RM + je .do_vga_bios_call + %if 0 + test bl, BS3_MODE_CODE_V86 + jz .do_system_call + %else + jmp .do_system_call + %endif + +.do_vga_bios_call: + mov al, [xBP + xCB*2] ; Load the char + cmp al, 0ah ; \n + je .newline + mov bx, 0ff00h + mov ah, 0eh + int 10h + jmp .return +.newline: + mov ax, 0e0dh ; cmd + '\r'. + mov bx, 0ff00h + int 10h + mov ax, 0e0ah ; cmd + '\n'. + mov bx, 0ff00h + int 10h + jmp .return +%endif + +.do_system_call: + mov cl, [xBP + xCB*2] ; Load the char + mov ax, BS3_SYSCALL_PRINT_CHR + call Bs3Syscall ; near! no BS3_CALL! + +.return: + pop xBX + pop xCX + pop xAX + pop xBP + BS3_CALL_CONV_EPILOG 1 + ret +BS3_PROC_END_CMN Bs3PrintChr + +; +; Generate 16-bit far stub. +; Peformance critical, so don't penalize near calls. +; +BS3_CMN_FAR_STUB Bs3PrintChr, 2 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintStr.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintStr.c new file mode 100644 index 00000000..7ff63b60 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintStr.c @@ -0,0 +1,44 @@ +/* $Id: bs3-cmn-PrintStr.c $ */ +/** @file + * BS3Kit - Bs3PrintStr + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit-template-header.h" + +#undef Bs3PrintStr +BS3_CMN_DEF(void, Bs3PrintStr,(const char BS3_FAR *pszString)) +{ + Bs3PrintStrN(pszString, Bs3StrLen(pszString)); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintStrN.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintStrN.asm new file mode 100644 index 00000000..4a0fe223 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintStrN.asm @@ -0,0 +1,204 @@ +; $Id: bs3-cmn-PrintStrN.asm $ +;; @file +; BS3Kit - Bs3PrintStrN. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +BS3_EXTERN_CMN Bs3Syscall + + +TMPL_BEGIN_TEXT + +;; +; @cproto BS3_DECL(void) Bs3PrintStrN_c16(const char BS3_FAR *pszString, size_t cchString); +; +; ASSUMES cchString < 64KB! +; +BS3_PROC_BEGIN_CMN Bs3PrintStrN, BS3_PBC_NEAR + BS3_CALL_CONV_PROLOG 2 + push xBP + mov xBP, xSP + push xAX + push xCX + push xBX + push xSI + +%if TMPL_BITS == 16 + ; If we're in real mode or v8086 mode, call the VGA BIOS directly. + mov bl, [g_bBs3CurrentMode] + cmp bl, BS3_MODE_RM + je .do_bios_call + %if 0 + test bl, BS3_MODE_CODE_V86 + jz .do_system_call + %else + jmp .do_system_call + %endif + + ; + ; We can do the work right here. + ; +.do_bios_call: + push ds + lds si, [xBP + xCB + cbCurRetAddr] ; DS:SI -> string. + cld + mov cx, [xBP + xCB + cbCurRetAddr + sCB] ; Use CX for counting down. + call Bs3PrintStrN_c16_CX_Bytes_At_DS_SI + pop ds + jmp .return +%endif + + + ; + ; Need to do system call(s). + ; String goes into CX:xSI, count into DX. + ; + ; We must ensure the string is real-mode addressable first, if not we + ; must do it char-by-char. + ; +.do_system_call: +%if TMPL_BITS == 16 + mov cx, [xBP + xCB + cbCurRetAddr + 2] +%else + mov cx, ds +%endif + mov xSI, [xBP + xCB + cbCurRetAddr] + mov dx, [xBP + xCB + cbCurRetAddr + sCB] +%if TMPL_BITS == 16 + +%else + cmp xSI, _1M + jae .char_by_char +%endif + mov ax, BS3_SYSCALL_PRINT_STR + call Bs3Syscall ; near! no BS3_CALL! + +.return: + pop xSI + pop xBX + pop xCX + pop xAX + pop xBP + BS3_CALL_CONV_EPILOG 2 + BS3_HYBRID_RET + + ; + ; Doesn't look like it's real-mode addressable. So, char-by-char. + ; +.char_by_char: +%if TMPL_BITS == 16 + push es + mov es, cx +%endif + cld + test dx, dx + jz .char_by_char_return +.char_by_char_loop: + mov ax, BS3_SYSCALL_PRINT_CHR + mov cl, [BS3_ONLY_16BIT(es:) xSI] + call Bs3Syscall ; near! no BS3_CALL! + inc xSI + dec xDX + jnz .char_by_char_loop +.char_by_char_return: +%if TMPL_BITS == 16 + pop es +%endif + jmp .return + +BS3_PROC_END_CMN Bs3PrintStrN + + +%if TMPL_BITS == 16 +; +; This code is shared with the system handler. +; +; @param CX Number of byte sto print. +; @param DS:SI The string to print +; @uses AX, BX, CX, SI +; +BS3_PROC_BEGIN Bs3PrintStrN_c16_CX_Bytes_At_DS_SI + CPU 8086 + ; Check if CX is zero first. + test cx, cx + jz .bios_loop_done + + ; The loop, processing the string char-by-char. +.bios_loop: + mov bx, 0ff00h + lodsb ; al = next char + cmp al, 0ah ; \n + je .bios_loop_newline +%ifdef BS3_STRICT + test al, al + jnz .not_zero + hlt +.not_zero: +%endif + mov ah, 0eh +.bios_loop_int10h: + int 10h + loop .bios_loop +.bios_loop_done: + ret + +.bios_loop_newline: + mov ax, 0e0dh ; cmd + '\r'. + int 10h + mov ax, 0e0ah ; cmd + '\n'. + mov bx, 0ff00h + jmp .bios_loop_int10h +BS3_PROC_END Bs3PrintStrN_c16_CX_Bytes_At_DS_SI + + +; +; Generate 16-bit far stub. +; Peformance critical, so don't penalize near calls. +; +BS3_CMN_FAR_STUB Bs3PrintStrN, 6 + +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintU32.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintU32.asm new file mode 100644 index 00000000..90be607d --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintU32.asm @@ -0,0 +1,93 @@ +; $Id: bs3-cmn-PrintU32.asm $ +;; @file +; BS3Kit - Bs3PrintU32, Common. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3PrintStr + +;; +; Prints a 32-bit unsigned integer value. +; +; @param [xBP + xCB*2] 32-bit value to format and print. +; +BS3_PROC_BEGIN_CMN Bs3PrintU32, BS3_PBC_HYBRID + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push sAX + push sDX + push sCX + push sBX +BONLY16 push ds + + mov eax, [xBP + xCB + cbCurRetAddr] + + ; Allocate a stack buffer and terminate it. ds:bx points ot the end. + sub xSP, 30h +BONLY16 mov bx, ss +BONLY16 mov ds, bx + mov xBX, xSP + add xBX, 2fh + mov byte [xBX], 0 + + mov ecx, 10 ; what to divide by +.next: + xor edx, edx + div ecx ; edx:eax / ecx -> eax and rest in edx. + add dl, '0' + dec xBX + mov [BS3_ONLY_16BIT(ss:)xBX], dl + cmp eax, 0 + jnz .next + + ; Print the string. +BONLY64 add rsp, 18h +BONLY16 push ss + push xBX + BS3_CALL Bs3PrintStr, 1 + + add xSP, 30h + BS3_IF_16_32_64BIT(2, 0, 18h) + xCB +BONLY16 pop ds + pop sBX + pop sCX + pop sDX + pop sAX + leave + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3PrintU32 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintX32.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintX32.asm new file mode 100644 index 00000000..6469ac08 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintX32.asm @@ -0,0 +1,97 @@ +; $Id: bs3-cmn-PrintX32.asm $ +;; @file +; BS3Kit - Bs3PrintU32, Common. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3PrintStr + +;; +; Prints a 32-bit unsigned integer value as hex. +; +; @param [xBP + xCB*2] 32-bit value to format and print. +; +BS3_PROC_BEGIN_CMN Bs3PrintX32, BS3_PBC_HYBRID + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push sAX + push sDX + push sCX + push sBX +BONLY16 push ds + + mov eax, [xBP + xCB + cbCurRetAddr] + + ; Allocate a stack buffer and terminate it. ds:bx points ot the end. + sub xSP, 30h +BONLY16 mov bx, ss +BONLY16 mov ds, bx + mov xBX, xSP + add xBX, 2fh + mov byte [xBX], 0 + + mov ecx, 16 ; what to divide by +.next: + xor edx, edx + div ecx ; edx:eax / ecx -> eax and rest in edx. + cmp dl, 10 + jb .decimal + add dl, 'a' - '0' - 10 +.decimal: + add dl, '0' + dec xBX + mov [BS3_ONLY_16BIT(ss:)xBX], dl + cmp eax, 0 + jnz .next + + ; Print the string. +BONLY64 add rsp, 18h +BONLY16 push ss + push xBX + BS3_CALL Bs3PrintStr, 1 + + add xSP, 30h + BS3_IF_16_32_64BIT(2, 0, 18h) + xCB +BONLY16 pop ds + pop sBX + pop sCX + pop sDX + pop sAX + leave + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3PrintX32 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Printf.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Printf.c new file mode 100644 index 00000000..29fcd518 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Printf.c @@ -0,0 +1,95 @@ +/* $Id: bs3-cmn-Printf.c $ */ +/** @file + * BS3Kit - Bs3Printf, Bs3PrintfV + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include <iprt/ctype.h> + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +/** Output buffering for Bs3TestPrintfV. */ +typedef struct BS3PRINTBUF +{ + uint8_t cchBuf; + char achBuf[79]; +} BS3PRINTBUF; + + +static BS3_DECL_CALLBACK(size_t) bs3PrintFmtOutput(char ch, void BS3_FAR *pvUser) +{ + BS3PRINTBUF BS3_FAR *pBuf = (BS3PRINTBUF BS3_FAR *)pvUser; + 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') + return 1; + } + Bs3PrintStrN(&pBuf->achBuf[0], pBuf->cchBuf); + pBuf->cchBuf = 0; + return ch != '\0'; +} + + +#undef Bs3PrintfV +BS3_CMN_DEF(size_t, Bs3PrintfV,(const char BS3_FAR *pszFormat, va_list BS3_FAR va)) +{ + BS3PRINTBUF Buf; + Buf.cchBuf = 0; + return Bs3StrFormatV(pszFormat, va, bs3PrintFmtOutput, &Buf); +} + + +#undef Bs3Printf +BS3_CMN_DEF(size_t, Bs3Printf,(const char BS3_FAR *pszFormat, ...)) +{ + size_t cchRet; + va_list va; + va_start(va, pszFormat); + cchRet = BS3_CMN_NM(Bs3PrintfV)(pszFormat, va); + va_end(va); + return cchRet; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxConvertToRingX.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxConvertToRingX.c new file mode 100644 index 00000000..f55c0c78 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxConvertToRingX.c @@ -0,0 +1,182 @@ +/* $Id: bs3-cmn-RegCtxConvertToRingX.c $ */ +/** @file + * BS3Kit - Bs3RegCtxConvertToRingX + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +/** + * Transforms a real mode segment into a protected mode selector. + * + * @returns Protected mode selector. + * @param uSeg The real mode segment. + * @param bRing The target ring. + */ +static uint16_t bs3RegCtxConvertRealSegToRingX(uint16_t uSeg, uint8_t bRing) +{ + uint16_t uSel; + if ( uSeg == 0 + || uSeg == BS3_SEL_R0_SS16) + uSel = BS3_SEL_R0_SS16 + ((uint16_t)bRing << BS3_SEL_RING_SHIFT); + else if ( uSeg == (BS3_ADDR_BS3TEXT16 >> 4) + || uSeg == BS3_SEL_R0_CS16) + uSel = BS3_SEL_R0_CS16 + ((uint16_t)bRing << BS3_SEL_RING_SHIFT); + else if ( uSeg == (BS3_ADDR_BS3DATA16 >> 4) + || uSeg == BS3_SEL_R0_DS16) + uSel = BS3_SEL_R0_DS16 + ((uint16_t)bRing << BS3_SEL_RING_SHIFT); + else if (uSeg == (BS3_ADDR_BS3SYSTEM16 >> 4)) + uSel = BS3_SEL_SYSTEM16; + else if (!(uSeg & 0xfff)) + uSel = (uSeg >> (12 - X86_SEL_SHIFT)) + BS3_SEL_TILED; + else if (uSeg == BS3_SEL_R0_DS16) + uSel = (uSeg >> (12 - X86_SEL_SHIFT)) + BS3_SEL_TILED; + else + { + Bs3Printf("uSeg=%#x\n", uSeg); + BS3_ASSERT(0); + return 0; + } + uSel |= bRing; + return uSel; +} + + +/** + * Transforms a protected mode selector to a different ring. + * + * @returns Adjusted protected mode selector. + * @param uSel The current selector value. + * @param bRing The target ring. + * @param iReg Register index. + */ +static uint16_t bs3RegCtxConvertProtSelToRingX(uint16_t uSel, uint8_t bRing, uint8_t iReg) +{ + if ( uSel > X86_SEL_RPL + && !(uSel & X86_SEL_LDT) ) + { + if (uSel >= BS3_SEL_R0_FIRST && uSel < BS3_SEL_R0_FIRST + (5 << BS3_SEL_RING_SHIFT)) + { + /* Convert BS3_SEL_R*_XXX to the target ring. */ + uSel &= BS3_SEL_RING_SUB_MASK; + uSel |= bRing; + uSel += BS3_SEL_R0_FIRST; + uSel += (uint16_t)bRing << BS3_SEL_RING_SHIFT; + } + else + { + /* Convert TEXT16 and DATA16 to BS3_SEL_R*_XXX. */ + uint16_t const uSelRaw = uSel & X86_SEL_MASK_OFF_RPL; + if (uSelRaw == BS3_SEL_TEXT16) + uSel = (BS3_SEL_R0_CS16 | bRing) + ((uint16_t)bRing << BS3_SEL_RING_SHIFT); + else if (uSelRaw == BS3_SEL_DATA16) + uSel = (BS3_SEL_R0_DS16 | bRing) + ((uint16_t)bRing << BS3_SEL_RING_SHIFT); + /* CS and SS must have CPL == DPL. So, convert to standard selectors as we're + usually here because Bs3SwitchToRing0 was called to get out of a test situation. */ + else if (iReg == X86_SREG_CS || iReg == X86_SREG_SS) + { + if ( Bs3Gdt[uSel >> X86_SEL_SHIFT].Gen.u1Long + && BS3_MODE_IS_64BIT_SYS(g_bBs3CurrentMode) ) + uSel = iReg == X86_SREG_CS ? BS3_SEL_R0_CS64 : BS3_SEL_R0_DS64; + else + { + uint32_t uFlat = Bs3SelFar32ToFlat32(0, uSel); + bool fDefBig = Bs3Gdt[uSel >> X86_SEL_SHIFT].Gen.u1DefBig; + if (!fDefBig && uFlat == BS3_ADDR_BS3TEXT16 && iReg == X86_SREG_CS) + uSel = BS3_SEL_R0_CS16; + else if (!fDefBig && uFlat == 0 && iReg == X86_SREG_SS) + uSel = BS3_SEL_R0_SS16; + else if (fDefBig && uFlat == 0) + uSel = iReg == X86_SREG_CS ? BS3_SEL_R0_CS32 : BS3_SEL_R0_SS32; + else + { + Bs3Printf("uSel=%#x iReg=%d\n", uSel, iReg); + BS3_ASSERT(0); + return uSel; + } + uSel |= bRing; + uSel += (uint16_t)bRing << BS3_SEL_RING_SHIFT; + } + } + /* Adjust the RPL on tiled and MMIO selectors. */ + else if ( uSelRaw == BS3_SEL_VMMDEV_MMIO16 + || uSelRaw >= BS3_SEL_TILED) + uSel = uSelRaw | bRing; + } + } + return uSel; +} + + +/** + * Transforms a register context to a different ring. + * + * @param pRegCtx The register context. + * @param bRing The target ring (0..3). + * + * @note Do _NOT_ call this for creating real mode or v8086 contexts, because + * it will always output a protected mode context! + */ +#undef Bs3RegCtxConvertToRingX +BS3_CMN_DEF(void, Bs3RegCtxConvertToRingX,(PBS3REGCTX pRegCtx, uint8_t bRing)) +{ + if ( (pRegCtx->rflags.u32 & X86_EFL_VM) + || pRegCtx->bMode == BS3_MODE_RM) + { + pRegCtx->rflags.u32 &= ~X86_EFL_VM; + pRegCtx->bMode &= ~BS3_MODE_CODE_MASK; + pRegCtx->bMode |= BS3_MODE_CODE_16; + pRegCtx->cs = bs3RegCtxConvertRealSegToRingX(pRegCtx->cs, bRing); + pRegCtx->ss = bs3RegCtxConvertRealSegToRingX(pRegCtx->ss, bRing); + pRegCtx->ds = bs3RegCtxConvertRealSegToRingX(pRegCtx->ds, bRing); + pRegCtx->es = bs3RegCtxConvertRealSegToRingX(pRegCtx->es, bRing); + pRegCtx->fs = bs3RegCtxConvertRealSegToRingX(pRegCtx->fs, bRing); + pRegCtx->gs = bs3RegCtxConvertRealSegToRingX(pRegCtx->gs, bRing); + } + else + { + pRegCtx->cs = bs3RegCtxConvertProtSelToRingX(pRegCtx->cs, bRing, X86_SREG_CS); + pRegCtx->ss = bs3RegCtxConvertProtSelToRingX(pRegCtx->ss, bRing, X86_SREG_SS); + pRegCtx->ds = bs3RegCtxConvertProtSelToRingX(pRegCtx->ds, bRing, X86_SREG_DS); + pRegCtx->es = bs3RegCtxConvertProtSelToRingX(pRegCtx->es, bRing, X86_SREG_ES); + pRegCtx->fs = bs3RegCtxConvertProtSelToRingX(pRegCtx->fs, bRing, X86_SREG_FS); + pRegCtx->gs = bs3RegCtxConvertProtSelToRingX(pRegCtx->gs, bRing, X86_SREG_GS); + } + pRegCtx->bCpl = bRing; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxConvertV86ToRm.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxConvertV86ToRm.c new file mode 100644 index 00000000..913ee555 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxConvertV86ToRm.c @@ -0,0 +1,55 @@ +/* $Id: bs3-cmn-RegCtxConvertV86ToRm.c $ */ +/** @file + * BS3Kit - Bs3RegCtxConvertV86ToRm + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3RegCtxConvertV86ToRm +BS3_CMN_DEF(void, Bs3RegCtxConvertV86ToRm,(PBS3REGCTX pRegCtx)) +{ + BS3_ASSERT(BS3_MODE_IS_V86(pRegCtx->bMode)); + + pRegCtx->cr0.u32 &= ~(X86_CR0_PE | X86_CR0_PG); + pRegCtx->rflags.u32 &= ~X86_EFL_VM; + pRegCtx->fbFlags |= BS3REG_CTX_F_NO_TR_LDTR | BS3REG_CTX_F_NO_AMD64; + pRegCtx->bCpl = 0; + pRegCtx->bMode = BS3_MODE_RM; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxGetRspSsAsCurPtr.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxGetRspSsAsCurPtr.c new file mode 100644 index 00000000..5f36e2b1 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxGetRspSsAsCurPtr.c @@ -0,0 +1,71 @@ +/* $Id: bs3-cmn-RegCtxGetRspSsAsCurPtr.c $ */ +/** @file + * BS3Kit - Bs3RegCtxGetRspSsAsCurPtr + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3RegCtxGetRspSsAsCurPtr +BS3_CMN_DEF(void BS3_FAR *, Bs3RegCtxGetRspSsAsCurPtr,(PBS3REGCTX pRegCtx)) +{ + uint64_t uFlat; + if (BS3_MODE_IS_RM_OR_V86(pRegCtx->bMode)) + { +#if ARCH_BITS == 16 + if (BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode)) + return BS3_FP_MAKE(pRegCtx->ss, pRegCtx->rsp.u16); +#endif + uFlat = ((uint32_t)pRegCtx->ss << 4) + pRegCtx->rsp.u16; + } + else if (!BS3_MODE_IS_64BIT_CODE(pRegCtx->bMode)) + uFlat = Bs3SelFar32ToFlat32(pRegCtx->rsp.u32, pRegCtx->ss); + else + uFlat = pRegCtx->rsp.u64; + +#if ARCH_BITS == 16 + if (uFlat >= (BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode) ? _1M : BS3_SEL_TILED_AREA_SIZE)) + return NULL; + return BS3_FP_MAKE(Bs3Sel16HighFlatPtrToSelector((uint32_t)uFlat >> 16), (uint16_t)uFlat); +#else + /* Typically no need to check limit in 32-bit mode, because 64-bit mode + just repeats the first 4GB for the rest of the address space. */ + return (void *)(uintptr_t)uFlat; +#endif +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxPrint.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxPrint.c new file mode 100644 index 00000000..0e5e73ba --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxPrint.c @@ -0,0 +1,77 @@ +/* $Id: bs3-cmn-RegCtxPrint.c $ */ +/** @file + * BS3Kit - Bs3RegCtxPrint + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3RegCtxPrint +BS3_CMN_DEF(void, Bs3RegCtxPrint,(PCBS3REGCTX pRegCtx)) +{ + if (!BS3_MODE_IS_64BIT_CODE(pRegCtx->bMode)) + { + Bs3TestPrintf("eax=%08RX32 ebx=%08RX32 ecx=%08RX32 edx=%08RX32 esi=%08RX32 edi=%08RX32\n", + pRegCtx->rax.u32, pRegCtx->rbx.u32, pRegCtx->rcx.u32, pRegCtx->rdx.u32, pRegCtx->rsi.u32, pRegCtx->rdi.u32); + Bs3TestPrintf("eip=%08RX32 esp=%08RX32 ebp=%08RX32 efl=%08RX32 cr0=%08RX32 cr2=%08RX32\n", + pRegCtx->rip.u32, pRegCtx->rsp.u32, pRegCtx->rbp.u32, pRegCtx->rflags.u32, + pRegCtx->cr0.u32, pRegCtx->cr2.u32); + Bs3TestPrintf("cs=%04RX16 ds=%04RX16 es=%04RX16 fs=%04RX16 gs=%04RX16 ss=%04RX16 cr3=%08RX32 cr4=%08RX32\n", + pRegCtx->cs, pRegCtx->ds, pRegCtx->es, pRegCtx->fs, pRegCtx->gs, pRegCtx->ss, + pRegCtx->cr3.u32, pRegCtx->cr4.u32); + } + else + { + Bs3TestPrintf("rax=%016RX64 rbx=%016RX64 rcx=%016RX64 rdx=%016RX64\n", + pRegCtx->rax.u64, pRegCtx->rbx.u64, pRegCtx->rcx.u64, pRegCtx->rdx.u64); + Bs3TestPrintf("rsi=%016RX64 rdi=%016RX64 r8 =%016RX64 r9 =%016RX64\n", + pRegCtx->rsi.u64, pRegCtx->rdi.u64, pRegCtx->r8.u64, pRegCtx->r9.u64); + Bs3TestPrintf("r10=%016RX64 r11=%016RX64 r12=%016RX64 r13=%016RX64\n", + pRegCtx->r10.u64, pRegCtx->r11.u64, pRegCtx->r12.u64, pRegCtx->r13.u64); + Bs3TestPrintf("r14=%016RX64 r15=%016RX64 cr0=%08RX64 cr4=%08RX64 cr3=%08RX64\n", + pRegCtx->r14.u64, pRegCtx->r15.u64, pRegCtx->cr0.u64, pRegCtx->cr4.u64, pRegCtx->cr3.u64); + Bs3TestPrintf("rip=%016RX64 rsp=%016RX64 rbp=%016RX64 rfl=%08RX64\n", + pRegCtx->rip.u64, pRegCtx->rsp.u64, pRegCtx->rbp.u64, pRegCtx->rflags.u32); + Bs3TestPrintf("cs=%04RX16 ds=%04RX16 es=%04RX16 fs=%04RX16 gs=%04RX16 ss=%04RX16 cr2=%016RX64\n", + pRegCtx->cs, pRegCtx->ds, pRegCtx->es, pRegCtx->fs, pRegCtx->gs, pRegCtx->ss, + pRegCtx->cr3.u64, pRegCtx->cr2.u64); + } + Bs3TestPrintf("tr=%04RX16 ldtr=%04RX16 cpl=%d mode=%#x fbFlags=%#x\n", + pRegCtx->tr, pRegCtx->ldtr, pRegCtx->bCpl, pRegCtx->bMode, pRegCtx->fbFlags); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxRestore.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxRestore.asm new file mode 100644 index 00000000..37d3a526 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxRestore.asm @@ -0,0 +1,608 @@ +; $Id: bs3-cmn-RegCtxRestore.asm $ +;; @file +; BS3Kit - Bs3RegCtxRestore. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_SYSTEM16 Bs3Gdt +BS3_EXTERN_DATA16 g_bBs3CurrentMode +BS3_EXTERN_DATA16 g_fBs3TrapNoV86Assist +%if TMPL_BITS != 64 +BS3_EXTERN_DATA16 g_uBs3CpuDetected +%endif +TMPL_BEGIN_TEXT +BS3_EXTERN_CMN Bs3Syscall +BS3_EXTERN_CMN Bs3Panic +TMPL_BEGIN_TEXT + + +;; +; Restores the given register context. +; +; @param pRegCtx +; @param fFlags +; @uses All registers and may trash stack immediately before the resume point. +; +; @note Only respects the BS3_MODE_CODE_MASK part of pRegCtx->bMode. +; +%if TMPL_BITS == 16 +BS3_PROC_BEGIN_CMN Bs3RegCtxRestore_aborts, BS3_PBC_FAR ; special entry point for when watcom applies __aborts +BS3_PROC_BEGIN_CMN Bs3RegCtxRestore_aborts, BS3_PBC_NEAR ; special entry point for when watcom applies __aborts + CPU 8086 + xor xAX, xAX + push xAX ; fake return address. + push xAX + jmp _Bs3RegCtxRestore_f16 +%elif TMPL_BITS == 32 +BS3_PROC_BEGIN_CMN Bs3RegCtxRestore_aborts, BS3_PBC_NEAR ; special entry point for when watcom applies __aborts + push 0feedfaceh ; fake return address. +%endif +BS3_PROC_BEGIN_CMN Bs3RegCtxRestore, BS3_PBC_HYBRID + BS3_CALL_CONV_PROLOG 2 + push xBP + mov xBP, xSP + + ; + ; If we're not in ring-0, ask the kernel to restore it for us (quicker + ; and less problematic if we're in a funny context right now with weird + ; CS or SS values). + ; +%if TMPL_BITS == 16 + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .in_ring0 + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .do_syscall_restore_ctx +%endif + mov ax, ss + test al, 3 + jz .in_ring0 + +.do_syscall_restore_ctx: +%if TMPL_BITS != 16 +.do_syscall_restore_ctx_restore_ds: + mov cx, ds + mov xSI, [xBP + xCB*2] + movzx edx, word [xBP + xCB*3] + mov eax, BS3_SYSCALL_RESTORE_CTX +%else + mov si, [bp + xCB + cbCurRetAddr] + mov cx, [bp + xCB + cbCurRetAddr + 2] + mov dx, [bp + xCB + cbCurRetAddr + sCB] + mov ax, BS3_SYSCALL_RESTORE_CTX +%endif + call Bs3Syscall + call Bs3Panic + +%if TMPL_BITS == 16 +.do_syscall_restore_ctx_restore_ds: + push es + pop ds + jmp .do_syscall_restore_ctx +%endif + + ; + ; Prologue. Loads ES with BS3KIT_GRPNM_DATA16/FLAT (for g_bBs3CurrentMode + ; and g_uBs3CpuDetected), DS:xBX with pRegCtx and fFlags into xCX. + ; +.in_ring0: +%if TMPL_BITS == 16 + mov ax, BS3_SEL_DATA16 + mov es, ax + lds bx, [bp + xCB + cbCurRetAddr] + mov cx, [bp + xCB + cbCurRetAddr + sCB] +%elif TMPL_BITS == 32 + mov ax, BS3_SEL_R0_DS32 + mov ds, ax + mov xBX, [xBP + xCB*2] + movzx xCX, word [xBP + xCB*3] +%else + mov ax, BS3_SEL_R0_DS64 + mov ds, ax + mov xBX, [xBP + xCB*2] + movzx xCX, word [xBP + xCB*3] +%endif + + +%if TMPL_BITS != 64 + ; Restoring a 64-bit context is best done from 64-bit code. + mov al, [xBX + BS3REGCTX.bMode] + test al, BS3_MODE_CODE_64 + jnz .do_syscall_restore_ctx_restore_ds +%endif + + ; The remainder must be done with interrupts disabled. + cli + + ; + ; Update g_bs3CurrentMode. + ; +%if TMPL_BITS == 64 + mov al, [xBX + BS3REGCTX.bMode] +%endif + and al, BS3_MODE_CODE_MASK + mov ah, [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_bBs3CurrentMode)] + and ah, ~BS3_MODE_CODE_MASK + or al, ah + mov [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_bBs3CurrentMode)], al + + ; + ; Set g_fBs3TrapNoV86Assist if BS3REGCTXRESTORE_F_NO_V86_ASSIST specified. + ; + test cl, BS3REGCTXRESTORE_F_NO_V86_ASSIST + jz .no_f_no_v86_assist + mov byte [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_fBs3TrapNoV86Assist)], 1 +.no_f_no_v86_assist: + +%if TMPL_BITS == 16 + ; + ; Check what the CPU can do. + ; + cmp byte [es:BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80386 + jae .restore_full + + ; Do the 80286 specifics first. + cmp byte [es:BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80286 + jb .restore_16_bit_ancient + CPU 286 + + lmsw [bx + BS3REGCTX.cr0] + cmp byte [es:BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .restore_16_bit_ancient + lldt [bx + BS3REGCTX.ldtr] + + ; TR - complicated because we need to clear the busy bit. ASSUMES GDT. + str ax + cmp ax, [bx + BS3REGCTX.tr] + je .skip_tr_286 + + mov di, word [xBX + BS3REGCTX.tr] + or di, di ; check for null. + jz .load_tr_286 + + push ds + push BS3_SEL_SYSTEM16 + pop ds + add di, Bs3Gdt wrt BS3SYSTEM16 + add di, X86DESCGENERIC_BIT_OFF_TYPE / 8 + and byte [di], ~(X86_SEL_TYPE_SYS_TSS_BUSY_MASK << (X86DESCGENERIC_BIT_OFF_TYPE % 8)) + pop ds + +.load_tr_286: + ltr [bx + BS3REGCTX.tr] +.skip_tr_286: + +.restore_16_bit_ancient: + CPU 8086 + ; Some general registers. + mov cx, [bx + BS3REGCTX.rcx] + mov dx, [bx + BS3REGCTX.rdx] + + ; Do the return frame and final registers (keep short as we're not quite + ; NMI safe here if pRegCtx is on the stack). + cmp byte [es:BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + mov di, [bx + BS3REGCTX.rsp] + je .restore_16_bit_same_privilege + cmp byte [bx + BS3REGCTX.bCpl], 0 + je .restore_16_bit_same_privilege + + mov ax, [bx + BS3REGCTX.ss] + push ax + mov ax, [bx + BS3REGCTX.rsp] + push ax + mov ax, [bx + BS3REGCTX.rflags] + push ax + mov ax, [bx + BS3REGCTX.cs] + push ax + mov ax, [bx + BS3REGCTX.rip] + push ax + mov ax, [bx + BS3REGCTX.ds] + push ax + + mov si, [bx + BS3REGCTX.rsi] + mov di, [bx + BS3REGCTX.rdi] + mov es, [bx + BS3REGCTX.es] + mov ax, [bx + BS3REGCTX.rax] + mov bp, [bx + BS3REGCTX.rbp] ; restore late for better stacks. + mov bx, [bx + BS3REGCTX.rbx] + + pop ds + iret + +.restore_16_bit_same_privilege: + sub di, 2*5 ; iret frame + pop ds + mov si, di + mov es, [bx + BS3REGCTX.ss] ; ES is target stack segment. + cld + + mov ax, [bx + BS3REGCTX.ds] + stosw + mov ax, [bx + BS3REGCTX.rbp] ; Restore esp as late as possible for better stacks. + stosw + mov ax, [bx + BS3REGCTX.rip] + stosw + mov ax, [bx + BS3REGCTX.cs] + stosw + mov ax, [bx + BS3REGCTX.rflags] + stosw + + mov di, [bx + BS3REGCTX.rdi] + mov es, [bx + BS3REGCTX.es] + mov ax, [bx + BS3REGCTX.rax] + mov ss, [bx + BS3REGCTX.ss] + mov sp, si + mov si, [bx + BS3REGCTX.rsi] + mov bx, [bx + BS3REGCTX.rbx] + + pop ds + pop bp + iret + + CPU 386 +%endif + +.restore_full: + ; + ; 80386 or later. + ; For 32-bit and 16-bit versions, we always use 32-bit iret. + ; + + ; Restore control registers if they've changed. + test cl, BS3REGCTXRESTORE_F_SKIP_CRX + jnz .skip_control_regs + test byte [xBX + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR0_IS_MSW | BS3REG_CTX_F_NO_CR2_CR3 + jnz .skip_control_regs + + test byte [xBX + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR4 ; (old 486s and 386s didn't have CR4) + jnz .skip_cr4 +%if TMPL_BITS != 64 + test word [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_F_CPUID + jz .skip_cr4 +%endif + mov sAX, [xBX + BS3REGCTX.cr4] + mov sDX, cr4 + cmp sAX, sDX + je .skip_cr4 + mov cr4, sAX +.skip_cr4: + + mov sAX, [xBX + BS3REGCTX.cr0] + mov sDX, cr0 + cmp sAX, sDX + je .skip_cr0 + mov cr0, sAX +.skip_cr0: + + mov sAX, [xBX + BS3REGCTX.cr3] + mov sDX, cr3 + cmp sAX, sDX + je .skip_cr3 + mov cr3, sAX +.skip_cr3: + + mov sAX, [xBX + BS3REGCTX.cr2] + mov sDX, cr2 + cmp sAX, sDX + je .skip_cr2 + mov cr2, sAX +.skip_cr2: + + ; + ; Restore + ; +%if TMPL_BITS != 64 + ; We cannot restore ldtr and tr if we're in real-mode. + cmp byte [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .skip_control_regs +%endif + test byte [xBX + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_TR_LDTR + jnz .skip_control_regs + + ; LDTR + sldt ax + cmp ax, [xBX + BS3REGCTX.ldtr] + je .skip_ldtr + lldt [xBX + BS3REGCTX.ldtr] +.skip_ldtr: + + ; TR - complicated because we need to clear the busy bit. ASSUMES GDT. + str ax + cmp ax, [xBX + BS3REGCTX.tr] + je .skip_tr + + movzx edi, word [xBX + BS3REGCTX.tr] + or edi, edi ; check for null. + jz .load_tr + +%if TMPL_BITS == 16 + push ds + push BS3_SEL_SYSTEM16 + pop ds + add xDI, Bs3Gdt wrt BS3SYSTEM16 +%else + add xDI, Bs3Gdt wrt FLAT +%endif + add xDI, X86DESCGENERIC_BIT_OFF_TYPE / 8 + and byte [xDI], ~(X86_SEL_TYPE_SYS_TSS_BUSY_MASK << (X86DESCGENERIC_BIT_OFF_TYPE % 8)) +%if TMPL_BITS == 16 + pop ds +%endif +.load_tr: + ltr [xBX + BS3REGCTX.tr] +.skip_tr: + +.skip_control_regs: + + +%if TMPL_BITS == 64 + ; + ; 64-bit returns are simple because ss:rsp are always restored. + ; + ; A small complication here when returning to a 16-bit stack (only + ; applicable to 16-bit and 32-bit code), iret doesn't touch the high + ; ESP bits and we can easily later end up with trap handlers + ; accessing memory never intended as stack. + ; + mov rcx, qword [xBX + BS3REGCTX.rsp] ; (also 1st param for conv call below) + cmp rcx, 0ffffh + ja .iretq_maybe_annoying_16bit_stack + cmp rsp, 0ffffh + ja .iretq_maybe_annoying_16bit_stack +.iretq_ok: + + movzx eax, word [xBX + BS3REGCTX.ss] + push rax + push qword [xBX + BS3REGCTX.rsp] + push qword [xBX + BS3REGCTX.rflags] + movzx eax, word [xBX + BS3REGCTX.cs] + push rax + push qword [xBX + BS3REGCTX.rip] + +.iretq_restore_regs_and_iret: + mov es, [xBX + BS3REGCTX.es] + mov fs, [xBX + BS3REGCTX.fs] + mov gs, [xBX + BS3REGCTX.gs] + mov rax, [xBX + BS3REGCTX.rax] + mov rdx, [xBX + BS3REGCTX.rdx] + mov rcx, [xBX + BS3REGCTX.rcx] + mov rsi, [xBX + BS3REGCTX.rsi] + mov rdi, [xBX + BS3REGCTX.rdi] + mov r8, [xBX + BS3REGCTX.r8] + mov r9, [xBX + BS3REGCTX.r9] + mov r10, [xBX + BS3REGCTX.r10] + mov r11, [xBX + BS3REGCTX.r11] + mov r12, [xBX + BS3REGCTX.r12] + mov r13, [xBX + BS3REGCTX.r13] + mov r14, [xBX + BS3REGCTX.r14] + mov r15, [xBX + BS3REGCTX.r15] + mov rbp, [xBX + BS3REGCTX.rbp] ; restore late for better stacks. + mov ds, [xBX + BS3REGCTX.ds] + mov rbx, [xBX + BS3REGCTX.rbx] + iretq + +.iretq_maybe_annoying_16bit_stack: + movzx edx, word [xBX + BS3REGCTX.ss] ; (also 2nd param for conv call below) + lar eax, dx + jnz .iretq_ok + test eax, X86LAR_F_D | X86LAR_F_L + jnz .iretq_ok ; Returning to a big of long SS needs not extra work. + + lar eax, word [xBX + BS3REGCTX.cs] + jnz .iretq_ok + test eax, X86LAR_F_L + jnz .iretq_ok ; It doesn't matter when returning to 64-bit code. + + ; Convert ss:sp to a flat address. + BS3_EXTERN_CMN Bs3SelFar32ToFlat32NoClobber + call Bs3SelFar32ToFlat32NoClobber + mov rdi, rax + + ; 2nd return frame (32-bit, same CPL). + mov eax, [xBX + BS3REGCTX.rflags] + mov [rdi - 4], eax + movzx eax, word [xBX + BS3REGCTX.cs] + mov [rdi - 8], eax + mov eax, [xBX + BS3REGCTX.rip] + mov [rdi - 12], eax + mov ecx, [xBX + BS3REGCTX.rsp] + sub cx, 12 + mov [rdi - 16], ecx + + ; 1st return frame. + movzx eax, word [xBX + BS3REGCTX.ss] + push rax ; new 16-bit SS + sub cx, 4 + push rcx ; new esp + mov rax, [xBX + BS3REGCTX.rflags] + and rax, ~(X86_EFL_NT | X86_EFL_TF) + push rax ; rflags + AssertCompile(BS3_SEL_RING_SHIFT == 8) + mov eax, BS3_SEL_R0_CS32 + add ah, [xBX + BS3REGCTX.bCpl] + or al, [xBX + BS3REGCTX.bCpl] + push rax ; 32-bit CS + push .iretq_pop_real_esp_and_iret_again wrt FLAT + jmp .iretq_restore_regs_and_iret + + BS3_SET_BITS 32 +.iretq_pop_real_esp_and_iret_again: + pop esp + iretd + BS3_SET_BITS 64 + +%else + ; + ; 32-bit/16-bit is more complicated as we have three different iret frames. + ; + mov al, [BS3_ONLY_16BIT(es:) BS3_DATA16_WRT(g_bBs3CurrentMode)] + cmp al, BS3_MODE_RM + je .iretd_same_cpl_rm + + test dword [xBX + BS3REGCTX.rflags], X86_EFL_VM + jnz .restore_v8086 + + cmp byte [xBX + BS3REGCTX.bCpl], 0 + je .iretd_same_cpl + + ; + ; IRETD to different CPL. Frame includes ss:esp. + ; +.iretd_different_cpl: + or eax, 0ffffffffh ; poison unused parts of segment pushes + mov ax, [xBX + BS3REGCTX.ss] + push eax + push dword [xBX + BS3REGCTX.rsp] + push dword [xBX + BS3REGCTX.rflags] + mov ax, [xBX + BS3REGCTX.cs] + push eax + push dword [xBX + BS3REGCTX.rip] + push dword [xBX + BS3REGCTX.rbp] ; Restore esp as late as possible for better stacks. + mov ax, [xBX + BS3REGCTX.ds] + push xAX + + mov es, [xBX + BS3REGCTX.es] + mov fs, [xBX + BS3REGCTX.fs] + mov gs, [xBX + BS3REGCTX.gs] + mov eax, [xBX + BS3REGCTX.rax] + mov edx, [xBX + BS3REGCTX.rdx] + mov ecx, [xBX + BS3REGCTX.rcx] + mov esi, [xBX + BS3REGCTX.rsi] + %if TMPL_BITS == 16 ; if SS is 16-bit, we will not be able to restore the high word. +;; @todo 16-bit stack will also mess us up in 32-bit code, so this needs fixing (see 64-bit above). + mov edi, [xBX + BS3REGCTX.rsp] + mov di, sp + mov esp, edi + %endif + mov edi, [xBX + BS3REGCTX.rdi] + mov ebx, [xBX + BS3REGCTX.rbx] + + pop ds + pop ebp + iretd + + ; + ; IRETD to same CPL (includes real mode). + ; +.iretd_same_cpl_rm: + ; Use STOSD/ES:EDI to create the frame. + mov es, [xBX + BS3REGCTX.ss] + mov esi, [xBX + BS3REGCTX.rsp] + sub esi, 5*4 + movzx edi, si + jmp .es_edi_is_pointing_to_return_frame_location + +.iretd_same_cpl: + ; Use STOSD/ES:EDI to create the frame. + mov es, [xBX + BS3REGCTX.ss] + mov edi, [xBX + BS3REGCTX.rsp] + sub edi, 5*4 + + ; Which part of the stack pointer is actually used depends on the SS.D/B bit. + lar eax, [xBX + BS3REGCTX.ss] + jnz .using_32_bit_stack_pointer + test eax, X86LAR_F_D + jnz .using_32_bit_stack_pointer +.using_16_bit_stack_pointer: + mov esi, edi ; save rsp for later. + movzx edi, di + jmp .es_edi_is_pointing_to_return_frame_location +.using_32_bit_stack_pointer: + mov esi, edi +.es_edi_is_pointing_to_return_frame_location: + cld + mov ax, [xBX + BS3REGCTX.ds] + o32 stosd + mov eax, [xBX + BS3REGCTX.rbp] ; Restore esp as late as possible for better stacks. + o32 stosd + mov eax, [xBX + BS3REGCTX.rip] + o32 stosd + mov ax, [xBX + BS3REGCTX.cs] + o32 stosd + mov eax, [xBX + BS3REGCTX.rflags] + o32 stosd + + mov es, [xBX + BS3REGCTX.es] + mov fs, [xBX + BS3REGCTX.fs] + mov gs, [xBX + BS3REGCTX.gs] + mov eax, [xBX + BS3REGCTX.rax] + mov edx, [xBX + BS3REGCTX.rdx] + mov ecx, [xBX + BS3REGCTX.rcx] + mov edi, [xBX + BS3REGCTX.rdi] + mov ebp, [xBX + BS3REGCTX.rbp] ; restore late for better stacks. + + mov ss, [xBX + BS3REGCTX.ss] + mov esp, esi + mov esi, [xBX + BS3REGCTX.rsi] + mov ebx, [xBX + BS3REGCTX.rbx] + + o32 pop ds + pop ebp + iretd + + ; + ; IRETD to v8086 mode. Frame includes ss:esp and the 4 data segment registers. + ; +.restore_v8086: + ; Create the return frame. + or eax, 0ffffffffh ; poison unused parts of segment pushes + mov eax, [xBX + BS3REGCTX.gs] + push eax + mov eax, [xBX + BS3REGCTX.fs] + push eax + mov eax, [xBX + BS3REGCTX.ds] + push eax + mov eax, [xBX + BS3REGCTX.es] + push eax + mov eax, [xBX + BS3REGCTX.ss] + push eax + push dword [xBX + BS3REGCTX.rsp] + push dword [xBX + BS3REGCTX.rflags] + mov ax, [xBX + BS3REGCTX.cs] + push eax + push dword [xBX + BS3REGCTX.rip] + + ; Load registers. + mov eax, [xBX + BS3REGCTX.rax] + mov edx, [xBX + BS3REGCTX.rdx] + mov ecx, [xBX + BS3REGCTX.rcx] + mov esi, [xBX + BS3REGCTX.rsi] + mov edi, [xBX + BS3REGCTX.rdi] + mov ebp, [xBX + BS3REGCTX.rbp] ; restore late for better stacks. + mov ebx, [xBX + BS3REGCTX.rbx] + + iretd +%endif +BS3_PROC_END_CMN Bs3RegCtxRestore + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSave.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSave.asm new file mode 100644 index 00000000..4888c8e7 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSave.asm @@ -0,0 +1,271 @@ +; $Id: bs3-cmn-RegCtxSave.asm $ +;; @file +; BS3Kit - Bs3RegCtxSave. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_SYSTEM16 Bs3Gdt +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%if TMPL_BITS != 64 +BS3_EXTERN_DATA16 g_uBs3CpuDetected +%endif +TMPL_BEGIN_TEXT + + + +;; +; Saves the current register context. +; +; @param pRegCtx +; @uses None. +; +BS3_PROC_BEGIN_CMN Bs3RegCtxSave, BS3_PBC_HYBRID_SAFE +TONLY16 CPU 8086 + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + xPUSHF ; xBP - xCB*1: save the incoming flags exactly. + push xAX ; xBP - xCB*2: save incoming xAX + push xCX ; xBP - xCB*3: save incoming xCX + push xDI ; xBP - xCB*4: save incoming xDI +BONLY16 push es ; xBP - xCB*5 +BONLY16 push ds ; xBP - xCB*6 + + ; + ; Clear the whole structure first. + ; + xor xAX, xAX + cld + AssertCompileSizeAlignment(BS3REGCTX, 4) +%if TMPL_BITS == 16 + les xDI, [xBP + xCB + cbCurRetAddr] + mov xCX, BS3REGCTX_size / 2 + rep stosw +%else + mov xDI, [xBP + xCB + cbCurRetAddr] + mov xCX, BS3REGCTX_size / 4 + rep stosd +%endif + mov xDI, [xBP + xCB + cbCurRetAddr] + + ; + ; Save the current mode. + ; + mov cl, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + mov [BS3_ONLY_16BIT(es:) xDI + BS3REGCTX.bMode], cl +%if TMPL_BITS == 16 + + ; + ; In 16-bit mode we could be running on really ancient CPUs, so check + ; mode and detected CPU and proceed with care. + ; + cmp cl, BS3_MODE_PP16 + jae .save_full + + mov cl, [BS3_DATA16_WRT(g_uBs3CpuDetected)] + cmp cl, BS3CPU_80386 + jae .save_full + + ; load ES into DS so we can save some segment prefix bytes. + push es + pop ds + + ; 16-bit GPRs not on the stack. + mov [xDI + BS3REGCTX.rdx], dx + mov [xDI + BS3REGCTX.rbx], bx + mov [xDI + BS3REGCTX.rsi], si + + ; Join the common code. + cmp cl, BS3CPU_80286 + jb .common_ancient + CPU 286 + smsw [xDI + BS3REGCTX.cr0] + + mov cl, [xDI + BS3REGCTX.bMode] ; assumed by jump destination + jmp .common_80286 + + CPU 386 +%endif + + +.save_full: + ; + ; 80386 or later. + ; +%if TMPL_BITS != 64 + ; Check for CR4 here while we've got a working DS in all contexts. + test byte [1 + BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_CPUID >> 8) + jnz .save_full_have_cr4 + or byte [BS3_ONLY_16BIT(es:) xDI + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR4 +.save_full_have_cr4: +%endif +%if TMPL_BITS == 16 + ; Load es into ds so we can save ourselves some segment prefix bytes. + push es + pop ds +%endif + + ; GPRs first. + mov [xDI + BS3REGCTX.rdx], sDX + mov [xDI + BS3REGCTX.rbx], sBX + mov [xDI + BS3REGCTX.rsi], sSI +%if TMPL_BITS == 64 + mov [xDI + BS3REGCTX.r8], r8 + mov [xDI + BS3REGCTX.r9], r9 + mov [xDI + BS3REGCTX.r10], r10 + mov [xDI + BS3REGCTX.r11], r11 + mov [xDI + BS3REGCTX.r12], r12 + mov [xDI + BS3REGCTX.r13], r13 + mov [xDI + BS3REGCTX.r14], r14 + mov [xDI + BS3REGCTX.r15], r15 +%else + or byte [xDI + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_AMD64 +%endif +%if TMPL_BITS == 16 ; Save high bits. + mov [xDI + BS3REGCTX.rax], eax + mov [xDI + BS3REGCTX.rcx], ecx + mov [xDI + BS3REGCTX.rdi], edi + mov [xDI + BS3REGCTX.rbp], ebp + mov [xDI + BS3REGCTX.rsp], esp + pushfd + pop dword [xDI + BS3REGCTX.rflags] +%endif +%if TMPL_BITS != 64 + ; The VM flag is never on the stack, so derive it from the bMode we saved above. + test byte [xDI + BS3REGCTX.bMode], BS3_MODE_CODE_V86 + jz .not_v8086 + or byte [xDI + BS3REGCTX.rflags + 2], X86_EFL_VM >> 16 + mov byte [xDI + BS3REGCTX.bCpl], 3 +.not_v8086: +%endif + + ; 386 segment registers. + mov [xDI + BS3REGCTX.fs], fs + mov [xDI + BS3REGCTX.gs], gs + +%if TMPL_BITS == 16 ; v8086 and real mode woes. + mov cl, [xDI + BS3REGCTX.bMode] + cmp cl, BS3_MODE_RM + je .common_full_control_regs + test cl, BS3_MODE_CODE_V86 + jnz .common_full_no_control_regs +%endif + mov ax, ss + test al, 3 + jnz .common_full_no_control_regs + + ; Control registers (ring-0 and real-mode only). +.common_full_control_regs: + mov sAX, cr0 + mov [xDI + BS3REGCTX.cr0], sAX + mov sAX, cr2 + mov [xDI + BS3REGCTX.cr2], sAX + mov sAX, cr3 + mov [xDI + BS3REGCTX.cr3], sAX +%if TMPL_BITS != 64 + test byte [xDI + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR4 + jnz .common_80286 +%endif + mov sAX, cr4 + mov [xDI + BS3REGCTX.cr4], sAX + jmp .common_80286 + +.common_full_no_control_regs: + or byte [xDI + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR0_IS_MSW | BS3REG_CTX_F_NO_CR2_CR3 | BS3REG_CTX_F_NO_CR4 + smsw [xDI + BS3REGCTX.cr0] + + ; 80286 control registers. +.common_80286: +TONLY16 CPU 286 +%if TMPL_BITS != 64 + cmp cl, BS3_MODE_RM + je .no_str_sldt + test cl, BS3_MODE_CODE_V86 + jnz .no_str_sldt +%endif + str [xDI + BS3REGCTX.tr] + sldt [xDI + BS3REGCTX.ldtr] + jmp .common_ancient + +.no_str_sldt: + or byte [xDI + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_TR_LDTR + + ; Common stuff - stuff on the stack, 286 segment registers. +.common_ancient: +TONLY16 CPU 8086 + mov xAX, [xBP - xCB*1] + mov [xDI + BS3REGCTX.rflags], xAX + mov xAX, [xBP - xCB*2] + mov [xDI + BS3REGCTX.rax], xAX + mov xAX, [xBP - xCB*3] + mov [xDI + BS3REGCTX.rcx], xAX + mov xAX, [xBP - xCB*4] + mov [xDI + BS3REGCTX.rdi], xAX + mov xAX, [xBP] + mov [xDI + BS3REGCTX.rbp], xAX + mov xAX, [xBP + xCB] + mov [xDI + BS3REGCTX.rip], xAX + lea xAX, [xBP + xCB + cbCurRetAddr] + mov [xDI + BS3REGCTX.rsp], xAX + +%if TMPL_BITS == 16 + mov ax, [xBP + xCB + 2] + mov [xDI + BS3REGCTX.cs], ax + mov ax, [xBP - xCB*6] + mov [xDI + BS3REGCTX.ds], ax + mov ax, [xBP - xCB*5] + mov [xDI + BS3REGCTX.es], ax +%else + mov [xDI + BS3REGCTX.cs], cs + mov [xDI + BS3REGCTX.ds], ds + mov [xDI + BS3REGCTX.es], es +%endif + mov [xDI + BS3REGCTX.ss], ss + + ; + ; Return. + ; +.return: +BONLY16 pop ds +BONLY16 pop es + pop xDI + pop xCX + pop xAX + xPOPF + pop xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegCtxSave + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSaveEx.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSaveEx.asm new file mode 100644 index 00000000..94203fe3 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSaveEx.asm @@ -0,0 +1,460 @@ +; $Id: bs3-cmn-RegCtxSaveEx.asm $ +;; @file +; BS3Kit - Bs3RegCtxSaveEx. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%if ARCH_BITS != 64 +BS3_EXTERN_DATA16 g_uBs3CpuDetected +%endif + +TMPL_BEGIN_TEXT +BS3_EXTERN_CMN Bs3Panic +BS3_EXTERN_CMN Bs3RegCtxSave +BS3_EXTERN_CMN Bs3SwitchTo16Bit +%if TMPL_BITS != 64 +BS3_EXTERN_CMN Bs3SwitchTo16BitV86 +%endif +%if TMPL_BITS != 32 +BS3_EXTERN_CMN Bs3SwitchTo32Bit +%endif +%if TMPL_BITS != 64 +BS3_EXTERN_CMN Bs3SwitchTo64Bit +%endif +%if TMPL_BITS == 16 +BS3_EXTERN_CMN Bs3SelRealModeDataToProtFar16 +BS3_EXTERN_CMN Bs3SelProtFar16DataToRealMode +BS3_EXTERN_CMN Bs3SelRealModeDataToFlat +BS3_EXTERN_CMN Bs3SelProtFar16DataToFlat +%else +BS3_EXTERN_CMN Bs3SelFlatDataToProtFar16 +%endif +%if TMPL_BITS == 32 +BS3_EXTERN_CMN Bs3SelFlatDataToRealMode +%endif + +BS3_BEGIN_TEXT16 +%if TMPL_BITS != 16 +extern _Bs3RegCtxSave_c16 +extern _Bs3SwitchTo%[TMPL_BITS]Bit_c16 +%endif + +BS3_BEGIN_TEXT32 +%if TMPL_BITS != 32 +extern _Bs3RegCtxSave_c32 +extern _Bs3SwitchTo%[TMPL_BITS]Bit_c32 +%endif +%if TMPL_BITS == 16 +extern _Bs3SwitchTo16BitV86_c32 +%endif + +BS3_BEGIN_TEXT64 +%if TMPL_BITS != 64 +extern _Bs3RegCtxSave_c64 +extern _Bs3SwitchTo%[TMPL_BITS]Bit_c64 +%endif + +TMPL_BEGIN_TEXT + + + +;; +; Saves the current register context. +; +; @param pRegCtx +; @param bBitMode (8) +; @param cbExtraStack (16) +; @uses xAX, xDX, xCX +; +BS3_PROC_BEGIN_CMN Bs3RegCtxSaveEx, BS3_PBC_NEAR ; Far stub generated by the makefile/bs3kit.h. +TONLY16 CPU 8086 + BS3_CALL_CONV_PROLOG 3 + push xBP + mov xBP, xSP +%if ARCH_BITS == 64 + push rcx ; Save pRegCtx +%endif + + ; + ; Get the CPU bitcount part of the current mode. + ; + mov dl, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + and dl, BS3_MODE_CODE_MASK +%if TMPL_BITS == 16 + push dx ; bp - 2: previous CPU mode (16-bit) +%endif + + ; + ; Reserve extra stack space. Make sure we've got 20h here in case we + ; are saving a 64-bit context. + ; +TONLY16 mov ax, [xBP + xCB + cbCurRetAddr + sCB + xCB] +TNOT16 movzx eax, word [xBP + xCB + cbCurRetAddr + sCB + xCB] +%ifdef BS3_STRICT + cmp xAX, 4096 + jb .extra_stack_ok + call Bs3Panic +.extra_stack_ok: +%endif + cmp xAX, 20h + jae .at_least_20h_extra_stack + add xAX, 20h +.at_least_20h_extra_stack: + sub xSP, xAX + + ; + ; Are we just saving the mode we're already in? + ; + mov al, [xBP + xCB + cbCurRetAddr + sCB] + and al, BS3_MODE_CODE_MASK + cmp dl, al + jne .not_the_same_mode + +%if TMPL_BITS == 16 + push word [xBP + xCB + cbCurRetAddr + 2] + push word [xBP + xCB + cbCurRetAddr] +%elif TMPL_BITS == 32 + push dword [xBP + xCB + cbCurRetAddr] +%endif + call Bs3RegCtxSave ; 64-bit: rcx is untouched thus far. + + + ; + ; Return - no need to pop xAX and xDX as the last two + ; operations preserves all registers. + ; +.return: + mov xSP, xBP + pop xBP + BS3_CALL_CONV_EPILOG 3 + BS3_HYBRID_RET + + ; + ; Turns out we have to do switch to a different bitcount before saving. + ; +.not_the_same_mode: + cmp al, BS3_MODE_CODE_16 + je .code_16 + +TONLY16 CPU 386 +%if TMPL_BITS != 32 + cmp al, BS3_MODE_CODE_32 + je .code_32 +%endif +%if TMPL_BITS != 64 + cmp al, BS3_MODE_CODE_V86 + je .code_v86 + cmp al, BS3_MODE_CODE_64 + jne .bad_input_mode + jmp .code_64 +%endif + + ; Bad input (al=input, dl=current). +.bad_input_mode: + call Bs3Panic + + + ; + ; Save a 16-bit context. + ; + ; Convert pRegCtx to 16:16 protected mode and make sure we're in the + ; 16-bit code segment. + ; +.code_16: +%if TMPL_BITS == 16 + %ifdef BS3_STRICT + cmp dl, BS3_MODE_CODE_V86 + jne .bad_input_mode + %endif + push word [xBP + xCB + cbCurRetAddr + 2] + push word [xBP + xCB + cbCurRetAddr] + call Bs3SelRealModeDataToProtFar16 + add sp, 4h + push dx ; Parameter #0 for _Bs3RegCtxSave_c16 + push ax +%else + %if TMPL_BITS == 32 + push dword [xBP + xCB + cbCurRetAddr] + %endif + call Bs3SelFlatDataToProtFar16 ; 64-bit: BS3_CALL not needed, ecx not touched thus far. + mov [xSP], eax ; Parameter #0 for _Bs3RegCtxSave_c16 + jmp .code_16_safe_segment + BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +.code_16_safe_segment: +%endif + call Bs3SwitchTo16Bit + BS3_SET_BITS 16 + + call _Bs3RegCtxSave_c16 + +%if TMPL_BITS == 16 + call _Bs3SwitchTo16BitV86_c16 +%else + call _Bs3SwitchTo%[TMPL_BITS]Bit_c16 +%endif + BS3_SET_BITS TMPL_BITS + jmp .supplement_and_return + TMPL_BEGIN_TEXT + +TONLY16 CPU 386 + + +%if TMPL_BITS != 64 + ; + ; Save a v8086 context. + ; +.code_v86: + %if TMPL_BITS == 16 + %ifdef BS3_STRICT + cmp dl, BS3_MODE_CODE_16 + jne .bad_input_mode + %endif + push word [xBP + xCB + cbCurRetAddr + 2] + push word [xBP + xCB + cbCurRetAddr] + call Bs3SelProtFar16DataToRealMode + add sp, 4h + push dx ; Parameter #0 for _Bs3RegCtxSave_c16 + push ax + %else + push dword [xBP + xCB + cbCurRetAddr] + call Bs3SelFlatDataToRealMode + mov [xSP], eax ; Parameter #0 for _Bs3RegCtxSave_c16 + jmp .code_v86_safe_segment + BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +.code_v86_safe_segment: + %endif + call Bs3SwitchTo16BitV86 + BS3_SET_BITS 16 + + call _Bs3RegCtxSave_c16 + + call _Bs3SwitchTo%[TMPL_BITS]Bit_c16 + BS3_SET_BITS TMPL_BITS + jmp .supplement_and_return +TMPL_BEGIN_TEXT +%endif + + +%if TMPL_BITS != 32 + ; + ; Save a 32-bit context. + ; +.code_32: + %if TMPL_BITS == 16 + push word [xBP + xCB + cbCurRetAddr + 2] + push word [xBP + xCB + cbCurRetAddr] + test dl, BS3_MODE_CODE_V86 + jnz .code_32_from_v86 + call Bs3SelProtFar16DataToFlat + jmp .code_32_flat_ptr +.code_32_from_v86: + call Bs3SelRealModeDataToFlat +.code_32_flat_ptr: + add sp, 4h + push dx ; Parameter #0 for _Bs3RegCtxSave_c32 + push ax + %else + mov [rsp], ecx ; Parameter #0 for _Bs3RegCtxSave_c16 + %endif + call Bs3SwitchTo32Bit + BS3_SET_BITS 32 + + call _Bs3RegCtxSave_c32 + + %if TMPL_BITS == 16 + cmp byte [bp - 2], BS3_MODE_CODE_V86 + je .code_32_back_to_v86 + call _Bs3SwitchTo16Bit_c32 + BS3_SET_BITS TMPL_BITS + jmp .supplement_and_return +.code_32_back_to_v86: + BS3_SET_BITS 32 + call _Bs3SwitchTo16BitV86_c32 + BS3_SET_BITS TMPL_BITS + jmp .return + %else + call _Bs3SwitchTo64Bit_c32 + BS3_SET_BITS TMPL_BITS + jmp .supplement_and_return + %endif +%endif + + +%if TMPL_BITS != 64 + ; + ; Save a 64-bit context. + ; + CPU x86-64 +.code_64: + %if TMPL_BITS == 16 + %ifdef BS3_STRICT + cmp dl, BS3_MODE_CODE_16 + jne .bad_input_mode + %endif + push word [xBP + xCB + cbCurRetAddr + 2] + push word [xBP + xCB + cbCurRetAddr] + call Bs3SelProtFar16DataToFlat + add sp, 4h + mov cx, dx ; Parameter #0 for _Bs3RegCtxSave_c64 + shl ecx, 16 + mov cx, ax + %else + mov ecx, [xBP + xCB + cbCurRetAddr] ; Parameter #0 for _Bs3RegCtxSave_c64 + %endif + call Bs3SwitchTo64Bit ; (preserves all 32-bit GPRs) + BS3_SET_BITS 64 + + call _Bs3RegCtxSave_c64 ; No BS3_CALL as rcx is already ready. + + call _Bs3SwitchTo%[TMPL_BITS]Bit_c64 + BS3_SET_BITS TMPL_BITS + jmp .return +%endif + + + ; + ; Supplement the state out of the current context and then return. + ; +.supplement_and_return: +%if ARCH_BITS == 16 + CPU 8086 + ; Skip 286 and older. Also make 101% sure we not in real mode or v8086 mode. + cmp byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80386 + jb .return ; Just skip if 286 or older. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .return + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + jne .return ; paranoia + CPU 386 +%endif + + ; Load the context pointer into a suitable register. +%if ARCH_BITS == 64 + %define pRegCtx rcx + mov rcx, [xBP - xCB] +%elif ARCH_BITS == 32 + %define pRegCtx ecx + mov ecx, [xBP + xCB + cbCurRetAddr] +%else + %define pRegCtx es:bx + push es + push bx + les bx, [xBP + xCB + cbCurRetAddr] +%endif +%if ARCH_BITS == 64 + ; If we're in 64-bit mode we can capture and restore the high bits. + test byte [pRegCtx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_AMD64 + jz .supplemented_64bit_registers + mov [pRegCtx + BS3REGCTX.r8], r8 + mov [pRegCtx + BS3REGCTX.r9], r9 + mov [pRegCtx + BS3REGCTX.r10], r10 + mov [pRegCtx + BS3REGCTX.r11], r11 + mov [pRegCtx + BS3REGCTX.r12], r12 + mov [pRegCtx + BS3REGCTX.r13], r13 + mov [pRegCtx + BS3REGCTX.r14], r14 + mov [pRegCtx + BS3REGCTX.r15], r15 + shr rax, 32 + mov [pRegCtx + BS3REGCTX.rax + 4], eax + mov rax, rbx + shr rax, 32 + mov [pRegCtx + BS3REGCTX.rbx + 4], eax + mov rax, rcx + shr rax, 32 + mov [pRegCtx + BS3REGCTX.rcx + 4], eax + mov rax, rdx + shr rax, 32 + mov [pRegCtx + BS3REGCTX.rdx + 4], eax + mov rax, rsp + shr rax, 32 + mov [pRegCtx + BS3REGCTX.rsp + 4], eax + mov rax, rbp + shr rax, 32 + mov [pRegCtx + BS3REGCTX.rbp + 4], eax + mov rax, rsi + shr rax, 32 + mov [pRegCtx + BS3REGCTX.rsi + 4], eax + mov rax, rdi + shr rax, 32 + mov [pRegCtx + BS3REGCTX.rdi + 4], eax + and byte [pRegCtx + BS3REGCTX.fbFlags], ~BS3REG_CTX_F_NO_AMD64 +.supplemented_64bit_registers: +%endif + ; The rest requires ring-0 (at least during restore). + mov ax, ss + test ax, 3 + jnz .done_supplementing + + ; Do control registers. + test byte [pRegCtx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR2_CR3 | BS3REG_CTX_F_NO_CR0_IS_MSW | BS3REG_CTX_F_NO_CR4 + jz .supplemented_control_registers + mov sAX, cr0 + mov [pRegCtx + BS3REGCTX.cr0], sAX + mov sAX, cr2 + mov [pRegCtx + BS3REGCTX.cr2], sAX + mov sAX, cr3 + mov [pRegCtx + BS3REGCTX.cr3], sAX + and byte [pRegCtx + BS3REGCTX.fbFlags], ~(BS3REG_CTX_F_NO_CR2_CR3 | BS3REG_CTX_F_NO_CR0_IS_MSW) + +%if ARCH_BITS != 64 + test byte [1 + BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_CPUID >> 8) + jz .supplemented_control_registers +%endif + mov sAX, cr4 + mov [pRegCtx + BS3REGCTX.cr4], sAX + and byte [pRegCtx + BS3REGCTX.fbFlags], ~BS3REG_CTX_F_NO_CR4 +.supplemented_control_registers: + + ; Supply tr and ldtr if necessary + test byte [pRegCtx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_TR_LDTR + jz .done_supplementing + str [pRegCtx + BS3REGCTX.tr] + sldt [pRegCtx + BS3REGCTX.ldtr] + and byte [pRegCtx + BS3REGCTX.fbFlags], ~BS3REG_CTX_F_NO_TR_LDTR + +.done_supplementing: +TONLY16 pop bx +TONLY16 pop es + jmp .return +%undef pRegCtx +BS3_PROC_END_CMN Bs3RegCtxSaveEx + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSaveForMode.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSaveForMode.c new file mode 100644 index 00000000..517d35a2 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSaveForMode.c @@ -0,0 +1,65 @@ +/* $Id: bs3-cmn-RegCtxSaveForMode.c $ */ +/** @file + * BS3Kit - Bs3RegCtxSaveForMode + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3RegCtxSaveForMode +BS3_CMN_DEF(void, Bs3RegCtxSaveForMode,(PBS3REGCTX pRegCtx, uint8_t bMode, uint16_t cbExtraStack)) +{ + if ( bMode != BS3_MODE_RM +#if ARCH_BIT == 16 + || g_bBs3CurrentMode == BS3_MODE_RM +#endif + ) + { + BS3_ASSERT((bMode & BS3_MODE_SYS_MASK) == (g_bBs3CurrentMode & BS3_MODE_SYS_MASK)); + Bs3RegCtxSaveEx(pRegCtx, bMode, cbExtraStack); + } + else + { +#if ARCH_BIT == 64 + BS3_ASSERT(0); /* No V86 mode in LM! */ +#endif + Bs3RegCtxSaveEx(pRegCtx, (bMode & ~BS3_MODE_CODE_MASK) | BS3_MODE_CODE_V86, cbExtraStack); + Bs3RegCtxConvertV86ToRm(pRegCtx); + } +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetGpr.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetGpr.c new file mode 100644 index 00000000..1411ee76 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetGpr.c @@ -0,0 +1,64 @@ +/* $Id: bs3-cmn-RegCtxSetGpr.c $ */ +/** @file + * BS3Kit - Bs3RegCtxSetGpr + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3RegCtxSetGpr +BS3_CMN_DEF(bool, Bs3RegCtxSetGpr,(PBS3REGCTX pRegCtx, uint8_t iGpr, uint64_t uValue, uint8_t cb)) +{ + if (iGpr < 16) + { + PBS3REG pGpr = &pRegCtx->rax + iGpr; + switch (cb) + { + case 1: pGpr->u8 = (uint8_t)uValue; break; + case 2: pGpr->u16 = (uint16_t)uValue; break; + case 4: pGpr->u32 = (uint32_t)uValue; break; + case 8: pGpr->u64 = uValue; break; + default: + BS3_ASSERT(false); + return false; + } + return true; + } + return false; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetGrpSegFromCurPtr.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetGrpSegFromCurPtr.c new file mode 100644 index 00000000..b45f583b --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetGrpSegFromCurPtr.c @@ -0,0 +1,60 @@ +/* $Id: bs3-cmn-RegCtxSetGrpSegFromCurPtr.c $ */ +/** @file + * BS3Kit - Bs3RegCtxSetGrpSegFromCurPtr, Bs3RegCtxSetGrpDsFromCurPtr + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3RegCtxSetGrpSegFromCurPtr +BS3_CMN_DEF(void, Bs3RegCtxSetGrpSegFromCurPtr,(PBS3REGCTX pRegCtx, PBS3REG pGpr, PRTSEL pSel, void BS3_FAR *pvPtr)) +{ +#if ARCH_BITS == 16 + Bs3RegCtxSetGrpSegFromFlat(pRegCtx, pGpr, pSel, Bs3SelPtrToFlat(pvPtr)); +#else + Bs3RegCtxSetGrpSegFromFlat(pRegCtx, pGpr, pSel, (uintptr_t)pvPtr); +#endif +} + + +#undef Bs3RegCtxSetGrpDsFromCurPtr +BS3_CMN_DEF(void, Bs3RegCtxSetGrpDsFromCurPtr,(PBS3REGCTX pRegCtx, PBS3REG pGpr, void BS3_FAR *pvPtr)) +{ + BS3_CMN_FAR_NM(Bs3RegCtxSetGrpSegFromCurPtr)(pRegCtx, pGpr, &pRegCtx->ds, pvPtr); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetGrpSegFromFlat.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetGrpSegFromFlat.c new file mode 100644 index 00000000..9c9f525d --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetGrpSegFromFlat.c @@ -0,0 +1,75 @@ +/* $Id: bs3-cmn-RegCtxSetGrpSegFromFlat.c $ */ +/** @file + * BS3Kit - Bs3RegCtxSetGrpSegFromFlat + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3RegCtxSetGrpSegFromFlat +BS3_CMN_DEF(void, Bs3RegCtxSetGrpSegFromFlat,(PBS3REGCTX pRegCtx, PBS3REG pGpr, PRTSEL pSel, RTCCUINTXREG uFlat)) +{ + if (BS3_MODE_IS_16BIT_CODE(pRegCtx->bMode)) + { + uint32_t uFar1616; + if (BS3_MODE_IS_RM_OR_V86(pRegCtx->bMode)) + uFar1616 = Bs3SelFlatDataToRealMode(uFlat); + else + uFar1616 = Bs3SelFlatDataToProtFar16(uFlat); + pGpr->u = uFar1616 & UINT16_MAX; + *pSel = uFar1616 >> 16; + } + else + { + pGpr->u = uFlat; + if (BS3_MODE_IS_32BIT_CODE(pRegCtx->bMode)) + *pSel = BS3_SEL_R0_DS32; + else + *pSel = BS3_SEL_R0_DS64; + } + + /* Adjust CS to the right ring, if not ring-0 or V86 context. */ + if ( pRegCtx->bCpl != 0 + && !BS3_MODE_IS_RM_OR_V86(pRegCtx->bMode)) + { + if (BS3_SEL_IS_IN_R0_RANGE(*pSel)) + *pSel += (uint16_t)pRegCtx->bCpl << BS3_SEL_RING_SHIFT; + *pSel |= pRegCtx->bCpl; + } +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetRipCsFromCurPtr.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetRipCsFromCurPtr.c new file mode 100644 index 00000000..ba0948f1 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetRipCsFromCurPtr.c @@ -0,0 +1,53 @@ +/* $Id: bs3-cmn-RegCtxSetRipCsFromCurPtr.c $ */ +/** @file + * BS3Kit - Bs3RegCtxSetRipCsFromCurPtr + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3RegCtxSetRipCsFromCurPtr +BS3_CMN_DEF(void, Bs3RegCtxSetRipCsFromCurPtr,(PBS3REGCTX pRegCtx, FPFNBS3FAR pfnCode)) +{ +#if ARCH_BITS == 16 + Bs3RegCtxSetRipCsFromFlat(pRegCtx, Bs3SelPtrToFlat((void BS3_FAR *)pfnCode)); +#else + Bs3RegCtxSetRipCsFromFlat(pRegCtx, (uintptr_t)pfnCode); +#endif +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetRipCsFromFlat.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetRipCsFromFlat.c new file mode 100644 index 00000000..833997a4 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetRipCsFromFlat.c @@ -0,0 +1,75 @@ +/* $Id: bs3-cmn-RegCtxSetRipCsFromFlat.c $ */ +/** @file + * BS3Kit - Bs3RegCtxSetRipCsFromFlat + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3RegCtxSetRipCsFromFlat +BS3_CMN_DEF(void, Bs3RegCtxSetRipCsFromFlat,(PBS3REGCTX pRegCtx, RTCCUINTXREG uFlatCode)) +{ + if (BS3_MODE_IS_16BIT_CODE(pRegCtx->bMode)) + { + uint32_t uFar1616; + if (BS3_MODE_IS_RM_OR_V86(pRegCtx->bMode)) + uFar1616 = Bs3SelFlatCodeToRealMode(uFlatCode); + else + uFar1616 = Bs3SelFlatCodeToProtFar16(uFlatCode); + pRegCtx->rip.u = uFar1616 & UINT16_MAX; + pRegCtx->cs = uFar1616 >> 16; + } + else + { + pRegCtx->rip.u = uFlatCode; + if (BS3_MODE_IS_32BIT_CODE(pRegCtx->bMode)) + pRegCtx->cs = BS3_SEL_R0_CS32; + else + pRegCtx->cs = BS3_SEL_R0_CS64; + } + + /* Adjust CS to the right ring, if not ring-0 or V86 context. */ + if ( pRegCtx->bCpl != 0 + && !BS3_MODE_IS_RM_OR_V86(pRegCtx->bMode) + && BS3_SEL_IS_IN_R0_RANGE(pRegCtx->cs)) + { + pRegCtx->cs += (uint16_t)pRegCtx->bCpl << BS3_SEL_RING_SHIFT; + pRegCtx->cs |= pRegCtx->bCpl; + } +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetRipCsFromLnkPtr.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetRipCsFromLnkPtr.c new file mode 100644 index 00000000..fd05fbbc --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetRipCsFromLnkPtr.c @@ -0,0 +1,87 @@ +/* $Id: bs3-cmn-RegCtxSetRipCsFromLnkPtr.c $ */ +/** @file + * BS3Kit - Bs3RegCtxSetRipCsFromLnkPtr + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3RegCtxSetRipCsFromLnkPtr +BS3_CMN_DEF(void, Bs3RegCtxSetRipCsFromLnkPtr,(PBS3REGCTX pRegCtx, FPFNBS3FAR pfnCode)) +{ + if (BS3_MODE_IS_16BIT_CODE(pRegCtx->bMode)) + { +#if ARCH_BITS == 16 + pRegCtx->rip.u = BS3_FP_OFF(pfnCode); + if (BS3_MODE_IS_RM_OR_V86(pRegCtx->bMode)) + pRegCtx->cs = BS3_FP_SEG(pfnCode); + else + pRegCtx->cs = Bs3SelRealModeCodeToProtMode(BS3_FP_SEG(pfnCode)); +#else + uint32_t uFar1616; + if (BS3_MODE_IS_RM_OR_V86(pRegCtx->bMode)) + uFar1616 = Bs3SelFlatCodeToRealMode((uint32_t)(uintptr_t)pfnCode); + else + uFar1616 = Bs3SelFlatCodeToProtFar16((uint32_t)(uintptr_t)pfnCode); + pRegCtx->rip.u = uFar1616 & UINT16_MAX; + pRegCtx->cs = uFar1616 >> 16; +#endif + } + else + { +#if ARCH_BITS == 16 + pRegCtx->rip.u = Bs3SelRealModeCodeToFlat(pfnCode); +#else + pRegCtx->rip.u = (uintptr_t)pfnCode; +#endif + if (BS3_MODE_IS_32BIT_CODE(pRegCtx->bMode)) + pRegCtx->cs = BS3_SEL_R0_CS32; + else + pRegCtx->cs = BS3_SEL_R0_CS64; + } + + /* Adjust CS to the right ring, if not ring-0 or V86 context. */ + if ( pRegCtx->bCpl != 0 + && !BS3_MODE_IS_RM_OR_V86(pRegCtx->bMode) + && BS3_SEL_IS_IN_R0_RANGE(pRegCtx->cs)) + { + pRegCtx->cs += (uint16_t)pRegCtx->bCpl << BS3_SEL_RING_SHIFT; + pRegCtx->cs |= pRegCtx->bCpl; + } +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetCr0.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetCr0.asm new file mode 100644 index 00000000..3f91ed80 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetCr0.asm @@ -0,0 +1,89 @@ +; $Id: bs3-cmn-RegGetCr0.asm $ +;; @file +; BS3Kit - Bs3RegGetCr0 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Panic +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(RTCCUINTXREG, Bs3RegGetCr0,(void)); +; +; @returns Register value. +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs (only return full register(s)). +; +BS3_PROC_BEGIN_CMN Bs3RegGetCr0, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 0 + push xBP + mov xBP, xSP + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov ax, ss + and ax, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sAX, cr0 +TONLY16 mov edx, eax +TONLY16 shr edx, 16 + jmp .return + +.via_system_call: + mov xAX, BS3_SYSCALL_GET_CRX + mov dl, 0 + call Bs3Syscall + +.return: + pop xBP + BS3_CALL_CONV_EPILOG 0 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegGetCr0 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetCr2.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetCr2.asm new file mode 100644 index 00000000..eb6be133 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetCr2.asm @@ -0,0 +1,89 @@ +; $Id: bs3-cmn-RegGetCr2.asm $ +;; @file +; BS3Kit - Bs3RegGetCr2 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Panic +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(RTCCUINTXREG, Bs3RegGetCr2,(void)); +; +; @returns Register value. +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs (only return full register(s)). +; +BS3_PROC_BEGIN_CMN Bs3RegGetCr2, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 0 + push xBP + mov xBP, xSP + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov ax, ss + and ax, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sAX, cr2 +TONLY16 mov edx, eax +TONLY16 shr edx, 16 + jmp .return + +.via_system_call: + mov xAX, BS3_SYSCALL_GET_CRX + mov dl, 2 + call Bs3Syscall + +.return: + pop xBP + BS3_CALL_CONV_EPILOG 0 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegGetCr2 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetCr3.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetCr3.asm new file mode 100644 index 00000000..4eddbd96 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetCr3.asm @@ -0,0 +1,89 @@ +; $Id: bs3-cmn-RegGetCr3.asm $ +;; @file +; BS3Kit - Bs3RegGetCr3 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Panic +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(RTCCUINTXREG, Bs3RegGetCr3,(void)); +; +; @returns Register value. +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs (only return full register(s)). +; +BS3_PROC_BEGIN_CMN Bs3RegGetCr3, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 0 + push xBP + mov xBP, xSP + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov ax, ss + and ax, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sAX, cr3 +TONLY16 mov edx, eax +TONLY16 shr edx, 16 + jmp .return + +.via_system_call: + mov xAX, BS3_SYSCALL_GET_CRX + mov dl, 3 + call Bs3Syscall + +.return: + pop xBP + BS3_CALL_CONV_EPILOG 0 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegGetCr3 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetCr4.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetCr4.asm new file mode 100644 index 00000000..a5e60735 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetCr4.asm @@ -0,0 +1,89 @@ +; $Id: bs3-cmn-RegGetCr4.asm $ +;; @file +; BS3Kit - Bs3RegGetCr4 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Panic +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(RTCCUINTXREG, Bs3RegGetCr4,(void)); +; +; @returns Register value. +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs (only return full register(s)). +; +BS3_PROC_BEGIN_CMN Bs3RegGetCr4, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 0 + push xBP + mov xBP, xSP + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov ax, ss + and ax, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sAX, cr4 +TONLY16 mov edx, eax +TONLY16 shr edx, 16 + jmp .return + +.via_system_call: + mov xAX, BS3_SYSCALL_GET_CRX + mov dl, 4 + call Bs3Syscall + +.return: + pop xBP + BS3_CALL_CONV_EPILOG 0 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegGetCr4 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr0.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr0.asm new file mode 100644 index 00000000..1c144c33 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr0.asm @@ -0,0 +1,89 @@ +; $Id: bs3-cmn-RegGetDr0.asm $ +;; @file +; BS3Kit - Bs3RegGetDr0 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Panic +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(RTCCUINTXREG, Bs3RegGetDr0,(void)); +; +; @returns Register value. +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs (only return full register(s)). +; +BS3_PROC_BEGIN_CMN Bs3RegGetDr0, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 0 + push xBP + mov xBP, xSP + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov ax, ss + and ax, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sAX, dr0 +TONLY16 mov edx, eax +TONLY16 shr edx, 16 + jmp .return + +.via_system_call: + mov xAX, BS3_SYSCALL_GET_DRX + mov dl, 0 + call Bs3Syscall + +.return: + pop xBP + BS3_CALL_CONV_EPILOG 0 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegGetDr0 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr1.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr1.asm new file mode 100644 index 00000000..057a763c --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr1.asm @@ -0,0 +1,89 @@ +; $Id: bs3-cmn-RegGetDr1.asm $ +;; @file +; BS3Kit - Bs3RegGetDr1 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Panic +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(RTCCUINTXREG, Bs3RegGetDr1,(void)); +; +; @returns Register value. +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs (only return full register(s)). +; +BS3_PROC_BEGIN_CMN Bs3RegGetDr1, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 0 + push xBP + mov xBP, xSP + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov ax, ss + and ax, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sAX, dr1 +TONLY16 mov edx, eax +TONLY16 shr edx, 16 + jmp .return + +.via_system_call: + mov xAX, BS3_SYSCALL_GET_DRX + mov dl, 1 + call Bs3Syscall + +.return: + pop xBP + BS3_CALL_CONV_EPILOG 0 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegGetDr1 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr2.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr2.asm new file mode 100644 index 00000000..8f2be61e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr2.asm @@ -0,0 +1,89 @@ +; $Id: bs3-cmn-RegGetDr2.asm $ +;; @file +; BS3Kit - Bs3RegGetDr2 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Panic +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(RTCCUINTXREG, Bs3RegGetDr2,(void)); +; +; @returns Register value. +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs (only return full register(s)). +; +BS3_PROC_BEGIN_CMN Bs3RegGetDr2, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 0 + push xBP + mov xBP, xSP + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov ax, ss + and ax, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sAX, dr2 +TONLY16 mov edx, eax +TONLY16 shr edx, 16 + jmp .return + +.via_system_call: + mov xAX, BS3_SYSCALL_GET_DRX + mov dl, 2 + call Bs3Syscall + +.return: + pop xBP + BS3_CALL_CONV_EPILOG 0 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegGetDr2 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr3.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr3.asm new file mode 100644 index 00000000..5388857e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr3.asm @@ -0,0 +1,89 @@ +; $Id: bs3-cmn-RegGetDr3.asm $ +;; @file +; BS3Kit - Bs3RegGetDr3 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Panic +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(RTCCUINTXREG, Bs3RegGetDr3,(void)); +; +; @returns Register value. +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs (only return full register(s)). +; +BS3_PROC_BEGIN_CMN Bs3RegGetDr3, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 0 + push xBP + mov xBP, xSP + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov ax, ss + and ax, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sAX, dr3 +TONLY16 mov edx, eax +TONLY16 shr edx, 16 + jmp .return + +.via_system_call: + mov xAX, BS3_SYSCALL_GET_DRX + mov dl, 3 + call Bs3Syscall + +.return: + pop xBP + BS3_CALL_CONV_EPILOG 0 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegGetDr3 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr6.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr6.asm new file mode 100644 index 00000000..12a56485 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr6.asm @@ -0,0 +1,89 @@ +; $Id: bs3-cmn-RegGetDr6.asm $ +;; @file +; BS3Kit - Bs3RegGetDr6 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Panic +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(RTCCUINTXREG, Bs3RegGetDr6,(void)); +; +; @returns Register value. +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs (only return full register(s)). +; +BS3_PROC_BEGIN_CMN Bs3RegGetDr6, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 0 + push xBP + mov xBP, xSP + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov ax, ss + and ax, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sAX, dr6 +TONLY16 mov edx, eax +TONLY16 shr edx, 16 + jmp .return + +.via_system_call: + mov xAX, BS3_SYSCALL_GET_DRX + mov dl, 6 + call Bs3Syscall + +.return: + pop xBP + BS3_CALL_CONV_EPILOG 0 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegGetDr6 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr7.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr7.asm new file mode 100644 index 00000000..ae45c4a8 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr7.asm @@ -0,0 +1,89 @@ +; $Id: bs3-cmn-RegGetDr7.asm $ +;; @file +; BS3Kit - Bs3RegGetDr7 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Panic +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(RTCCUINTXREG, Bs3RegGetDr7,(void)); +; +; @returns Register value. +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs (only return full register(s)). +; +BS3_PROC_BEGIN_CMN Bs3RegGetDr7, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 0 + push xBP + mov xBP, xSP + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov ax, ss + and ax, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sAX, dr7 +TONLY16 mov edx, eax +TONLY16 shr edx, 16 + jmp .return + +.via_system_call: + mov xAX, BS3_SYSCALL_GET_DRX + mov dl, 7 + call Bs3Syscall + +.return: + pop xBP + BS3_CALL_CONV_EPILOG 0 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegGetDr7 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDrX.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDrX.asm new file mode 100644 index 00000000..26cc9774 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDrX.asm @@ -0,0 +1,135 @@ +; $Id: bs3-cmn-RegGetDrX.asm $ +;; @file +; BS3Kit - Bs3RegGetDrX +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Panic +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + +;TONLY16 CPU 386 + +;; +; @cproto BS3_CMN_PROTO_STUB(RTCCUINTXREG, Bs3RegGetDrX,(uint8_t iReg)); +; +; @returns Register value. +; @param iRegister The source register +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs (only return full register(s)). +; +BS3_PROC_BEGIN_CMN Bs3RegGetDrX, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov ax, ss + and ax, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + ; Switch (iRegister) + mov al, [xBP + xCB + cbCurRetAddr] + cmp al, 6 + jz .get_dr6 + cmp al, 7 + jz .get_dr7 + cmp al, 0 + jz .get_dr0 + cmp al, 1 + jz .get_dr1 + cmp al, 2 + jz .get_dr2 + cmp al, 3 + jz .get_dr3 + cmp al, 4 + jz .get_dr4 + cmp al, 5 + jz .get_dr5 + call Bs3Panic + +.get_dr0: + mov sAX, dr0 + jmp .return_fixup +.get_dr1: + mov sAX, dr1 + jmp .return_fixup +.get_dr2: + mov sAX, dr2 + jmp .return_fixup +.get_dr3: + mov sAX, dr3 + jmp .return_fixup +.get_dr4: + mov sAX, dr4 + jmp .return_fixup +.get_dr5: + mov sAX, dr5 + jmp .return_fixup +.get_dr7: + mov sAX, dr7 + jmp .return_fixup +.get_dr6: + mov sAX, dr6 + jmp .return_fixup + +.via_system_call: + mov xAX, BS3_SYSCALL_GET_DRX + mov dl, [xBP + xCB + cbCurRetAddr] + call Bs3Syscall + jmp .return + +.return_fixup: +TONLY16 mov edx, eax +TONLY16 shr edx, 16 +.return: + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegGetDrX + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetLdtr.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetLdtr.asm new file mode 100644 index 00000000..5291d5c6 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetLdtr.asm @@ -0,0 +1,80 @@ +; $Id: bs3-cmn-RegGetLdtr.asm $ +;; @file +; BS3Kit - Bs3RegGetLdtr +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +BS3_EXTERN_SYSTEM16 Bs3Gdt +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(uint16_t, Bs3RegGetLdtr,(void)); +; +; @returns The LDTR value. + +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3RegGetLdtr, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 0 + push xBP + mov xBP, xSP + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call +%endif + ; Load it. + sldt ax + jmp .return + +.via_system_call: + mov ax, BS3_SYSCALL_GET_LDTR + call Bs3Syscall + +.return: + pop xBP + BS3_CALL_CONV_EPILOG 0 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegGetLdtr + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetTr.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetTr.asm new file mode 100644 index 00000000..d1f6a2d9 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetTr.asm @@ -0,0 +1,80 @@ +; $Id: bs3-cmn-RegGetTr.asm $ +;; @file +; BS3Kit - Bs3RegGetTr +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +BS3_EXTERN_SYSTEM16 Bs3Gdt +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(uint16_t, Bs3RegGetTr,(void)); +; +; @returns The LDTR value. + +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3RegGetTr, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 0 + push xBP + mov xBP, xSP + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call +%endif + ; Load it. + str ax + jmp .return + +.via_system_call: + mov ax, BS3_SYSCALL_GET_TR + call Bs3Syscall + +.return: + pop xBP + BS3_CALL_CONV_EPILOG 0 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegGetTr + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetXcr0.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetXcr0.asm new file mode 100644 index 00000000..f717205d --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetXcr0.asm @@ -0,0 +1,77 @@ +; $Id: bs3-cmn-RegGetXcr0.asm $ +;; @file +; BS3Kit - Bs3RegGetXcr0 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; @cproto BS3_CMN_PROTO_STUB(uint64_t, Bs3RegGetXcr0,(void)); +; +; @returns Register value. +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs, though 16-bit mode the upper 48-bits of RAX, RDX and RCX are cleared. +; +BS3_PROC_BEGIN_CMN Bs3RegGetXcr0, BS3_PBC_HYBRID_SAFE + push xBP + mov xBP, xSP +TONLY64 push rdx + + ; Read the value. +TNOT16 push sCX + xor ecx, ecx + xgetbv +TNOT16 pop sCX + + ; Move the edx:eax value into the appropriate return register(s). +%if TMPL_BITS == 16 + ; value [dx cx bx ax] + ror eax, 16 + mov bx, ax + mov cx, dx + shr eax, 16 + shr edx, 16 +%elif TMPL_BITS == 64 + mov eax, eax + shr rdx, 32 + or rax, rdx +%endif + +TONLY64 pop rdx + pop xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegGetXcr0 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetCr0.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetCr0.asm new file mode 100644 index 00000000..2c1f4bc1 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetCr0.asm @@ -0,0 +1,96 @@ +; $Id: bs3-cmn-RegSetCr0.asm $ +;; @file +; BS3Kit - Bs3RegSetCr0 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(void, Bs3RegSetCr0,(RTCCUINTXREG uValue)); +; +; @param uValue The value to set. + +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3RegSetCr0, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push sSI + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov si, ss + and si, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sSI, [xBP + xCB + cbCurRetAddr] + mov cr0, sSI + jmp .return + +.via_system_call: + push xDX + push xAX + + mov sSI, [xBP + xCB + cbCurRetAddr] + mov xAX, BS3_SYSCALL_SET_CRX + mov dl, 0 + call Bs3Syscall + pop xAX + pop xDX + +.return: + pop sSI + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegSetCr0 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetCr2.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetCr2.asm new file mode 100644 index 00000000..282d850a --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetCr2.asm @@ -0,0 +1,96 @@ +; $Id: bs3-cmn-RegSetCr2.asm $ +;; @file +; BS3Kit - Bs3RegSetCr2 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(void, Bs3RegSetCr1,(RTCCUINTXREG uValue)); +; +; @param uValue The value to set. + +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3RegSetCr2, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push sSI + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov si, ss + and si, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sSI, [xBP + xCB + cbCurRetAddr] + mov cr2, sSI + jmp .return + +.via_system_call: + push xDX + push xAX + + mov sSI, [xBP + xCB + cbCurRetAddr] + mov xAX, BS3_SYSCALL_SET_DRX + mov dl, 2 + call Bs3Syscall + pop xAX + pop xDX + +.return: + pop sSI + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegSetCr2 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetCr3.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetCr3.asm new file mode 100644 index 00000000..b95df2db --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetCr3.asm @@ -0,0 +1,96 @@ +; $Id: bs3-cmn-RegSetCr3.asm $ +;; @file +; BS3Kit - Bs3RegSetCr3 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(void, Bs3RegSetCr3,(RTCCUINTXREG uValue)); +; +; @param uValue The value to set. + +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3RegSetCr3, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push sSI + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov si, ss + and si, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sSI, [xBP + xCB + cbCurRetAddr] + mov cr3, sSI + jmp .return + +.via_system_call: + push xDX + push xAX + + mov sSI, [xBP + xCB + cbCurRetAddr] + mov xAX, BS3_SYSCALL_SET_DRX + mov dl, 3 + call Bs3Syscall + pop xAX + pop xDX + +.return: + pop sSI + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegSetCr3 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetCr4.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetCr4.asm new file mode 100644 index 00000000..f32cc9fc --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetCr4.asm @@ -0,0 +1,96 @@ +; $Id: bs3-cmn-RegSetCr4.asm $ +;; @file +; BS3Kit - Bs3RegSetCr4 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(void, Bs3RegSetCr4,(RTCCUINTXREG uValue)); +; +; @param uValue The value to set. + +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3RegSetCr4, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push sSI + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov si, ss + and si, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sSI, [xBP + xCB + cbCurRetAddr] + mov cr4, sSI + jmp .return + +.via_system_call: + push xDX + push xAX + + mov sSI, [xBP + xCB + cbCurRetAddr] + mov xAX, BS3_SYSCALL_SET_CRX + mov dl, 4 + call Bs3Syscall + pop xAX + pop xDX + +.return: + pop sSI + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegSetCr4 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr0.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr0.asm new file mode 100644 index 00000000..704d6f31 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr0.asm @@ -0,0 +1,96 @@ +; $Id: bs3-cmn-RegSetDr0.asm $ +;; @file +; BS3Kit - Bs3RegSetDr0 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(void, Bs3RegSetDr0,(RTCCUINTXREG uValue)); +; +; @param uValue The value to set. + +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3RegSetDr0, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push sSI + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov si, ss + and si, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sSI, [xBP + xCB + cbCurRetAddr] + mov dr0, sSI + jmp .return + +.via_system_call: + push xDX + push xAX + + mov sSI, [xBP + xCB + cbCurRetAddr] + mov xAX, BS3_SYSCALL_SET_DRX + mov dl, 0 + call Bs3Syscall + pop xAX + pop xDX + +.return: + pop sSI + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegSetDr0 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr1.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr1.asm new file mode 100644 index 00000000..6b20e58c --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr1.asm @@ -0,0 +1,96 @@ +; $Id: bs3-cmn-RegSetDr1.asm $ +;; @file +; BS3Kit - Bs3RegSetDr1 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(void, Bs3RegSetDr1,(RTCCUINTXREG uValue)); +; +; @param uValue The value to set. + +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3RegSetDr1, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push sSI + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov si, ss + and si, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sSI, [xBP + xCB + cbCurRetAddr] + mov dr1, sSI + jmp .return + +.via_system_call: + push xDX + push xAX + + mov sSI, [xBP + xCB + cbCurRetAddr] + mov xAX, BS3_SYSCALL_SET_DRX + mov dl, 1 + call Bs3Syscall + pop xAX + pop xDX + +.return: + pop sSI + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegSetDr1 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr2.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr2.asm new file mode 100644 index 00000000..e39ff7f2 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr2.asm @@ -0,0 +1,96 @@ +; $Id: bs3-cmn-RegSetDr2.asm $ +;; @file +; BS3Kit - Bs3RegSetDr2 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(void, Bs3RegSetDr2,(RTCCUINTXREG uValue)); +; +; @param uValue The value to set. + +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3RegSetDr2, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push sSI + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov si, ss + and si, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sSI, [xBP + xCB + cbCurRetAddr] + mov dr2, sSI + jmp .return + +.via_system_call: + push xDX + push xAX + + mov sSI, [xBP + xCB + cbCurRetAddr] + mov xAX, BS3_SYSCALL_SET_DRX + mov dl, 2 + call Bs3Syscall + pop xAX + pop xDX + +.return: + pop sSI + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegSetDr2 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr3.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr3.asm new file mode 100644 index 00000000..66b98c0a --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr3.asm @@ -0,0 +1,96 @@ +; $Id: bs3-cmn-RegSetDr3.asm $ +;; @file +; BS3Kit - Bs3RegSetDr3 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(void, Bs3RegSetDr3,(RTCCUINTXREG uValue)); +; +; @param uValue The value to set. + +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3RegSetDr3, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push sSI + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov si, ss + and si, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sSI, [xBP + xCB + cbCurRetAddr] + mov dr3, sSI + jmp .return + +.via_system_call: + push xDX + push xAX + + mov sSI, [xBP + xCB + cbCurRetAddr] + mov xAX, BS3_SYSCALL_SET_DRX + mov dl, 3 + call Bs3Syscall + pop xAX + pop xDX + +.return: + pop sSI + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegSetDr3 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr6.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr6.asm new file mode 100644 index 00000000..11e945dd --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr6.asm @@ -0,0 +1,96 @@ +; $Id: bs3-cmn-RegSetDr6.asm $ +;; @file +; BS3Kit - Bs3RegSetDr6 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(void, Bs3RegSetDr6,(RTCCUINTXREG uValue)); +; +; @param uValue The value to set. + +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3RegSetDr6, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push sSI + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov si, ss + and si, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sSI, [xBP + xCB + cbCurRetAddr] + mov dr6, sSI + jmp .return + +.via_system_call: + push xDX + push xAX + + mov sSI, [xBP + xCB + cbCurRetAddr] + mov xAX, BS3_SYSCALL_SET_DRX + mov dl, 6 + call Bs3Syscall + pop xAX + pop xDX + +.return: + pop sSI + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegSetDr6 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr7.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr7.asm new file mode 100644 index 00000000..ea36ad7c --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr7.asm @@ -0,0 +1,96 @@ +; $Id: bs3-cmn-RegSetDr7.asm $ +;; @file +; BS3Kit - Bs3RegSetDr7 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(void, Bs3RegSetDr7,(RTCCUINTXREG uValue)); +; +; @param uValue The value to set. + +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3RegSetDr7, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push sSI + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov si, ss + and si, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + mov sSI, [xBP + xCB + cbCurRetAddr] + mov dr7, sSI + jmp .return + +.via_system_call: + push xDX + push xAX + + mov sSI, [xBP + xCB + cbCurRetAddr] + mov xAX, BS3_SYSCALL_SET_DRX + mov dl, 7 + call Bs3Syscall + pop xAX + pop xDX + +.return: + pop sSI + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegSetDr7 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDrX.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDrX.asm new file mode 100644 index 00000000..cc36df17 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDrX.asm @@ -0,0 +1,142 @@ +; $Id: bs3-cmn-RegSetDrX.asm $ +;; @file +; BS3Kit - Bs3RegSetDrX +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Panic +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + +;TONLY16 CPU 386 + +;; +; @cproto BS3_CMN_PROTO_STUB(void, Bs3RegSetDrX,(uint8_t iReg, RTCCUINTXREG uValue)); +; +; @returns Register value. +; @param iRegister The source register +; @param uValue The new Value. + +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3RegSetDrX, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 2 + push xBP + mov xBP, xSP + push sSI + push xDX + + mov sSI, [xBP + xCB + cbCurRetAddr + xCB] + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov dx, ss + and dx, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + ; Switch (iRegister) + mov dl, [xBP + xCB + cbCurRetAddr] + cmp dl, 6 + jz .set_dr6 + cmp dl, 7 + jz .set_dr7 + cmp dl, 0 + jz .set_dr0 + cmp dl, 1 + jz .set_dr1 + cmp dl, 2 + jz .set_dr2 + cmp dl, 3 + jz .set_dr3 + cmp dl, 4 + jz .set_dr4 + cmp dl, 5 + jz .set_dr5 + + call Bs3Panic + +.set_dr0: + mov dr0, sSI + jmp .return +.set_dr1: + mov dr1, sSI + jmp .return +.set_dr2: + mov dr2, sSI + jmp .return +.set_dr3: + mov dr3, sSI + jmp .return +.set_dr4: + mov dr4, sSI + jmp .return +.set_dr5: + mov dr5, sSI + jmp .return +.set_dr7: + mov dr7, sSI + jmp .return +.set_dr6: + mov dr6, sSI + jmp .return + +.via_system_call: + mov dl, [xBP + xCB + cbCurRetAddr] + push xAX + mov xAX, BS3_SYSCALL_SET_DRX + call Bs3Syscall + pop xAX + +.return: + pop xDX + pop sSI + pop xBP + BS3_CALL_CONV_EPILOG 2 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegSetDrX + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetLdtr.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetLdtr.asm new file mode 100644 index 00000000..8ff229ec --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetLdtr.asm @@ -0,0 +1,91 @@ +; $Id: bs3-cmn-RegSetLdtr.asm $ +;; @file +; BS3Kit - Bs3RegSetLdtr +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +BS3_EXTERN_SYSTEM16 Bs3Gdt +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(void, Bs3RegSetLdtr,(uint16_t uValue)); +; +; @param uValue The value to set. + +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3RegSetLdtr, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push xDX + push xAX + + mov dx, [xBP + xCB + cbCurRetAddr] + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call +%endif + ; If not in ring-0, we have to make a system call. + mov ax, ss + and ax, X86_SEL_RPL + jnz .via_system_call + + ; Load it. + lldt dx + jmp .return + +.via_system_call: + mov ax, BS3_SYSCALL_SET_LDTR + call Bs3Syscall + +.return: + pop xAX + pop xDX + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegSetLdtr + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetTr.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetTr.asm new file mode 100644 index 00000000..0d0ffa8e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetTr.asm @@ -0,0 +1,108 @@ +; $Id: bs3-cmn-RegSetTr.asm $ +;; @file +; BS3Kit - Bs3RegSetTr +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +BS3_EXTERN_SYSTEM16 Bs3Gdt +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(void, Bs3RegSetTr,(uint16_t uValue)); +; +; @param uValue The value to set. + +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3RegSetTr, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push xDX + push xAX + push xDI + + mov dx, [xBP + xCB + cbCurRetAddr] + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call +%endif + ; If not in ring-0, we have to make a system call. + mov ax, ss + and ax, X86_SEL_RPL + jnz .via_system_call + + ; Before we can load it, we must mark it non-busy. +%if TMPL_BITS == 16 + push ds + mov ax, BS3_SEL_SYSTEM16 + mov ds, ax + mov di, dx + add xDI, Bs3Gdt wrt BS3SYSTEM16 +%else + movzx edi, dx + add xDI, Bs3Gdt wrt FLAT +%endif + add xDI, X86DESCGENERIC_BIT_OFF_TYPE / 8 + and byte [xDI], ~(X86_SEL_TYPE_SYS_TSS_BUSY_MASK << (X86DESCGENERIC_BIT_OFF_TYPE % 8)) +%if TMPL_BITS == 16 + pop ds +%endif + ltr dx + jmp .return + +.via_system_call: + mov ax, BS3_SYSCALL_SET_TR + call Bs3Syscall + +.return: + pop xDI + pop xAX + pop xDX + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegSetTr + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetXcr0.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetXcr0.asm new file mode 100644 index 00000000..eba35364 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetXcr0.asm @@ -0,0 +1,104 @@ +; $Id: bs3-cmn-RegSetXcr0.asm $ +;; @file +; BS3Kit - Bs3RegSetXcr0 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO_STUB(void, Bs3RegSetXcr0,(uint64_t uValue)); +; +; @param uValue The value to set. + +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3RegSetXcr0, BS3_PBC_HYBRID_SAFE + push xBP + mov xBP, xSP + push sSI + push sDX + push sAX + + ; Load the value +%if TMPL_BITS == 64 + mov eax, ecx + mov rdx, rcx + shr rdx, 32 +%else + mov sAX, [xBP + xCB + cbCurRetAddr] + mov sDX, [xBP + xCB + cbCurRetAddr + 4] +%endif + +%if TMPL_BITS == 16 + ; If V8086 mode we have to go thru a syscall. + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + jnz .via_system_call + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM + je .direct_access +%endif + ; If not in ring-0, we have to make a system call. + mov si, ss + and si, X86_SEL_RPL + jnz .via_system_call + +.direct_access: + push sCX + xor ecx, ecx + xsetbv + pop sCX + jmp .return + +.via_system_call: + xchg esi, eax + mov xAX, BS3_SYSCALL_SET_XCR0 + call Bs3Syscall + +.return: + pop sAX + pop sDX + pop sSI + pop xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3RegSetXcr0 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFar32ToFlat32.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFar32ToFlat32.c new file mode 100644 index 00000000..af3bc079 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFar32ToFlat32.c @@ -0,0 +1,47 @@ +/* $Id: bs3-cmn-SelFar32ToFlat32.c $ */ +/** @file + * BS3Kit - Bs3SelFar32ToFlat32 + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit-template-header.h" + + +#undef Bs3SelFar32ToFlat32 +BS3_CMN_DEF(uint32_t, Bs3SelFar32ToFlat32,(uint32_t off, uint16_t uSel)) +{ + if (BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode)) + return ((uint32_t)uSel << 4) + off; + return Bs3SelProtFar32ToFlat32(off, uSel); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFar32ToFlat32NoClobber.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFar32ToFlat32NoClobber.asm new file mode 100644 index 00000000..d2df7366 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFar32ToFlat32NoClobber.asm @@ -0,0 +1,114 @@ +; $Id: bs3-cmn-SelFar32ToFlat32NoClobber.asm $ +;; @file +; BS3Kit - Bs3SelFar32ToFlat32NoClobber. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_EXTERN_CMN Bs3SelFar32ToFlat32 +TMPL_BEGIN_TEXT + + +;; +; Wrapper around the Bs3SelFar32ToFlat32 C function that doesn't +; clobber any registers nor require 20h stack scratch area (64-bit). +; +; @uses Only return registers (ax:dx, eax, eax) +; @remarks No 20h scratch space required in 64-bit mode. +; +BS3_PROC_BEGIN_CMN Bs3SelFar32ToFlat32NoClobber, BS3_PBC_NEAR ; Far stub generated by the makefile. + push xBP + mov xBP, xSP + +%if TMPL_BITS == 16 + push bx + push cx + push es + + push word [xBP + xCB + cbCurRetAddr + 4] ; uSel + push word [xBP + xCB + cbCurRetAddr + 2] ; high off + push word [xBP + xCB + cbCurRetAddr] ; low off + call Bs3SelFar32ToFlat32 + add sp, 6 + + pop es + pop cx + pop bx +%else + push xDX + push xCX + %if TMPL_BITS == 32 + push es + push fs + push gs + + push dword [xBP + xCB + cbCurRetAddr + 4] ; uSel + push dword [xBP + xCB + cbCurRetAddr] ; off + call Bs3SelFar32ToFlat32 + add esp, 8 + + pop gs + pop fs + pop es + %else + push r8 + push r9 + push r10 + push r11 + sub rsp, 20h + + call Bs3SelFar32ToFlat32 ; Just pass ECX and DX along as-is. + + add rsp, 20h + pop r11 + pop r10 + pop r9 + pop r8 + %endif + pop xCX + pop xDX +%endif + + pop xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3SelFar32ToFlat32NoClobber + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFlatCodeToProtFar16.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFlatCodeToProtFar16.asm new file mode 100644 index 00000000..e7734dcb --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFlatCodeToProtFar16.asm @@ -0,0 +1,128 @@ +; $Id: bs3-cmn-SelFlatCodeToProtFar16.asm $ +;; @file +; BS3Kit - Bs3SelFlatCodeToProtFar16. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_EXTERN_CMN Bs3SelFlatCodeToRealMode +BS3_EXTERN_CMN Bs3SelRealModeCodeToProtMode +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO(uint32_t, Bs3SelRealModeCodeToProtMode,(uint32_t uFlatAddr), false); +; +; @uses Only return registers (ax:dx, eax, eax) +; +BS3_PROC_BEGIN_CMN Bs3SelFlatCodeToProtFar16, BS3_PBC_NEAR + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + + ; + ; Call Bs3SelFlatCodeToRealMode and then Bs3SelRealModeCodeToProtMode. + ; This avoid some code duplication. + ; +%if TMPL_BITS == 16 + push word [xBP + xCB + cbCurRetAddr + 2] + push word [xBP + xCB + cbCurRetAddr] + call Bs3SelFlatCodeToRealMode + add sp, 4h + + push ax ; save the offset as it will be the same. + + push dx + call Bs3SelRealModeCodeToProtMode + add sp, 2h + + mov dx, ax ; The protected mode selector. + pop ax ; The offset. + +%elif TMPL_BITS == 32 + push dword [xBP + xCB + cbCurRetAddr] + call Bs3SelFlatCodeToRealMode + add esp, 4h + + push eax ; save the result. + + shr eax, 16 + push eax + call Bs3SelRealModeCodeToProtMode + add esp, 4h + + mov [esp + 2], ax ; Update the selector before popping the result. + pop eax + +%elif TMPL_BITS == 64 + push xCX ; Preserve RCX to make the behaviour uniform. + sub xSP, 28h ; 20h bytes of calling convention scratch and 8 byte for saving the result. + + mov ecx, [xBP + xCB + cbCurRetAddr] ; move straight to parameter 0 register. + call Bs3SelFlatCodeToRealMode + + mov [xBP - xCB*2], eax ; Save the result. + + shr eax, 16 + mov ecx, eax ; Move straight to parameter 0 register. + call Bs3SelRealModeCodeToProtMode + + shl eax, 16 ; Shift prot mode selector into result position. + mov ax, [xBP - xCB*2] ; The segment offset from the previous call. + + add xSP, 28h + pop xCX +%else + %error "TMPL_BITS=" TMPL_BITS "!" +%endif + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3SelFlatCodeToProtFar16 + + +; +; We may be using the near code in some critical code paths, so don't +; penalize it. +; +BS3_CMN_FAR_STUB Bs3SelFlatCodeToProtFar16, 4 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFlatCodeToRealMode.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFlatCodeToRealMode.asm new file mode 100644 index 00000000..f88d9d46 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFlatCodeToRealMode.asm @@ -0,0 +1,163 @@ +; $Id: bs3-cmn-SelFlatCodeToRealMode.asm $ +;; @file +; BS3Kit - Bs3SelFlatCodeToRealMode. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* Global Variables * +;********************************************************************************************************************************* +BS3_EXTERN_DATA16 Bs3RmText16_EndOfSegment +BS3_EXTERN_DATA16 Bs3X0Text16_EndOfSegment +BS3_EXTERN_DATA16 Bs3X1Text16_EndOfSegment + + +; +; Make sure we can get at all the segments. +; +BS3_BEGIN_TEXT16 +BS3_BEGIN_RMTEXT16 +BS3_BEGIN_X0TEXT16 +BS3_BEGIN_X1TEXT16 +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO(uint32_t, Bs3SelRealModeCodeToProtMode,(uint32_t uFlatAddr), false); +; +; @uses Only return registers (ax:dx, eax, eax) +; +BS3_PROC_BEGIN_CMN Bs3SelFlatCodeToRealMode, BS3_PBC_NEAR + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push xCX + push xBX +%if TMPL_BITS != 16 + push xDX +%endif + + ; + ; Load the real mode frame number into DX so we can compare with the + ; segment frame numbers fixed up by the linker. + ; + ; Imagine: FlatAddr = 0x054321 + ; + mov dx, [xBP + xCB + cbCurRetAddr + 1] ; dx = 0x0543 + mov al, [xBP + xCB + cbCurRetAddr + 0] ; al = 0x21 + mov cl,4 + shl dx, 4 ; dx = 0x5430 + shr al, 4 ; al = 0x02 + or dl, al ; dx = 0x5432 + + mov ax, dx + sub ax, CGROUP16 + cmp ax, 1000h + jb .bs3text16 + + mov ax, dx + sub ax, BS3GROUPRMTEXT16 + mov bx, Bs3RmText16_EndOfSegment wrt BS3GROUPRMTEXT16 + add bx, 15 + shr bx, cl + cmp ax, bx + jb .bs3rmtext16 + + mov ax, dx + sub ax, BS3GROUPX0TEXT16 + mov bx, Bs3X0Text16_EndOfSegment wrt BS3GROUPX0TEXT16 + add bx, 15 + shr bx, cl + cmp ax, bx + jb .bs3x0text16 + + mov ax, dx + sub ax, BS3GROUPX1TEXT16 + mov bx, Bs3X1Text16_EndOfSegment wrt BS3GROUPX1TEXT16 + add bx, 15 + shr bx, cl + cmp ax, bx + jb .bs3x1text16 + + extern BS3_CMN_NM(Bs3Panic) + call BS3_CMN_NM(Bs3Panic) + + ; + ; Load the real-mode frame into DX and calc the offset in AX. + ; +.bs3x1text16: + mov dx, BS3GROUPX1TEXT16 + jmp .calc_return +.bs3x0text16: + mov dx, BS3GROUPX0TEXT16 + jmp .calc_return +.bs3rmtext16: + mov dx, BS3GROUPRMTEXT16 + jmp .calc_return +.bs3text16: + mov dx, CGROUP16 +.calc_return: + ; Convert the real-mode frame into the low 16-bit base (BX). + mov bx, dx + shl bx, cl + ; Subtract the 16-bit base from the flat address. (No need to consider + ; the top half on either side.) + mov ax, [xBP + xCB + cbCurRetAddr + 0] + sub ax, bx +%if TMPL_BITS != 16 + ; Got a single 32-bit return register here. + shl edx, 16 + mov dx, ax + mov eax, edx + pop xDX +%endif + pop xBX + pop xCX + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3SelFlatCodeToRealMode + +; +; We may be using the near code in some critical code paths, so don't +; penalize it. +; +BS3_CMN_FAR_STUB Bs3SelFlatCodeToRealMode, 4 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFlatDataToProtFar16.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFlatDataToProtFar16.asm new file mode 100644 index 00000000..6869247b --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFlatDataToProtFar16.asm @@ -0,0 +1,142 @@ +; $Id: bs3-cmn-SelFlatDataToProtFar16.asm $ +;; @file +; BS3Kit - Bs3SelFlatDataToProtFar16. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +%ifdef BS3_STRICT +BS3_EXTERN_CMN Bs3Panic +%endif + +TMPL_BEGIN_TEXT +%if TMPL_BITS == 16 +CPU 8086 +%endif + + +;; +; @cproto BS3_CMN_PROTO_NOSB(uint32_t, Bs3SelFlatDataToProtFar16,(uint32_t uFlatAddr)); +; +; @uses Only return registers (ax:dx, eax, eax) +; @remarks No 20h scratch area requirements. +; +BS3_PROC_BEGIN_CMN Bs3SelFlatDataToProtFar16, BS3_PBC_NEAR ; Far stub generated by the makefile/bs3kit.h. + push xBP + mov xBP, xSP + + ; + ; Check if we can use the protected mode stack or data selector. + ; The latter ensures the usability of this function for setting SS. + ; +%if TMPL_BITS == 16 + mov ax, [xBP + xCB + cbCurRetAddr] + mov dx, [xBP + xCB + cbCurRetAddr + 2] + test dx, dx + jnz .not_stack + mov dx, BS3_SEL_R0_SS16 +%else +TNOT64 mov eax, [xBP + xCB + cbCurRetAddr] +TONLY64 mov eax, ecx + test eax, 0ffff0000h + jnz .not_stack + or eax, BS3_SEL_R0_SS16 << 16 +%endif + jmp .return + +.not_stack: +%if TMPL_BITS == 16 + sub ax, BS3_ADDR_BS3DATA16 & 0xffff + sbb dx, BS3_ADDR_BS3DATA16 >> 16 + jnz .do_tiled + mov dx, BS3_SEL_R0_DS16 +%else + sub eax, BS3_ADDR_BS3DATA16 + test eax, 0ffff0000h + jnz .do_tiled + or eax, BS3_SEL_R0_DS16 << 16 +%endif + jmp .return + + ; + ; Just translate the address to tiled. + ; +.do_tiled: +%if TMPL_BITS == 16 + ; Convert upper 16-bit to a tiled selector. + mov ax, cx ; save cx + mov dx, [xBP + xCB + cbCurRetAddr + 2] + %ifdef BS3_STRICT + cmp dx, BS3_SEL_TILED_AREA_SIZE >> 16 + jb .address_ok + call Bs3Panic +.address_ok: + %endif + mov cl, X86_SEL_SHIFT + shl dx, cl + add dx, BS3_SEL_TILED + mov cx, ax ; restore cx + + ; Load segment offset and return. + mov ax, [xBP + xCB + cbCurRetAddr] + +%else + ; Convert upper 16-bit to tiled selector. +TNOT64 mov eax, [xBP + xCB + cbCurRetAddr] +TONLY64 mov rax, rcx + %ifdef BS3_STRICT + cmp xAX, BS3_SEL_TILED_AREA_SIZE + jb .address_ok + call Bs3Panic +.address_ok: + %endif + ror eax, 16 + shl ax, X86_SEL_SHIFT + add ax, BS3_SEL_TILED + rol eax, 16 +%endif + +.return: + pop xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3SelFlatDataToProtFar16 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFlatDataToRealMode.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFlatDataToRealMode.asm new file mode 100644 index 00000000..cb142e80 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFlatDataToRealMode.asm @@ -0,0 +1,104 @@ +; $Id: bs3-cmn-SelFlatDataToRealMode.asm $ +;; @file +; BS3Kit - Bs3SelFlatDataToRealMode +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +%ifdef BS3_STRICT +BS3_EXTERN_CMN Bs3Panic +%endif +TMPL_BEGIN_TEXT +%if TMPL_BITS == 16 +CPU 8086 +%endif + + +;; +; @cproto BS3_CMN_PROTO_NOSB(uint32_t, Bs3SelFlatDataToRealMode,(uint32_t uFlatAddr)); +; +; @uses Only return registers (ax:dx, eax, eax) +; @remarks No 20h scratch area requirements. +; +BS3_PROC_BEGIN_CMN Bs3SelFlatDataToRealMode, BS3_PBC_NEAR ; Far stub generated by the makefile/bs3kit.h. + push xBP + mov xBP, xSP + + ; + ; Take the simplest approach possible (64KB tiled). + ; +%if TMPL_BITS == 16 + mov ax, cx ; save cx + mov dx, [xBP + xCB + cbCurRetAddr + 2] + %ifdef BS3_STRICT + cmp dx, _1M >> 16 + jb .address_ok + call Bs3Panic +.address_ok: + %endif + mov cl, 12 + shl dx, cl + mov ax, cx ; restore cx + + mov ax, [xBP + xCB + cbCurRetAddr] + +%else + %if TMPL_BITS == 32 + mov eax, [xBP + xCB + cbCurRetAddr] + %else + mov rax, rcx + %endif + %ifdef BS3_STRICT + cmp xAX, _1M + jb .address_ok + call Bs3Panic +.address_ok: + %endif + ror eax, 16 + shl ax, 12 + rol eax, 16 +%endif + + pop xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3SelFlatDataToRealMode + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelLnkPtrToCurPtr.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelLnkPtrToCurPtr.c new file mode 100644 index 00000000..add55863 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelLnkPtrToCurPtr.c @@ -0,0 +1,51 @@ +/* $Id: bs3-cmn-SelLnkPtrToCurPtr.c $ */ +/** @file + * BS3Kit - Bs3SelLnkPtrToCurPtr + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit-template-header.h" + + +#undef Bs3SelLnkPtrToCurPtr +BS3_CMN_DEF(void BS3_FAR *, Bs3SelLnkPtrToCurPtr,(void BS3_FAR *pvLnkPtr)) +{ +#if ARCH_BITS == 16 + if (BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode)) + return pvLnkPtr; + return (void BS3_FAR *)Bs3SelRealModeDataToProtFar16((uint32_t)pvLnkPtr); +#else + return pvLnkPtr; +#endif +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelLnkPtrToFlat.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelLnkPtrToFlat.c new file mode 100644 index 00000000..7de7db3e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelLnkPtrToFlat.c @@ -0,0 +1,49 @@ +/* $Id: bs3-cmn-SelLnkPtrToFlat.c $ */ +/** @file + * BS3Kit - Bs3SelLnkPtrToFlat + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit-template-header.h" + + +#undef Bs3SelLnkPtrToFlat +BS3_CMN_DEF(uint32_t, Bs3SelLnkPtrToFlat,(void BS3_FAR *pvLnkPtr)) +{ +#if ARCH_BITS == 16 + return Bs3SelRealModeDataToFlat((uint32_t)pvLnkPtr); +#else + return (uint32_t)(uintptr_t)pvLnkPtr; +#endif +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelProtFar16DataToFlat.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelProtFar16DataToFlat.asm new file mode 100644 index 00000000..5aea8c16 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelProtFar16DataToFlat.asm @@ -0,0 +1,100 @@ +; $Id: bs3-cmn-SelProtFar16DataToFlat.asm $ +;; @file +; BS3Kit - Bs3SelProtFar16DataToFlat. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_EXTERN_CMN Bs3SelFar32ToFlat32NoClobber +TMPL_BEGIN_TEXT +%if TMPL_BITS == 16 +CPU 8086 +%endif + + +;; +; @cproto BS3_CMN_PROTO_NOSB(uint32_t, Bs3SelProtFar16DataToFlat,(uint32_t uFar1616)); +; +; @uses Only return registers (ax:dx, eax, eax) +; @remarks No 20h scratch area requirements. +; +BS3_PROC_BEGIN_CMN Bs3SelProtFar16DataToFlat, BS3_PBC_NEAR ; Far stub generated by the makefile/bs3kit.h. + push xBP + mov xBP, xSP + + ; + ; Just call Bs3SelFar32ToFlat32NoClobber to do the job. + ; +%if TMPL_BITS == 16 + push word [xBP + xCB + cbCurRetAddr + 2] + xor ax, ax + push ax + push word [xBP + xCB + cbCurRetAddr] + call Bs3SelFar32ToFlat32NoClobber + add sp, 6 +%else + %if TMPL_BITS == 32 + movzx eax, word [xBP + xCB + cbCurRetAddr + 2] + push eax + movzx eax, word [xBP + xCB + cbCurRetAddr] + push eax + call Bs3SelFar32ToFlat32NoClobber + add esp, 8 + %else + push xDX + push xCX + + mov edx, ecx ; arg #2: selector + shr edx, 16 + movzx ecx, cx ; arg #1: offset + call Bs3SelFar32ToFlat32NoClobber + + pop xDX + pop xCX + %endif +%endif + +.return: + pop xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3SelProtFar16DataToFlat + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelProtFar16DataToRealMode.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelProtFar16DataToRealMode.asm new file mode 100644 index 00000000..b244adf8 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelProtFar16DataToRealMode.asm @@ -0,0 +1,157 @@ +; $Id: bs3-cmn-SelProtFar16DataToRealMode.asm $ +;; @file +; BS3Kit - Bs3SelProtFar16DataToRealMode. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_BEGIN_DATA16 ; For real mode segment value. +BS3_BEGIN_SYSTEM16 ; Ditto. +TMPL_BEGIN_TEXT +BS3_EXTERN_CMN Bs3SelFar32ToFlat32NoClobber + +TMPL_BEGIN_TEXT +%if TMPL_BITS == 16 +CPU 8086 +%endif + + +;; +; @cproto BS3_CMN_PROTO_NOSB(uint32_t, Bs3SelProtFar16DataToRealMode,(uint32_t uFar1616)); +; +; @uses Only return registers (ax:dx, eax, eax) +; @remarks No 20h scratch area requirements. +; +BS3_PROC_BEGIN_CMN Bs3SelProtFar16DataToRealMode, BS3_PBC_NEAR ; Far stub generated by the makefile/bs3kit.h. + push xBP + mov xBP, xSP + + ; + ; See if it's our default 16-bit ring-0 data, stack or system data segment. + ; +%if TMPL_BITS == 16 + mov ax, [xBP + xCB + cbCurRetAddr + 2] +%elif TMPL_BITS == 32 + movzx eax, word [xBP + xCB + cbCurRetAddr + 2] +%else + mov eax, ecx + shr eax, 16 +%endif + cmp ax, BS3_SEL_R0_SS16 + jne .not_stack + mov ax, 0 + +.quick_return: +%if TMPL_BITS == 16 + mov dx, ax + mov ax, [xBP + xCB + cbCurRetAddr] +%elif TMPL_BITS == 32 + shl eax, 16 + mov ax, word [xBP + xCB + cbCurRetAddr] +%else + shl eax, 16 + mov ax, cx +%endif + +.return: + pop xBP + BS3_HYBRID_RET + +.not_stack: + cmp ax, BS3_SEL_R0_DS16 + jne .not_dgroup + mov ax, BS3KIT_GRPNM_DATA16 + jmp .quick_return + +.not_dgroup: + cmp ax, BS3_SEL_SYSTEM16 + jne .not_system16 + mov ax, BS3SYSTEM16 + jmp .quick_return + + ; + ; Call worker function to convert it to flat and the do tiled + ; calculation from that. + ; +.not_system16: +%if TMPL_BITS == 16 + push word [xBP + xCB + cbCurRetAddr + 2] + xor ax, ax + push ax + push word [xBP + xCB + cbCurRetAddr] + call Bs3SelFar32ToFlat32NoClobber + add sp, 6 + + ; Convert upper 16-bit of the flat address to a tiled selector. + push cx + mov cl, X86_SEL_SHIFT + shl dx, cl + add dx, BS3_SEL_TILED + pop cx +%else + %if TMPL_BITS == 32 + push eax + movzx eax, word [xBP + xCB + cbCurRetAddr] + push eax + call Bs3SelFar32ToFlat32NoClobber + add esp, 8 + %else + push xDX + push xCX + + mov edx, eax ; arg #2: selector + movzx ecx, cx ; arg #1: offset + call Bs3SelFar32ToFlat32NoClobber + + pop xDX + pop xCX + %endif + + ; Convert upper 16-bit to tiled selector. + rol eax, 16 + shl ax, X86_SEL_SHIFT + add ax, BS3_SEL_TILED + ror eax, 16 +%endif + jmp .return +BS3_PROC_END_CMN Bs3SelProtFar16DataToRealMode + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelProtFar32ToFlat32.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelProtFar32ToFlat32.c new file mode 100644 index 00000000..7d31de27 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelProtFar32ToFlat32.c @@ -0,0 +1,55 @@ +/* $Id: bs3-cmn-SelProtFar32ToFlat32.c $ */ +/** @file + * BS3Kit - Bs3SelProtFar32ToFlat32 + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit-template-header.h" + + +#undef Bs3SelProtFar32ToFlat32 +BS3_CMN_DEF(uint32_t, Bs3SelProtFar32ToFlat32,(uint32_t off, uint16_t uSel)) +{ + uint32_t uRet; + PCX86DESC pEntry; + if (!(uSel & X86_SEL_LDT)) + pEntry = &Bs3Gdt[uSel >> X86_SEL_SHIFT]; + else + pEntry = &Bs3Ldt[uSel >> X86_SEL_SHIFT]; + uRet = pEntry->Gen.u16BaseLow; + uRet |= (uint32_t)pEntry->Gen.u8BaseHigh1 << 16; + uRet |= (uint32_t)pEntry->Gen.u8BaseHigh2 << 24; + uRet += off; + return uRet; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelProtModeCodeToRealMode.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelProtModeCodeToRealMode.asm new file mode 100644 index 00000000..6fd749bd --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelProtModeCodeToRealMode.asm @@ -0,0 +1,122 @@ +; $Id: bs3-cmn-SelProtModeCodeToRealMode.asm $ +;; @file +; BS3Kit - Bs3SelProtModeCodeToRealMode. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +; +; Make sure we can get at all the segments. +; +BS3_BEGIN_TEXT16 +BS3_BEGIN_RMTEXT16 +BS3_BEGIN_X0TEXT16 +BS3_BEGIN_X1TEXT16 +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO(uint16_t, Bs3SelProtModeCodeToRealMode,(uint16_t uRealSel), false); +; @uses ax (return register) +; +BS3_PROC_BEGIN_CMN Bs3SelProtModeCodeToRealMode, BS3_PBC_NEAR + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + + ; Load it and mask off the RPL. + mov ax, [xBP + xCB + cbCurRetAddr] + and ax, X86_SEL_MASK_OFF_RPL + + ; We're allowed to use the real-mode segment value. + cmp ax, CGROUP16 + je .bs3text16 + + ; Check for typical code segments. + cmp ax, BS3_SEL_R0_CS16 + je .bs3text16 + cmp ax, BS3_SEL_RMTEXT16_CS + je .bs3rmtext16 + cmp ax, BS3_SEL_X0TEXT16_CS + je .bs3x0text16 + cmp ax, BS3_SEL_X1TEXT16_CS + je .bs3x1text16 + + ; Check for less common BS3_SEL_R*_CS16_* values. + cmp ax, BS3_SEL_R0_FIRST + jb .panic + cmp ax, BS3_SEL_R3_FIRST + (1 << BS3_SEL_RING_SHIFT) + jae .panic + + ; Since the relevant bits now are the lower 8 ones, we skip the + ; AND AX, BS3_SEL_RING_SHIFT + ; ADD AX, BS3_SEL_R0_FIRST + ; bits and compare AL with lower 8-bit of the BS3_SEL_R0_CS16* values. +AssertCompile(BS3_SEL_RING_SHIFT == 8) + cmp al, BS3_SEL_R0_CS16 & 0xff + je .bs3text16 + cmp al, BS3_SEL_R0_CS16_EO & 0xff + je .bs3text16 + cmp ax, BS3_SEL_R0_CS16_CNF & 0xff + je .bs3text16 + cmp ax, BS3_SEL_R0_CS16_CNF_EO & 0xff + je .bs3text16 +.panic: + extern BS3_CMN_NM(Bs3Panic) + call BS3_CMN_NM(Bs3Panic) + jmp .return + +.bs3x1text16: + mov ax, BS3GROUPX1TEXT16 + jmp .return +.bs3x0text16: + mov ax, BS3GROUPX0TEXT16 + jmp .return +.bs3rmtext16: + mov ax, BS3GROUPRMTEXT16 + jmp .return +.bs3text16: + mov ax, CGROUP16 +.return: + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3SelProtModeCodeToRealMode + +; +; We may be using the near code in some critical code paths, so don't +; penalize it. +; +BS3_CMN_FAR_STUB Bs3SelProtModeCodeToRealMode, 2 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelRealModeCodeToProtMode.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelRealModeCodeToProtMode.asm new file mode 100644 index 00000000..c574901a --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelRealModeCodeToProtMode.asm @@ -0,0 +1,94 @@ +; $Id: bs3-cmn-SelRealModeCodeToProtMode.asm $ +;; @file +; BS3Kit - Bs3SelRealModeCodeToProtMode. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +; +; Make sure we can get at all the segments. +; +BS3_BEGIN_TEXT16 +BS3_BEGIN_RMTEXT16 +BS3_BEGIN_X0TEXT16 +BS3_BEGIN_X1TEXT16 +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_CMN_PROTO(uint16_t, Bs3SelRealModeCodeToProtMode,(uint16_t uRealSel), false); +; @uses ax (return register) +; +BS3_PROC_BEGIN_CMN Bs3SelRealModeCodeToProtMode, BS3_PBC_NEAR + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + + mov ax, [xBP + xCB + cbCurRetAddr] + cmp ax, CGROUP16 + je .bs3text16 + cmp ax, BS3GROUPRMTEXT16 + je .bs3rmtext16 + cmp ax, BS3GROUPX0TEXT16 + je .bs3x0text16 + cmp ax, BS3GROUPX1TEXT16 + je .bs3x1text16 + + extern BS3_CMN_NM(Bs3Panic) + call BS3_CMN_NM(Bs3Panic) + jmp .return + +.bs3x1text16: + mov ax, BS3_SEL_X1TEXT16_CS + jmp .return +.bs3x0text16: + mov ax, BS3_SEL_X0TEXT16_CS + jmp .return +.bs3rmtext16: + mov ax, BS3_SEL_RMTEXT16_CS + jmp .return +.bs3text16: + mov ax, BS3_SEL_R0_CS16 +.return: + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3SelRealModeCodeToProtMode + +; +; We may be using the near code in some critical code paths, so don't +; penalize it. +; +BS3_CMN_FAR_STUB Bs3SelRealModeCodeToProtMode, 2 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelRealModeDataToFlat.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelRealModeDataToFlat.asm new file mode 100644 index 00000000..0f0f0408 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelRealModeDataToFlat.asm @@ -0,0 +1,101 @@ +; $Id: bs3-cmn-SelRealModeDataToFlat.asm $ +;; @file +; BS3Kit - Bs3SelRealModeDataToFlat. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +TMPL_BEGIN_TEXT +%if TMPL_BITS == 16 +CPU 8086 +%endif + + +;; +; @cproto BS3_CMN_PROTO_NOSB(uint32_t, Bs3SelRealModeDataToFlat,(uint32_t uFar1616)); +; @cproto BS3_CMN_PROTO_NOSB(uint32_t, Bs3SelRealModeCodeToFlat,(uint32_t uFar1616)); +; +; @uses Only return registers (ax:dx, eax, eax); +; @remarks No 20h scratch area requirements. +; +BS3_PROC_BEGIN_CMN Bs3SelRealModeCodeToFlat, BS3_PBC_NEAR ; Far stub generated by the makefile/bs3kit.h. +BS3_PROC_BEGIN_CMN Bs3SelRealModeDataToFlat, BS3_PBC_NEAR ; Far stub generated by the makefile/bs3kit.h. + push xBP + mov xBP, xSP + + ; Calc flat address. +%if TMPL_BITS == 16 + push cx + mov dx, [xBP + xCB + cbCurRetAddr + 2] + mov ax, dx + mov cl, 12 + shr dx, cl + mov cl, 4 + shl ax, cl + add ax, [xBP + xCB + cbCurRetAddr] + adc dx, 0 + pop cx + +%elif TMPL_BITS == 32 + movzx eax, word [xBP + xCB + cbCurRetAddr + 2] + shl eax, 4 + add ax, [xBP + xCB + cbCurRetAddr] + jnc .return + add eax, 10000h + +%elif TMPL_BITS == 64 + mov eax, ecx + shr eax, 16 + shl eax, 4 + add ax, cx + jnc .return + add eax, 10000h + +%else + %error "TMPL_BITS!" +%endif + +.return: + pop xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3SelRealModeDataToFlat + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelRealModeDataToProtFar16.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelRealModeDataToProtFar16.asm new file mode 100644 index 00000000..b70a7894 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelRealModeDataToProtFar16.asm @@ -0,0 +1,151 @@ +; $Id: bs3-cmn-SelRealModeDataToProtFar16.asm $ +;; @file +; BS3Kit - Bs3SelRealModeDataToProtFar16. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_BEGIN_DATA16 ; For real mode segment value. +BS3_BEGIN_SYSTEM16 ; Ditto. + +TMPL_BEGIN_TEXT +%if TMPL_BITS == 16 +CPU 8086 +%endif + + +;; +; @cproto BS3_CMN_PROTO_NOSB(uint32_t, Bs3SelRealModeDataToProtFar16,(uint32_t uFar1616)); +; +; @uses Only return registers (ax:dx, eax, eax) +; @remarks No 20h scratch area requirements. +; +BS3_PROC_BEGIN_CMN Bs3SelRealModeDataToProtFar16, BS3_PBC_NEAR ; Far stub generated by the makefile/bs3kit.h. + push xBP + mov xBP, xSP + + ; + ; See if it's our default 16-bit data, stack or system data segment. + ; +%if TMPL_BITS == 16 + mov ax, [xBP + xCB + cbCurRetAddr + 2] +%elif TMPL_BITS == 32 + movzx eax, word [xBP + xCB + cbCurRetAddr + 2] +%else + mov eax, ecx + shr eax, 16 +%endif + cmp ax, 0 + jnz .not_stack + mov ax, BS3_SEL_R0_SS16 + +.quick_return: +%if TMPL_BITS == 16 + mov dx, ax + mov ax, [xBP + xCB + cbCurRetAddr] +%elif TMPL_BITS == 32 + shl eax, 16 + mov ax, word [xBP + xCB + cbCurRetAddr] +%else + shl eax, 16 + mov ax, cx +%endif + +.return: + pop xBP + BS3_HYBRID_RET + +.not_stack: + cmp ax, BS3KIT_GRPNM_DATA16 + jne .not_dgroup + mov ax, BS3_SEL_R0_DS16 + jmp .quick_return + +.not_dgroup: + cmp ax, BS3SYSTEM16 + jne .not_system16 + mov ax, BS3_SEL_SYSTEM16 + jmp .quick_return + + ; + ; Compute flat address and translate it to tiled. + ; +.not_system16: +%if TMPL_BITS == 16 + push cx + + ; Calc flat address. + mov dx, ax + mov cl, 12 + shr dx, cl + mov cl, 4 + shl ax, cl + add ax, [xBP + xCB + cbCurRetAddr] + adc dx, 0 + + ; Convert upper 16-bit to tiled selector. + mov cl, X86_SEL_SHIFT + shl dx, cl + add dx, BS3_SEL_TILED + + pop cx +%else + ; Calc flat address. + shl eax, 4 + %if TMPL_BITS == 32 + add ax, [xBP + xCB + cbCurRetAddr] + %else + add ax, cx + %endif + jnc .no_carry + add eax, 10000h +.no_carry: + + ; Convert upper 16-bit to tiled selector. + rol eax, 16 + shl ax, X86_SEL_SHIFT + add ax, BS3_SEL_TILED + ror eax, 16 +%endif + jmp .return +BS3_PROC_END_CMN Bs3SelRealModeDataToProtFar16 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetup16BitCode.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetup16BitCode.c new file mode 100644 index 00000000..5c53c98d --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetup16BitCode.c @@ -0,0 +1,61 @@ +/* $Id: bs3-cmn-SelSetup16BitCode.c $ */ +/** @file + * BS3Kit - Bs3SelSetup16BitCode + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <bs3kit.h> + + +#undef Bs3SelSetup16BitCode +BS3_CMN_DEF(void, Bs3SelSetup16BitCode,(X86DESC BS3_FAR *pDesc, uint32_t uBaseAddr, uint8_t bDpl)) +{ + pDesc->Gen.u16LimitLow = UINT16_C(0xffff); + pDesc->Gen.u16BaseLow = (uint16_t)uBaseAddr; + pDesc->Gen.u8BaseHigh1 = (uint8_t)(uBaseAddr >> 16); + pDesc->Gen.u4Type = X86_SEL_TYPE_ER_ACC; + pDesc->Gen.u1DescType = 1; /* data/code */ + pDesc->Gen.u2Dpl = bDpl & 3; + pDesc->Gen.u1Present = 1; + pDesc->Gen.u4LimitHigh = 0; + pDesc->Gen.u1Available = 0; + pDesc->Gen.u1Long = 0; + pDesc->Gen.u1DefBig = 0; + pDesc->Gen.u1Granularity = 0; + pDesc->Gen.u8BaseHigh2 = (uint8_t)(uBaseAddr >> 24); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetup16BitData.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetup16BitData.c new file mode 100644 index 00000000..611f5a1e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetup16BitData.c @@ -0,0 +1,61 @@ +/* $Id: bs3-cmn-SelSetup16BitData.c $ */ +/** @file + * BS3Kit - Bs3SelSetup16BitData + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <bs3kit.h> + + +#undef Bs3SelSetup16BitData +BS3_CMN_DEF(void, Bs3SelSetup16BitData,(X86DESC BS3_FAR *pDesc, uint32_t uBaseAddr)) +{ + pDesc->Gen.u16LimitLow = UINT16_C(0xffff); + pDesc->Gen.u16BaseLow = (uint16_t)uBaseAddr; + pDesc->Gen.u8BaseHigh1 = (uint8_t)(uBaseAddr >> 16); + pDesc->Gen.u4Type = X86_SEL_TYPE_RW_ACC; + pDesc->Gen.u1DescType = 1; /* data/code */ + pDesc->Gen.u2Dpl = 3; + pDesc->Gen.u1Present = 1; + pDesc->Gen.u4LimitHigh = 0; + pDesc->Gen.u1Available = 0; + pDesc->Gen.u1Long = 0; + pDesc->Gen.u1DefBig = 0; + pDesc->Gen.u1Granularity = 0; + pDesc->Gen.u8BaseHigh2 = (uint8_t)(uBaseAddr >> 24); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetup32BitCode.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetup32BitCode.c new file mode 100644 index 00000000..e3942d80 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetup32BitCode.c @@ -0,0 +1,62 @@ +/* $Id: bs3-cmn-SelSetup32BitCode.c $ */ +/** @file + * BS3Kit - Bs3SelSetup32BitCode + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <bs3kit.h> + + +#undef Bs3SelSetup32BitCode +BS3_CMN_DEF(void, Bs3SelSetup32BitCode,(X86DESC BS3_FAR *pDesc, uint32_t uBaseAddr, uint32_t uLimit, uint8_t bDpl)) +{ + uint8_t const cLimitShift = uLimit <= UINT32_C(0xfffff) ? 0 : 12; + pDesc->Gen.u16LimitLow = (uint16_t)(uLimit >> cLimitShift); + pDesc->Gen.u16BaseLow = (uint16_t)uBaseAddr; + pDesc->Gen.u8BaseHigh1 = (uint8_t)(uBaseAddr >> 16); + pDesc->Gen.u4Type = X86_SEL_TYPE_ER_ACC; + pDesc->Gen.u1DescType = 1; /* data/code */ + pDesc->Gen.u2Dpl = bDpl & 3; + pDesc->Gen.u1Present = 1; + pDesc->Gen.u4LimitHigh = (unsigned)(uLimit >> (16 + cLimitShift)); + pDesc->Gen.u1Available = 0; + pDesc->Gen.u1Long = 0; + pDesc->Gen.u1DefBig = 1; + pDesc->Gen.u1Granularity = cLimitShift != 0; + pDesc->Gen.u8BaseHigh2 = (uint8_t)(uBaseAddr >> 24); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetupGate.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetupGate.c new file mode 100644 index 00000000..99cc3581 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetupGate.c @@ -0,0 +1,61 @@ +/* $Id: bs3-cmn-SelSetupGate.c $ */ +/** @file + * BS3Kit - Bs3SelSetupGate + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3SelSetupGate +BS3_CMN_DEF(void, Bs3SelSetupGate,(X86DESC BS3_FAR *pDesc, uint8_t bType, uint8_t bDpl, + uint16_t uSel, uint32_t off, uint8_t cParams)) +{ + BS3_ASSERT(bDpl <= 3); + BS3_ASSERT(bType <= 15); + BS3_ASSERT(cParams <= 15); + pDesc->Gate.u16OffsetLow = (uint16_t)off; + pDesc->Gate.u16OffsetHigh = (uint16_t)(off >> 16); + pDesc->Gate.u16Sel = uSel; + pDesc->Gate.u5ParmCount = cParams; + pDesc->Gate.u4Type = bType; + pDesc->Gate.u2Dpl = bDpl; + pDesc->Gate.u3Reserved = 0; + pDesc->Gate.u1DescType = 0; /* system */ + pDesc->Gate.u1Present = 1; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetupGate64.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetupGate64.c new file mode 100644 index 00000000..b2c4927e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetupGate64.c @@ -0,0 +1,61 @@ +/* $Id: bs3-cmn-SelSetupGate64.c $ */ +/** @file + * BS3Kit - Bs3SelSetupGate64 + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3SelSetupGate64 +BS3_CMN_DEF(void, Bs3SelSetupGate64,(X86DESC BS3_FAR *pDescPair, uint8_t bType, uint8_t bDpl, uint16_t uSel, uint64_t off)) +{ + BS3_ASSERT(bDpl <= 3); + BS3_ASSERT(bType <= 15); + pDescPair[0].Gate.u16OffsetLow = (uint16_t)off; + pDescPair[0].Gate.u16OffsetHigh = (uint16_t)(off >> 16); + pDescPair[0].Gate.u16Sel = uSel; + pDescPair[0].Gate.u5ParmCount = 0; + pDescPair[0].Gate.u4Type = bType; + pDescPair[0].Gate.u2Dpl = bDpl; + pDescPair[0].Gate.u3Reserved = 0; + pDescPair[0].Gate.u1DescType = 0; /* system */ + pDescPair[0].Gate.u1Present = 1; + pDescPair[1].au32[0] = (uint32_t)(off >> 32); + pDescPair[1].au32[1] = 0; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Shutdown.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Shutdown.asm new file mode 100644 index 00000000..fbe82287 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Shutdown.asm @@ -0,0 +1,63 @@ +; $Id: bs3-cmn-Shutdown.asm $ +;; @file +; BS3Kit - Bs3Shutdown +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" +%include "VBox/bios.mac" + +BS3_EXTERN_CMN Bs3Panic + +BS3_PROC_BEGIN_CMN Bs3Shutdown, BS3_PBC_HYBRID_0_ARGS + cli +%ifdef TMPL_16BIT + mov ax, cs + mov ds, ax +%endif + mov bl, 64 + mov dx, VBOX_BIOS_SHUTDOWN_PORT + mov ax, VBOX_BIOS_OLD_SHUTDOWN_PORT +.retry: + mov ecx, 8 + mov esi, .s_szShutdown + rep outsb + xchg ax, dx ; alternate between the new (VBox) and old (Bochs) ports. + dec bl + jnz .retry + ; Shutdown failed! + jmp Bs3Panic +.s_szShutdown: + db 'Shutdown', 0 +BS3_PROC_END_CMN Bs3Shutdown + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabAlloc.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabAlloc.c new file mode 100644 index 00000000..12e87e4f --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabAlloc.c @@ -0,0 +1,64 @@ +/* $Id: bs3-cmn-SlabAlloc.c $ */ +/** @file + * BS3Kit - Bs3SlabAlloc + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include <iprt/asm.h> + + +#undef Bs3SlabAlloc +BS3_CMN_DEF(void BS3_FAR *, Bs3SlabAlloc,(PBS3SLABCTL pSlabCtl)) +{ + if (pSlabCtl->cFreeChunks) + { + int32_t iBit = ASMBitFirstClear(&pSlabCtl->bmAllocated, pSlabCtl->cChunks); + if (iBit >= 0) + { + BS3_XPTR_AUTO(void, pvRet); + ASMBitSet(&pSlabCtl->bmAllocated, iBit); + pSlabCtl->cFreeChunks -= 1; + + BS3_XPTR_SET_FLAT(void, pvRet, + BS3_XPTR_GET_FLAT(uint8_t, pSlabCtl->pbStart) + ((uint32_t)iBit << pSlabCtl->cChunkShift)); + return BS3_XPTR_GET(void, pvRet); + } + } + return NULL; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabAllocEx.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabAllocEx.c new file mode 100644 index 00000000..a3354185 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabAllocEx.c @@ -0,0 +1,111 @@ +/* $Id: bs3-cmn-SlabAllocEx.c $ */ +/** @file + * BS3Kit - Bs3SlabAllocEx + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include <iprt/asm.h> + + +#undef Bs3SlabAllocEx +BS3_CMN_DEF(void BS3_FAR *, Bs3SlabAllocEx,(PBS3SLABCTL pSlabCtl, uint16_t cChunks, uint16_t fFlags)) +{ + BS3_ASSERT(cChunks > 0); + if (pSlabCtl->cFreeChunks >= cChunks) + { + int32_t iBit = ASMBitFirstClear(&pSlabCtl->bmAllocated, pSlabCtl->cChunks); + if (iBit >= 0) + { + BS3_ASSERT(!ASMBitTest(&pSlabCtl->bmAllocated, iBit)); + + while ((uint32_t)iBit + cChunks <= pSlabCtl->cChunks) + { + /* Check that we've got the requested number of free chunks here. */ + uint16_t i; + for (i = 1; i < cChunks; i++) + if (ASMBitTest(&pSlabCtl->bmAllocated, iBit + i)) + break; + if (i == cChunks) + { + /* Check if the chunks are all in the same tiled segment. */ + BS3_XPTR_AUTO(void, pvRet); + BS3_XPTR_SET_FLAT(void, pvRet, + BS3_XPTR_GET_FLAT(uint8_t, pSlabCtl->pbStart) + ((uint32_t)iBit << pSlabCtl->cChunkShift)); + if ( !(fFlags & BS3_SLAB_ALLOC_F_SAME_TILE) + || (BS3_XPTR_GET_FLAT(void, pvRet) >> 16) + == ((BS3_XPTR_GET_FLAT(void, pvRet) + ((uint32_t)cChunks << pSlabCtl->cChunkShift) - 1) >> 16) ) + { + /* Complete the allocation. */ + void *fpRet; + for (i = 0; i < cChunks; i++) + ASMBitSet(&pSlabCtl->bmAllocated, iBit + i); + pSlabCtl->cFreeChunks -= cChunks; + fpRet = BS3_XPTR_GET(void, pvRet); +#if ARCH_BITS == 16 + BS3_ASSERT(fpRet != NULL); +#endif + return fpRet; + } + + /* + * We're crossing a tiled segment boundrary. + * Skip to the start of the next segment and retry there. + * (We already know that the first chunk in the next tiled + * segment is free, otherwise we wouldn't have a crossing.) + */ + BS3_ASSERT(((uint32_t)cChunks << pSlabCtl->cChunkShift) <= _64K); + i = BS3_XPTR_GET_FLAT_LOW(void, pvRet); + i = UINT16_C(0) - i; + i >>= pSlabCtl->cChunkShift; + iBit += i; + } + else + { + /* + * Continue searching. + */ + iBit = ASMBitNextClear(&pSlabCtl->bmAllocated, pSlabCtl->cChunks, iBit + i); + if (iBit < 0) + break; + } + } + } + } + return NULL; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabFree.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabFree.c new file mode 100644 index 00000000..730de635 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabFree.c @@ -0,0 +1,69 @@ +/* $Id: bs3-cmn-SlabFree.c $ */ +/** @file + * BS3Kit - Bs3SlabFree + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include <iprt/asm.h> + + +#undef Bs3SlabFree +BS3_CMN_DEF(uint16_t, Bs3SlabFree,(PBS3SLABCTL pSlabCtl, uint32_t uFlatChunkPtr, uint16_t cChunks)) +{ + uint16_t cFreed = 0; + BS3_ASSERT(cChunks > 0); + if (cChunks > 0) + { + uint16_t iChunk = (uint16_t)((uFlatChunkPtr - BS3_XPTR_GET_FLAT(uint8_t, pSlabCtl->pbStart)) >> pSlabCtl->cChunkShift); + BS3_ASSERT(iChunk < pSlabCtl->cChunks); + BS3_ASSERT(iChunk + cChunks <= pSlabCtl->cChunks); + + do + { + if (ASMBitTestAndClear(&pSlabCtl->bmAllocated, iChunk)) + cFreed++; + else + BS3_ASSERT(0); + iChunk++; + } while (--cChunks > 0); + + pSlabCtl->cFreeChunks += cFreed; + } + return cFreed; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabInit.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabInit.c new file mode 100644 index 00000000..4d50ee4c --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabInit.c @@ -0,0 +1,72 @@ +/* $Id: bs3-cmn-SlabInit.c $ */ +/** @file + * BS3Kit - Bs3SlabInit + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include <iprt/asm.h> + + +#undef Bs3SlabInit +BS3_CMN_DEF(void, Bs3SlabInit,(PBS3SLABCTL pSlabCtl, size_t cbSlabCtl, uint32_t uFlatSlabPtr, uint32_t cbSlab, uint16_t cbChunk)) +{ + uint16_t cBits; + BS3_ASSERT(RT_IS_POWER_OF_TWO(cbChunk)); + BS3_ASSERT(cbSlab >= cbChunk * 4); + BS3_ASSERT(!(uFlatSlabPtr & (cbChunk - 1))); + + BS3_XPTR_SET_FLAT(BS3SLABCTL, pSlabCtl->pNext, 0); + BS3_XPTR_SET_FLAT(BS3SLABCTL, pSlabCtl->pHead, 0); + BS3_XPTR_SET_FLAT(BS3SLABCTL, pSlabCtl->pbStart, uFlatSlabPtr); + pSlabCtl->cbChunk = cbChunk; + pSlabCtl->cChunkShift = ASMBitFirstSetU16(cbChunk) - 1; + pSlabCtl->cChunks = cbSlab >> pSlabCtl->cChunkShift; + pSlabCtl->cFreeChunks = pSlabCtl->cChunks; + cBits = RT_ALIGN_T(pSlabCtl->cChunks, 32, uint16_t); + BS3_ASSERT(cbSlabCtl >= RT_UOFFSETOF_DYN(BS3SLABCTL, bmAllocated[cBits >> 3])); + Bs3MemZero(&pSlabCtl->bmAllocated, cBits >> 3); + + /* Mark excess bitmap padding bits as allocated. */ + if (cBits != pSlabCtl->cChunks) + { + uint16_t iBit; + for (iBit = pSlabCtl->cChunks; iBit < cBits; iBit++) + ASMBitSet(pSlabCtl->bmAllocated, iBit); + } +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListAdd.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListAdd.c new file mode 100644 index 00000000..ba881526 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListAdd.c @@ -0,0 +1,53 @@ +/* $Id: bs3-cmn-SlabListAdd.c $ */ +/** @file + * BS3Kit - Bs3SlabListAdd + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit-template-header.h" + + +#undef Bs3SlabListAdd +BS3_CMN_DEF(void, Bs3SlabListAdd,(PBS3SLABHEAD pHead, PBS3SLABCTL pSlabCtl)) +{ + BS3_ASSERT(pHead->cbChunk == pSlabCtl->cbChunk); + BS3_ASSERT(BS3_XPTR_IS_NULL(BS3SLABHEAD, pSlabCtl->pNext)); + + BS3_XPTR_SET_FLAT(BS3SLABCTL, pSlabCtl->pNext, BS3_XPTR_GET_FLAT(BS3SLABCTL, pHead->pFirst)); + BS3_XPTR_SET(BS3SLABCTL, pHead->pFirst, pSlabCtl); + + pHead->cSlabs += 1; + pHead->cChunks += pSlabCtl->cChunks; + pHead->cFreeChunks += pSlabCtl->cFreeChunks; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListAlloc.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListAlloc.c new file mode 100644 index 00000000..3d1596c2 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListAlloc.c @@ -0,0 +1,67 @@ +/* $Id: bs3-cmn-SlabListAlloc.c $ */ +/** @file + * BS3Kit - Bs3SlabListAlloc + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3SlabListAlloc +BS3_CMN_DEF(void BS3_FAR *, Bs3SlabListAlloc,(PBS3SLABHEAD pHead)) +{ + if (pHead->cFreeChunks) + { + PBS3SLABCTL pCur; + for (pCur = BS3_XPTR_GET(BS3SLABCTL, pHead->pFirst); + pCur != NULL; + pCur = BS3_XPTR_GET(BS3SLABCTL, pCur->pNext)) + { + if (pCur->cFreeChunks) + { + void BS3_FAR *pvRet = Bs3SlabAlloc(pCur); + if (pvRet) + { + pHead->cFreeChunks -= 1; + return pvRet; + } + } + } + } + return NULL; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListAllocEx.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListAllocEx.c new file mode 100644 index 00000000..9f0eddd8 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListAllocEx.c @@ -0,0 +1,68 @@ +/* $Id: bs3-cmn-SlabListAllocEx.c $ */ +/** @file + * BS3Kit - Bs3SlabListAllocEx + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3SlabListAllocEx +BS3_CMN_DEF(void BS3_FAR *, Bs3SlabListAllocEx,(PBS3SLABHEAD pHead, uint16_t cChunks, uint16_t fFlags)) +{ + BS3_ASSERT(!(fFlags & ~BS3_SLAB_ALLOC_F_SAME_TILE)); + if (pHead->cFreeChunks >= cChunks) + { + PBS3SLABCTL pCur; + for (pCur = BS3_XPTR_GET(BS3SLABCTL, pHead->pFirst); + pCur != NULL; + pCur = BS3_XPTR_GET(BS3SLABCTL, pCur->pNext)) + { + if (pCur->cFreeChunks >= cChunks) + { + void BS3_FAR *pvRet = Bs3SlabAllocEx(pCur, cChunks, fFlags); + if (pvRet) + { + pHead->cFreeChunks -= cChunks; + return pvRet; + } + } + } + } + return NULL; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListFree.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListFree.c new file mode 100644 index 00000000..16bcc23d --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListFree.c @@ -0,0 +1,64 @@ +/* $Id: bs3-cmn-SlabListFree.c $ */ +/** @file + * BS3Kit - Bs3SlabListFree + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit-template-header.h" + + +#undef Bs3SlabListFree +BS3_CMN_DEF(void, Bs3SlabListFree,(PBS3SLABHEAD pHead, void BS3_FAR *pvChunks, uint16_t cChunks)) +{ + BS3_ASSERT(cChunks > 0); + if (cChunks > 0) + { + PBS3SLABCTL pCur; + BS3_XPTR_AUTO(void, pvFlatChunk); + BS3_XPTR_SET(void, pvFlatChunk, pvChunks); + + for (pCur = BS3_XPTR_GET(BS3SLABCTL, pHead->pFirst); + pCur != NULL; + pCur = BS3_XPTR_GET(BS3SLABCTL, pCur->pNext)) + { + if ( ((BS3_XPTR_GET_FLAT(void, pvFlatChunk) - BS3_XPTR_GET_FLAT(uint8_t, pCur->pbStart)) >> pCur->cChunkShift) + < pCur->cChunks) + { + pHead->cFreeChunks += Bs3SlabFree(pCur, BS3_XPTR_GET_FLAT(void, pvFlatChunk), cChunks); + return; + } + } + BS3_ASSERT(0); + } +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListInit.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListInit.c new file mode 100644 index 00000000..38c68b3f --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListInit.c @@ -0,0 +1,50 @@ +/* $Id: bs3-cmn-SlabListInit.c $ */ +/** @file + * BS3Kit - Bs3SlabListInit + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit-template-header.h" + + +#undef Bs3SlabListInit +BS3_CMN_DEF(void, Bs3SlabListInit,(PBS3SLABHEAD pHead, uint16_t cbChunk)) +{ + BS3_ASSERT(RT_IS_POWER_OF_TWO(cbChunk)); + BS3_XPTR_SET(struct BS3SLABCTL, pHead->pFirst, 0); + pHead->cbChunk = cbChunk; + pHead->cSlabs = 0; + pHead->cChunks = 0; + pHead->cFreeChunks = 0; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrCpy.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrCpy.c new file mode 100644 index 00000000..3da9e78b --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrCpy.c @@ -0,0 +1,51 @@ +/* $Id: bs3-cmn-StrCpy.c $ */ +/** @file + * BS3Kit - Bs3StrCpy + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit-template-header.h" + +#undef Bs3StrCpy +BS3_CMN_DEF(char BS3_FAR *, Bs3StrCpy,(char BS3_FAR *pszDst, const char BS3_FAR *pszSrc)) +{ + char BS3_FAR *pszRet = pszDst; + char ch; + do + { + ch = *pszSrc++; + *pszDst++ = ch; + } while (ch != '\0'); + return pszRet; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrFormatV.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrFormatV.c new file mode 100644 index 00000000..89d14a1d --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrFormatV.c @@ -0,0 +1,788 @@ +/* $Id: bs3-cmn-StrFormatV.c $ */ +/** @file + * BS3Kit - Bs3StrFormatV + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include <iprt/ctype.h> + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +#define STR_F_CAPITAL 0x0001 +#define STR_F_LEFT 0x0002 +#define STR_F_ZEROPAD 0x0004 +#define STR_F_SPECIAL 0x0008 +#define STR_F_VALSIGNED 0x0010 +#define STR_F_PLUS 0x0020 +#define STR_F_BLANK 0x0040 +#define STR_F_WIDTH 0x0080 +#define STR_F_PRECISION 0x0100 +#define STR_F_THOUSAND_SEP 0x0200 +#define STR_F_NEGATIVE 0x0400 /**< Used to indicated '-' must be printed. */ + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +/** Size of the temporary buffer. */ +#define BS3FMT_TMP_SIZE 64 + +/** + * BS3kit string format state. + */ +typedef struct BS3FMTSTATE +{ + /** The output function. */ + PFNBS3STRFORMATOUTPUT pfnOutput; + /** User argument for pfnOutput. */ + void BS3_FAR *pvUser; + + /** STR_F_XXX flags. */ + unsigned fFlags; + /** The width when STR_F_WIDTH is specific. */ + int cchWidth; + /** The width when STR_F_PRECISION is specific. */ + int cchPrecision; + /** The number format base. */ + unsigned uBase; + /** Temporary buffer. */ + char szTmp[BS3FMT_TMP_SIZE]; +} BS3FMTSTATE; +/** Pointer to a BS3Kit string formatter state. */ +typedef BS3FMTSTATE BS3_FAR *PBS3FMTSTATE; + + + +/********************************************************************************************************************************* +* Internal Functions * +*********************************************************************************************************************************/ +#if ARCH_BITS != 64 +static size_t bs3StrFormatU32(PBS3FMTSTATE pState, uint32_t uValue); +#endif + + + +/** + * Formats a number string. + * + * @returns Number of chars printed. + * @param pState The string formatter state. + * @param pszNumber The formatted number string. + * @param cchNumber The length of the number. + */ +static size_t bs3StrFormatNumberString(PBS3FMTSTATE pState, char const BS3_FAR *pszNumber, size_t cchNumber) +{ + /* + * Calc the length of the core number with prefixes. + */ + size_t cchActual = 0; + size_t cchRet = cchNumber; + + /* Accunt for sign char. */ + cchRet += !!(pState->fFlags & (STR_F_NEGATIVE | STR_F_PLUS | STR_F_BLANK)); + + /* Account for the hex prefix: '0x' or '0X' */ + if (pState->fFlags & STR_F_SPECIAL) + { + cchRet += 2; + BS3_ASSERT(pState->uBase == 16); + } + + /* Account for thousand separators (applied while printing). */ + if (pState->fFlags & STR_F_THOUSAND_SEP) + cchRet += (cchNumber - 1) / (pState->uBase == 10 ? 3 : 8); + + /* + * Do left blank padding. + */ + if ((pState->fFlags & (STR_F_ZEROPAD | STR_F_LEFT | STR_F_WIDTH)) == STR_F_WIDTH) + while (cchRet < pState->cchWidth) + { + cchActual += pState->pfnOutput(' ', pState->pvUser); + cchRet++; + } + + /* + * Sign indicator / space. + */ + if (pState->fFlags & (STR_F_NEGATIVE | STR_F_PLUS | STR_F_BLANK)) + { + char ch; + if (pState->fFlags & STR_F_NEGATIVE) + ch = '-'; + else if (pState->fFlags & STR_F_PLUS) + ch = '+'; + else + ch = ' '; + cchActual += pState->pfnOutput(ch, pState->pvUser); + } + + /* + * Hex prefix. + */ + if (pState->fFlags & STR_F_SPECIAL) + { + cchActual += pState->pfnOutput('0', pState->pvUser); + cchActual += pState->pfnOutput(!(pState->fFlags & STR_F_CAPITAL) ? 'x' : 'X', pState->pvUser); + } + + /* + * Zero padding. + */ + if (pState->fFlags & STR_F_ZEROPAD) + while (cchRet < pState->cchWidth) + { + cchActual += pState->pfnOutput('0', pState->pvUser); + cchRet++; + } + + /* + * Output the number. + */ + if ( !(pState->fFlags & STR_F_THOUSAND_SEP) + || cchNumber < 4) + while (cchNumber-- > 0) + cchActual += pState->pfnOutput(*pszNumber++, pState->pvUser); + else + { + char const chSep = pState->uBase == 10 ? ' ' : '\''; + unsigned const cchEvery = pState->uBase == 10 ? 3 : 8; + unsigned cchLeft = --cchNumber % cchEvery; + + cchActual += pState->pfnOutput(*pszNumber++, pState->pvUser); + while (cchNumber-- > 0) + { + if (cchLeft == 0) + { + cchActual += pState->pfnOutput(chSep, pState->pvUser); + cchLeft = cchEvery; + } + cchLeft--; + cchActual += pState->pfnOutput(*pszNumber++, pState->pvUser); + } + } + + /* + * Do right blank padding. + */ + if ((pState->fFlags & (STR_F_ZEROPAD | STR_F_LEFT | STR_F_WIDTH)) == (STR_F_WIDTH | STR_F_LEFT)) + while (cchRet < pState->cchWidth) + { + cchActual += pState->pfnOutput(' ', pState->pvUser); + cchRet++; + } + + return cchActual; +} + + +/** + * Format a 64-bit number. + * + * @returns Number of characters. + * @param pState The string formatter state. + * @param uValue The value. + */ +static size_t bs3StrFormatU64(PBS3FMTSTATE pState, uint64_t uValue) +{ +#if ARCH_BITS != 64 + /* Avoid 64-bit division by formatting 64-bit numbers as hex if they're higher than _4G. */ + if (pState->uBase == 10) + { + if (!(uValue >> 32)) /* uValue <= UINT32_MAX does not work, trouble with 64-bit compile time math! */ + return bs3StrFormatU32(pState, uValue); + pState->fFlags |= STR_F_SPECIAL; + pState->uBase = 16; + } +#endif + + { + const char BS3_FAR *pachDigits = !(pState->fFlags & STR_F_CAPITAL) ? g_achBs3HexDigits : g_achBs3HexDigitsUpper; + char BS3_FAR *psz = &pState->szTmp[BS3FMT_TMP_SIZE]; + + *--psz = '\0'; +#if ARCH_BITS == 64 + if (pState->uBase == 10) + { + do + { + *--psz = pachDigits[uValue % 10]; + uValue /= 10; + } while (uValue > 0); + } + else +#endif + { + BS3_ASSERT(pState->uBase == 16); + do + { + *--psz = pachDigits[uValue & 0xf]; + uValue >>= 4; + } while (uValue > 0); + } + return bs3StrFormatNumberString(pState, psz, &pState->szTmp[BS3FMT_TMP_SIZE - 1] - psz); + } +} + + +/** + * Format a 32-bit number. + * + * @returns Number of characters. + * @param pState The string formatter state. + * @param uValue The value. + */ +static size_t bs3StrFormatU32(PBS3FMTSTATE pState, uint32_t uValue) +{ +#if ARCH_BITS < 64 + const char BS3_FAR *pachDigits = !(pState->fFlags & STR_F_CAPITAL) ? g_achBs3HexDigits : g_achBs3HexDigitsUpper; + char BS3_FAR *psz = &pState->szTmp[BS3FMT_TMP_SIZE]; + + *--psz = '\0'; + if (pState->uBase == 10) + { + do + { + *--psz = pachDigits[uValue % 10]; + uValue /= 10; + } while (uValue > 0); + } + else + { + BS3_ASSERT(pState->uBase == 16); + do + { + *--psz = pachDigits[uValue & 0xf]; + uValue >>= 4; + } while (uValue > 0); + } + return bs3StrFormatNumberString(pState, psz, &pState->szTmp[BS3FMT_TMP_SIZE - 1] - psz); + +#else + /* We've got native 64-bit division, save space. */ + return bs3StrFormatU64(pState, uValue); +#endif +} + + +#if ARCH_BITS == 16 +/** + * Format a 16-bit number. + * + * @returns Number of characters. + * @param pState The string formatter state. + * @param uValue The value. + */ +static size_t bs3StrFormatU16(PBS3FMTSTATE pState, uint16_t uValue) +{ + if (pState->uBase == 10) + { + const char BS3_FAR *pachDigits = !(pState->fFlags & STR_F_CAPITAL) + ? g_achBs3HexDigits : g_achBs3HexDigitsUpper; + char BS3_FAR *psz = &pState->szTmp[BS3FMT_TMP_SIZE]; + + *--psz = '\0'; + do + { + *--psz = pachDigits[uValue % 10]; + uValue /= 10; + } while (uValue > 0); + return bs3StrFormatNumberString(pState, psz, &pState->szTmp[BS3FMT_TMP_SIZE - 1] - psz); + } + + /* + * 32-bit shifting is reasonably cheap and inlined, so combine with 32-bit. + */ + return bs3StrFormatU32(pState, uValue); +} +#endif + + +static size_t bs3StrFormatS64(PBS3FMTSTATE pState, int32_t iValue) +{ + if (iValue < 0) + { + iValue = -iValue; + pState->fFlags |= STR_F_NEGATIVE; + } + return bs3StrFormatU64(pState, iValue); +} + + +static size_t bs3StrFormatS32(PBS3FMTSTATE pState, int32_t iValue) +{ + if (iValue < 0) + { + iValue = -iValue; + pState->fFlags |= STR_F_NEGATIVE; + } + return bs3StrFormatU32(pState, iValue); +} + + +#if ARCH_BITS == 16 +static size_t bs3StrFormatS16(PBS3FMTSTATE pState, int16_t iValue) +{ + if (iValue < 0) + { + iValue = -iValue; + pState->fFlags |= STR_F_NEGATIVE; + } + return bs3StrFormatU16(pState, iValue); +} +#endif + + +#undef Bs3StrFormatV +BS3_CMN_DEF(size_t, Bs3StrFormatV,(const char BS3_FAR *pszFormat, va_list BS3_FAR va, + PFNBS3STRFORMATOUTPUT pfnOutput, void BS3_FAR *pvUser)) +{ + BS3FMTSTATE State; + size_t cchRet = 0; + char ch; +#if ARCH_BITS == 16 + typedef int SIZE_CHECK_TYPE1[sizeof(va) == 4 && sizeof(va[0]) == 4]; +#endif + + State.pfnOutput = pfnOutput; + State.pvUser = pvUser; + + while ((ch = *pszFormat++) != '\0') + { + char chArgSize; + + /* + * Deal with plain chars. + */ + if (ch != '%') + { + cchRet += State.pfnOutput(ch, State.pvUser); + continue; + } + + ch = *pszFormat++; + if (ch == '%') + { + cchRet += State.pfnOutput(ch, State.pvUser); + continue; + } + + /* + * Flags. + */ + State.fFlags = 0; + for (;;) + { + unsigned int fThis; + switch (ch) + { + default: fThis = 0; break; + case '#': fThis = STR_F_SPECIAL; break; + case '-': fThis = STR_F_LEFT; break; + case '+': fThis = STR_F_PLUS; break; + case ' ': fThis = STR_F_BLANK; break; + case '0': fThis = STR_F_ZEROPAD; break; + case '\'': fThis = STR_F_THOUSAND_SEP; break; + } + if (!fThis) + break; + State.fFlags |= fThis; + ch = *pszFormat++; + } + + /* + * Width. + */ + State.cchWidth = 0; + if (RT_C_IS_DIGIT(ch)) + { + do + { + State.cchWidth *= 10; + State.cchWidth += ch - '0'; + ch = *pszFormat++; + } while (RT_C_IS_DIGIT(ch)); + State.fFlags |= STR_F_WIDTH; + } + else if (ch == '*') + { + State.cchWidth = va_arg(va, int); + if (State.cchWidth < 0) + { + State.cchWidth = -State.cchWidth; + State.fFlags |= STR_F_LEFT; + } + State.fFlags |= STR_F_WIDTH; + ch = *pszFormat++; + } + + /* + * Precision + */ + State.cchPrecision = 0; + if (ch == '.') + { + ch = *pszFormat++; + if (RT_C_IS_DIGIT(ch)) + { + do + { + State.cchPrecision *= 10; + State.cchPrecision += ch - '0'; + ch = *pszFormat++; + } while (RT_C_IS_DIGIT(ch)); + State.fFlags |= STR_F_PRECISION; + } + else if (ch == '*') + { + State.cchPrecision = va_arg(va, int); + if (State.cchPrecision < 0) + State.cchPrecision = 0; + State.fFlags |= STR_F_PRECISION; + ch = *pszFormat++; + } + } + + /* + * Argument size. + */ + chArgSize = ch; + switch (ch) + { + default: + chArgSize = 0; + break; + + case 'z': + case 'L': + case 'j': + case 't': + ch = *pszFormat++; + break; + + case 'l': + ch = *pszFormat++; + if (ch == 'l') + { + chArgSize = 'L'; + ch = *pszFormat++; + } + break; + + case 'h': + ch = *pszFormat++; + if (ch == 'h') + { + chArgSize = 'H'; + ch = *pszFormat++; + } + break; + } + + /* + * The type. + */ + switch (ch) + { + /* + * Char + */ + case 'c': + { + char ch = va_arg(va, int /*char*/); + cchRet += State.pfnOutput(ch, State.pvUser); + break; + } + + /* + * String. + */ + case 's': + { + const char BS3_FAR *psz = va_arg(va, const char BS3_FAR *); + size_t cch; + if (psz != NULL) + cch = Bs3StrNLen(psz, State.fFlags & STR_F_PRECISION ? RT_ABS(State.cchPrecision) : ~(size_t)0); + else + { + psz = "<NULL>"; + cch = 6; + } + + if ((State.fFlags & (STR_F_LEFT | STR_F_WIDTH)) == STR_F_WIDTH) + while (--State.cchWidth >= cch) + cchRet += State.pfnOutput(' ', State.pvUser); + + while (cch-- > 0) + cchRet += State.pfnOutput(*psz++, State.pvUser); + + if ((State.fFlags & (STR_F_LEFT | STR_F_WIDTH)) == (STR_F_LEFT | STR_F_WIDTH)) + while (--State.cchWidth >= cch) + cchRet += State.pfnOutput(' ', State.pvUser); + break; + } + + /* + * Signed integers. + */ + case 'i': + case 'd': + State.fFlags &= ~STR_F_SPECIAL; + State.fFlags |= STR_F_VALSIGNED; + State.uBase = 10; + switch (chArgSize) + { + case 0: + case 'h': /* signed short should be promoted to int or be the same as int */ + case 'H': /* signed char should be promoted to int. */ + { + signed int iValue = va_arg(va, signed int); +#if ARCH_BITS == 16 + cchRet += bs3StrFormatS16(&State, iValue); +#else + cchRet += bs3StrFormatS32(&State, iValue); +#endif + break; + } + case 'l': + { + signed long lValue = va_arg(va, signed long); + if (sizeof(lValue) == 4) + cchRet += bs3StrFormatS32(&State, lValue); + else + cchRet += bs3StrFormatS64(&State, lValue); + break; + } + case 'L': + { + unsigned long long ullValue = va_arg(va, unsigned long long); + cchRet += bs3StrFormatS64(&State, ullValue); + break; + } + } + break; + + /* + * Unsigned integers. + */ + case 'X': + State.fFlags |= STR_F_CAPITAL; + case 'x': + case 'u': + { + if (ch == 'u') + { + State.uBase = 10; + State.fFlags &= ~(STR_F_PLUS | STR_F_BLANK | STR_F_SPECIAL); + } + else + { + State.uBase = 16; + State.fFlags &= ~(STR_F_PLUS | STR_F_BLANK); + } + switch (chArgSize) + { + case 0: + case 'h': /* unsigned short should be promoted to int or be the same as int */ + case 'H': /* unsigned char should be promoted to int. */ + { + unsigned int uValue = va_arg(va, unsigned int); +#if ARCH_BITS == 16 + cchRet += bs3StrFormatU16(&State, uValue); +#else + cchRet += bs3StrFormatU32(&State, uValue); +#endif + break; + } + case 'l': + { + unsigned long ulValue = va_arg(va, unsigned long); + if (sizeof(ulValue) == 4) + cchRet += bs3StrFormatU32(&State, ulValue); + else + cchRet += bs3StrFormatU64(&State, ulValue); + break; + } + case 'L': + { + unsigned long long ullValue = va_arg(va, unsigned long long); + cchRet += bs3StrFormatU64(&State, ullValue); + break; + } + } + break; + } + + /* + * Our stuff. + */ + case 'R': + { + ch = *pszFormat++; + switch (ch) + { + case 'I': + State.fFlags |= STR_F_VALSIGNED; + State.uBase &= ~STR_F_SPECIAL; + State.uBase = 10; + break; + case 'U': + State.fFlags &= ~(STR_F_PLUS | STR_F_BLANK | STR_F_SPECIAL); + State.uBase = 10; + break; + case 'X': + State.fFlags &= ~(STR_F_PLUS | STR_F_BLANK); + State.uBase = 16; + break; + case 'h': + ch = *pszFormat++; + if (ch == 'x') + { + /* Hex dumping. */ + uint8_t const BS3_FAR *pbHex = va_arg(va, uint8_t const BS3_FAR *); + if (State.cchPrecision < 0) + State.cchPrecision = 16; + ch = *pszFormat++; + if (ch == 's' || ch == 'd') + { + /* %Rhxd is currently implemented as %Rhxs. */ + while (State.cchPrecision-- > 0) + { + uint8_t b = *pbHex++; + State.pfnOutput(g_achBs3HexDigits[b >> 4], State.pvUser); + State.pfnOutput(g_achBs3HexDigits[b & 0x0f], State.pvUser); + if (State.cchPrecision) + State.pfnOutput(' ', State.pvUser); + } + } + } + State.uBase = 0; + break; + default: + State.uBase = 0; + break; + } + if (State.uBase) + { + ch = *pszFormat++; + switch (ch) + { +#if ARCH_BITS != 16 + case '3': + case '1': /* Will an unsigned 16-bit value always be promoted + to a 16-bit unsigned int. It certainly will be promoted to a 32-bit int. */ + pszFormat++; /* Assumes (1)'6' or (3)'2' */ +#else + case '1': + pszFormat++; /* Assumes (1)'6' */ +#endif + case '8': /* An unsigned 8-bit value should be promoted to int, which is at least 16-bit. */ + { + unsigned int uValue = va_arg(va, unsigned int); +#if ARCH_BITS == 16 + cchRet += bs3StrFormatU16(&State, uValue); +#else + cchRet += bs3StrFormatU32(&State, uValue); +#endif + break; + } +#if ARCH_BITS == 16 + case '3': + { + uint32_t uValue = va_arg(va, uint32_t); + pszFormat++; + cchRet += bs3StrFormatU32(&State, uValue); + break; + } +#endif + case '6': + { + uint64_t uValue = va_arg(va, uint64_t); + pszFormat++; + cchRet += bs3StrFormatU64(&State, uValue); + break; + } + } + } + break; + } + + /* + * Pointers. + */ + case 'P': + State.fFlags |= STR_F_CAPITAL; + RT_FALL_THRU(); + case 'p': + { + void BS3_FAR *pv = va_arg(va, void BS3_FAR *); + State.uBase = 16; + State.fFlags &= ~(STR_F_PLUS | STR_F_BLANK); +#if ARCH_BITS == 16 + State.fFlags |= STR_F_ZEROPAD; + State.cchWidth = State.fFlags & STR_F_SPECIAL ? 6: 4; + cchRet += bs3StrFormatU16(&State, BS3_FP_SEG(pv)); + cchRet += State.pfnOutput(':', State.pvUser); + cchRet += bs3StrFormatU16(&State, BS3_FP_OFF(pv)); +#elif ARCH_BITS == 32 + State.fFlags |= STR_F_SPECIAL | STR_F_ZEROPAD; + State.cchWidth = 10; + cchRet += bs3StrFormatU32(&State, (uintptr_t)pv); +#elif ARCH_BITS == 64 + State.fFlags |= STR_F_SPECIAL | STR_F_ZEROPAD | STR_F_THOUSAND_SEP; + State.cchWidth = 19; + cchRet += bs3StrFormatU64(&State, (uintptr_t)pv); +#else +# error "Undefined or invalid ARCH_BITS." +#endif + break; + } + + } + } + + /* + * Termination call. + */ + cchRet += State.pfnOutput(0, State.pvUser); + + return cchRet; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrLen.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrLen.c new file mode 100644 index 00000000..b188bf7c --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrLen.c @@ -0,0 +1,47 @@ +/* $Id: bs3-cmn-StrLen.c $ */ +/** @file + * BS3Kit - Bs3StrLen + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit-template-header.h" + +#undef Bs3StrLen +BS3_CMN_DEF(size_t, Bs3StrLen,(const char BS3_FAR *pszString)) +{ + size_t cch = 0; + while (pszString[cch] != '\0') + cch++; + return cch; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrNLen.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrNLen.c new file mode 100644 index 00000000..d52eedab --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrNLen.c @@ -0,0 +1,47 @@ +/* $Id: bs3-cmn-StrNLen.c $ */ +/** @file + * BS3Kit - Bs3StrNLen + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit-template-header.h" + +#undef Bs3StrNLen +BS3_CMN_DEF(size_t, Bs3StrNLen,(const char BS3_FAR *pszString, size_t cchMax)) +{ + size_t cch = 0; + while (cchMax-- > 0 && pszString[cch] != '\0') + cch++; + return cch; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrPrintf.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrPrintf.c new file mode 100644 index 00000000..8c2d9511 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrPrintf.c @@ -0,0 +1,105 @@ +/* $Id: bs3-cmn-StrPrintf.c $ */ +/** @file + * BS3Kit - Bs3StrPrintf, Bs3StrPrintfV + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include <iprt/ctype.h> + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +typedef struct BS3STRPRINTFSTATE +{ + /** Current buffer position. */ + char *pchBuf; + /** Number of bytes left in the buffer. */ + size_t cchLeft; +} BS3STRPRINTFSTATE; +typedef BS3STRPRINTFSTATE BS3_FAR *PBS3STRPRINTFSTATE; + + + +static BS3_DECL_CALLBACK(size_t) bs3StrPrintfFmtOutput(char ch, void BS3_FAR *pvUser) +{ + PBS3STRPRINTFSTATE pState = (PBS3STRPRINTFSTATE)pvUser; + if (ch) + { + /* Put to the buffer if there is place for this char and a terminator. */ + if (pState->cchLeft > 1) + { + pState->cchLeft--; + *pState->pchBuf++ = ch; + } + + /* Always return 1. */ + return 1; + } + + /* Terminate the string. */ + if (pState->cchLeft) + { + pState->cchLeft--; + *pState->pchBuf++ = '\0'; + } + return 0; +} + + +#undef Bs3StrPrintfV +BS3_CMN_DEF(size_t, Bs3StrPrintfV,(char BS3_FAR *pszBuf, size_t cchBuf, const char BS3_FAR *pszFormat, va_list BS3_FAR va)) +{ + BS3STRPRINTFSTATE State; + State.pchBuf = pszBuf; + State.cchLeft = cchBuf; + return Bs3StrFormatV(pszFormat, va, bs3StrPrintfFmtOutput, &State); +} + + +#undef Bs3StrPrintf +BS3_CMN_DEF(size_t, Bs3StrPrintf,(char BS3_FAR *pszBuf, size_t cchBuf, const char BS3_FAR *pszFormat, ...)) +{ + size_t cchRet; + va_list va; + va_start(va, pszFormat); + cchRet = BS3_CMN_NM(Bs3StrPrintfV)(pszBuf, cchBuf, pszFormat, va); + va_end(va); + return cchRet; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchHlpConvFlatRetToRetfProtMode.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchHlpConvFlatRetToRetfProtMode.asm new file mode 100644 index 00000000..e3b40821 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchHlpConvFlatRetToRetfProtMode.asm @@ -0,0 +1,78 @@ +; $Id: bs3-cmn-SwitchHlpConvFlatRetToRetfProtMode.asm $ +;; @file +; BS3Kit - SwitchHlpConvFlatRetToRetfProtMode +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +%if TMPL_BITS != 16 +BS3_EXTERN_CMN Bs3SelFlatCodeToProtFar16 + +;; +; SwitchToXxx helper that converts a 32-bit or 64-bit flat return address +; into a 16-bit protected mode far return. +; +; +; The caller calls this routine before switching modes. The flat return +; to be converted is immediately after our own return address on the stack. +; +; @uses Nothing. +; @remarks No 16-bit version. +; +BS3_PROC_BEGIN_CMN Bs3SwitchHlpConvFlatRetToRetfProtMode, BS3_PBC_NEAR + %if TMPL_BITS == 64 + push xAX + push xCX + sub xSP, 20h + + mov xCX, [xSP + xCB*3 + 20h] + call Bs3SelFlatCodeToProtFar16 ; well behaved assembly function, only clobbers ecx + mov [xSP + xCB*3 + 20h + 4], eax + + add xSP, 20h + pop xCX + pop xAX + ret 4 + %else + xchg eax, [xSP + xCB] + push xAX + call Bs3SelFlatCodeToProtFar16 ; well behaved assembly function, only clobbers eax + add xSP, 4 + xchg [xSP + xCB], eax + ret + %endif +BS3_PROC_END_CMN Bs3SwitchHlpConvFlatRetToRetfProtMode + +%endif ; 32 || 64 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchHlpConvProtModeRetfPopBpDecBpAndReturn.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchHlpConvProtModeRetfPopBpDecBpAndReturn.asm new file mode 100644 index 00000000..223e95e6 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchHlpConvProtModeRetfPopBpDecBpAndReturn.asm @@ -0,0 +1,126 @@ +; $Id: bs3-cmn-SwitchHlpConvProtModeRetfPopBpDecBpAndReturn.asm $ +;; @file +; BS3Kit - Bs3SwitchToPP32 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +%if TMPL_BITS == 16 +BS3_EXTERN_CMN Bs3SelProtModeCodeToRealMode +%else +BS3_EXTERN_CMN Bs3SelFar32ToFlat32 +%endif + + +;; +; SwitchToXxx helper that converts a 16-bit protected mode far return +; into something suitable for the current mode and performs the return. +; +; The caller jmps to this routine. The stack holds an incremented BP (odd is +; far indicator) and a 16-bit far return address. +; +; @uses Nothing. +; @remarks 16-bit ASSUMES we're returning to protected mode!! +; +%if TMPL_BITS == 16 +BS3_BEGIN_TEXT16_FARSTUBS +%endif +BS3_PROC_BEGIN_CMN Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn, BS3_PBC_NEAR +%if TMPL_BITS == 16 + ; Convert the selector of the 16:16 protected mode return address to the + ; corresponding 16-bit real mode segment. + push ax + + mov ax, [bp + 2 + 2] + push ax + call Bs3SelProtModeCodeToRealMode ; This doesn't trash any registers (except AX). + add sp, 2 + mov [bp + 2 + 2], ax + + pop ax + + pop bp + dec bp + retf + +%elif TMPL_BITS == 32 + push eax + push ecx + push edx + + movzx eax, word [esp + 4*3 + 2] ; return offset + movzx edx, word [esp + 4*3 + 2 + 2] ; return selector + push eax + push edx + call Bs3SelFar32ToFlat32 + add esp, 8 + mov [esp + 4*3 + 2], eax + + pop edx + pop ecx + pop eax + pop bp + dec bp + ret +%else + push rax + push rcx + push rdx + push r8 + push r9 + push r10 + push r11 + + movzx ecx, word [rsp + 8*7 + 2] ; return offset + movzx edx, word [rsp + 8*7 + 2 + 2] ; return selector + sub rsp, 20h + call Bs3SelFar32ToFlat32 + add rsp, 20h + mov [rsp + 8*7 + 2], eax + + pop r11 + pop r10 + pop r9 + pop r8 + pop rdx + pop rcx + pop rax + mov bp, [rsp] + add rsp, 2h + dec bp + o32 ret +%endif +BS3_PROC_END_CMN Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchHlpConvRealModeRetfPopBpDecBpAndReturn.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchHlpConvRealModeRetfPopBpDecBpAndReturn.asm new file mode 100644 index 00000000..04b9c912 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchHlpConvRealModeRetfPopBpDecBpAndReturn.asm @@ -0,0 +1,109 @@ +; $Id: bs3-cmn-SwitchHlpConvRealModeRetfPopBpDecBpAndReturn.asm $ +;; @file +; BS3Kit - SwitchHlpConvRealModeRetfPopBpDecBpAndReturn +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +BS3_EXTERN_CMN Bs3SelFar32ToFlat32 + +;; +; SwitchToXxx helper that converts a 16-bit real mode far return +; into something suitable for the current mode and performs the return. +; +; The caller jmps to this routine. The stack holds an incremented BP (odd is +; far indicator) and a 16-bit far return address. +; +; @uses Nothing. +; @remarks 16-bit ASSUMES we're returning to protected mode!! +; +%if TMPL_BITS == 16 +BS3_BEGIN_TEXT16_FARSTUBS +%endif +BS3_PROC_BEGIN_CMN Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn, BS3_PBC_NEAR +%if TMPL_BITS == 16 + ; Convert the selector of the 16:16 real mode return address to the + ; corresponding 16-bit protected mode selector. + push ax + + mov ax, [bp + 2 + 2] + push ax + BS3_EXTERN_CMN Bs3SelRealModeCodeToProtMode + call Bs3SelRealModeCodeToProtMode ; This doesn't trash any registers (except AX). + add sp, 2 + mov [bp + 2 + 2], ax + + pop ax + + pop bp + dec bp + retf + +%elif TMPL_BITS == 32 + push xAX + push xDX + + movzx eax, word [xSP + xCB*2 + 2 + 2] ; return segment + movzx edx, word [xSP + xCB*2 + 2] ; return offset + shl eax, 4 + add eax, edx + mov [xSP + xCB*2 + 2], eax + + pop xDX + pop xAX + pop bp + dec bp + ret +%else + sub rsp, 2h + + push xAX + push xDX + + movzx eax, word [xSP + xCB*2 + 4 + 2] ; return segment + movzx edx, word [xSP + xCB*2 + 4] ; return offset + shl eax, 4 + add eax, edx + + mov bp, [xSP + xCB*2 + 2] + dec bp + + mov [xSP + xCB*2], rax + + pop xDX + pop xAX + ret +%endif +BS3_PROC_END_CMN Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchTo16Bit.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchTo16Bit.asm new file mode 100644 index 00000000..1e1d8747 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchTo16Bit.asm @@ -0,0 +1,130 @@ +; $Id: bs3-cmn-SwitchTo16Bit.asm $ +;; @file +; BS3Kit - Bs3SwitchTo16Bit +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%if TMPL_BITS == 16 +BS3_EXTERN_CMN Bs3Syscall +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_DECL(void) Bs3SwitchTo16Bit(void); +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +BS3_PROC_BEGIN_CMN Bs3SwitchTo16Bit, BS3_PBC_NEAR +%if TMPL_BITS == 16 + push ax + push ds + + ; Check g_bBs3CurrentMode whether we're in v8086 mode or not. + mov al, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + test al, BS3_MODE_CODE_V86 + jz .ret_16bit + + ; Switch to ring-0 if v8086 mode. + mov ax, BS3_SYSCALL_TO_RING0 + call Bs3Syscall + +.ret_16bit: + pop ds + pop ax + ret + +%else + push xAX + push xBX + xPUSHF + cli + + ; Calc new CS. + mov ax, cs + and xAX, 3 + shl xAX, BS3_SEL_RING_SHIFT ; ring addend. + add xAX, BS3_SEL_R0_CS16 + + ; Construct a far return for switching to 16-bit code. + push xAX + push .sixteen_bit + xRETF + +BS3_BEGIN_TEXT16 +BS3_GLOBAL_LOCAL_LABEL .sixteen_bit + + ; Load 16-bit segment registers. + add ax, BS3_SEL_R0_SS16 - BS3_SEL_R0_CS16 + mov ss, ax + + add ax, BS3_SEL_R0_DS16 - BS3_SEL_R0_SS16 + mov ds, ax + mov es, ax + + ; Thunk the stack if necessary. + mov ebx, esp + shr ebx, 16 + jz .stack_ok +int3 ; This is for later, just remove this int3 once needed. + test ax, X86_SEL_RPL + jnz .stack_rpl_must_be_0_for_custom_stacks + shl bx, X86_SEL_SHIFT + add bx, BS3_SEL_TILED + mov ss, bx + movzx esp, sp +.stack_ok: + + ; Update globals. + and byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], ~BS3_MODE_CODE_MASK + or byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_16 + + popfd +TONLY64 pop ebx + pop ebx +TONLY64 pop eax + pop eax +TONLY64 add sp, 4 + ret (TMPL_BITS - 16) / 8 ; Return and pop 2 or 6 bytes of "parameters" (unused return value) + +.stack_rpl_must_be_0_for_custom_stacks: + int3 + jmp .stack_rpl_must_be_0_for_custom_stacks +TMPL_BEGIN_TEXT +%endif +BS3_PROC_END_CMN Bs3SwitchTo16Bit + +;; @todo far 16-bit variant. + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchTo16BitV86.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchTo16BitV86.asm new file mode 100644 index 00000000..636e6184 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchTo16BitV86.asm @@ -0,0 +1,133 @@ +; $Id: bs3-cmn-SwitchTo16BitV86.asm $ +;; @file +; BS3Kit - Bs3SwitchTo16BitV86 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +%if TMPL_BITS != 64 + +BS3_EXTERN_DATA16 g_bBs3CurrentMode +BS3_EXTERN_CMN Bs3SwitchToRing0 +BS3_EXTERN_CMN Bs3SelProtFar32ToFlat32 +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_DECL(void) Bs3SwitchTo16BitV86(void); +; @uses No general registers modified. Regment registers loaded with specific +; values and the stack register converted to real mode (not ebp). +; +BS3_PROC_BEGIN_CMN Bs3SwitchTo16BitV86, BS3_PBC_NEAR + ; Construct basic v8086 return frame. +BONLY16 movzx esp, sp + push dword 0 ; +0x20: GS + push dword 0 ; +0x1c: FS + push dword BS3_SEL_DATA16 ; +0x18: ES + push dword BS3_SEL_DATA16 ; +0x14: DS + push dword 0 ; +0x10: SS - later + push dword 0 ; +0x0c: return ESP, later. + pushfd + or dword [esp], X86_EFL_VM | X86_EFL_IOPL ; +0x08: Set IOPL=3 and the VM flag (EFLAGS). + push dword BS3_SEL_TEXT16 ; +0x04 + push word 0 + push word [esp + 24h - 2] ; +0x00 + ; Save registers and stuff. + push eax + push edx + push ecx + push ebx + %if TMPL_BITS == 16 + push ds + + ; Check g_bBs3CurrentMode whether we're in v8086 mode or not. + mov ax, seg g_bBs3CurrentMode + mov ds, ax + mov al, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + test al, BS3_MODE_CODE_V86 + jz .not_v8086 + + pop ds + pop ebx + pop ecx + pop edx + pop eax + add xSP, 0x24 + ret + +.not_v8086: + pop ax ; Drop the push ds so the stacks are identical. Keep DS = BS3KIT_GRPNM_DATA16 though. + %endif + + ; Ensure that we're in ring-0. + mov ax, ss + test ax, 3 + jz .is_ring0 + call Bs3SwitchToRing0 + %if TMPL_BITS == 16 + mov ax, seg g_bBs3CurrentMode + mov ds, ax ; parnoia + %endif +.is_ring0: + + ; Update globals. + and byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], ~BS3_MODE_CODE_MASK + or byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + + ; Thunk return SS:ESP to real-mode address via 32-bit flat. + lea eax, [esp + 4*4 + 24h + xCB] + push ss + push eax + BS3_CALL Bs3SelProtFar32ToFlat32, 2 + add esp, sCB + xCB + mov [esp + 4*4 + 0ch], ax ; high word is already zero + %if TMPL_BITS == 16 + mov [esp + 4*4 + 10h], dx + %else + shr eax, 16 + mov [esp + 4*4 + 10h], ax + %endif + + ; Return to v8086 mode. + pop ebx + pop ecx + pop edx + pop eax + iretd +BS3_PROC_END_CMN Bs3SwitchTo16BitV86 + +;; @todo far 16-bit variant. + +%endif ; ! 64-bit + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchTo32Bit.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchTo32Bit.asm new file mode 100644 index 00000000..5b3cf18b --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchTo32Bit.asm @@ -0,0 +1,162 @@ +; $Id: bs3-cmn-SwitchTo32Bit.asm $ +;; @file +; BS3Kit - Bs3SwitchTo32Bit +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +%if TMPL_BITS == 16 +BS3_EXTERN_CMN Bs3SelProtFar32ToFlat32 +BS3_EXTERN_CMN Bs3Syscall +%endif +%if TMPL_BITS != 32 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +TMPL_BEGIN_TEXT +%endif + + +;; +; @cproto BS3_DECL(void) Bs3SwitchTo32Bit(void); +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +BS3_PROC_BEGIN_CMN Bs3SwitchTo32Bit, BS3_PBC_NEAR +%if TMPL_BITS == 32 + ret +%else + %if TMPL_BITS == 16 + push ax ; Reserve space for larger return value (adjusted in 32-bit code). + push eax + pushfd + push edx + %else + pushfq + mov [rsp + 4], eax + %endif + cli + + %if TMPL_BITS == 16 + ; Check for v8086 mode, we need to exit it to enter 32-bit mode. + mov ax, seg g_bBs3CurrentMode + mov ds, ax + mov al, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + test al, BS3_MODE_CODE_V86 + jz .not_v8086 + + ; Calc flat stack into edx. + mov dx, ss + movzx edx, dx + shl edx, 4 + add dx, sp + adc edx, 0 ; edx = flat stack address corresponding to ss:sp + + ; Switch to 16-bit ring0 and go on to do the far jump to 32-bit code. + mov ax, BS3_SYSCALL_TO_RING0 + call Bs3Syscall + + mov xAX, BS3_SEL_R0_CS32 + jmp .do_far_jump + %endif + +.not_v8086: + %if TMPL_BITS == 16 + ; Calc flat stack into edx. + movzx eax, sp + push ecx + push ebx + push ss + push eax + call Bs3SelProtFar32ToFlat32 + add sp, 6 + shl edx, 16 + mov dx, ax ; edx = flat stack address corresponding to ss:sp + pop ebx + pop ecx + %endif + + ; Calc ring addend. + mov ax, cs + and xAX, 3 + shl xAX, BS3_SEL_RING_SHIFT + add xAX, BS3_SEL_R0_CS32 + + ; Create far return for switching to 32-bit mode. +.do_far_jump: + push sAX + %if TMPL_BITS == 16 + push dword .thirty_two_bit wrt FLAT + o32 retf + %else + push .thirty_two_bit + o64 retf + %endif + +BS3_SET_BITS 32 +.thirty_two_bit: + ; Load 32-bit segment registers. + add eax, BS3_SEL_R0_SS32 - BS3_SEL_R0_CS32 + mov ss, ax + %if TMPL_BITS == 16 + mov esp, edx ; Load flat stack address. + %endif + + add eax, BS3_SEL_R0_DS32 - BS3_SEL_R0_SS32 + mov ds, ax + mov es, ax + + ; Update globals. + and byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], ~BS3_MODE_CODE_MASK + or byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_32 + + %if TMPL_BITS == 16 + ; Adjust the return address. + movzx eax, word [esp + 4*3 + 2] + add eax, BS3_ADDR_BS3TEXT16 + mov [esp + 4*3], eax + %endif + + ; Restore and return. + %if TMPL_BITS == 16 + pop edx + %endif + popfd + pop eax +TONLY64 ret 4 +TNOT64 ret +%endif +BS3_PROC_END_CMN Bs3SwitchTo32Bit + +;; @todo far 16-bit variant. + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchTo64Bit.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchTo64Bit.asm new file mode 100644 index 00000000..dfa70f58 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchTo64Bit.asm @@ -0,0 +1,120 @@ +; $Id: bs3-cmn-SwitchTo64Bit.asm $ +;; @file +; BS3Kit - Bs3SwitchTo64Bit +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +%if TMPL_BITS != 64 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +TMPL_BEGIN_TEXT +%endif + + +;; +; @cproto BS3_DECL(void) Bs3SwitchTo64Bit(void); +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3SwitchTo64Bit, BS3_PBC_NEAR +%if TMPL_BITS == 64 + ret + +%else + %if TMPL_BITS == 16 + sub sp, 6 ; Space for extended return value (corrected in 64-bit mode). + %else + push xPRE [xSP] ; Duplicate the return address. + and dword [xSP + xCB], 0 ; Clear the high dword or it. + %endif + push dword 0 + push sAX + push dword 0 + pushfd + cli + + %if TMPL_BITS == 16 + ; Check that this is LM16 + mov ax, seg g_bBs3CurrentMode + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_LM16 + je .ok_lm16 + int3 + .ok_lm16: + %endif + + ; Calc ring addend. + mov ax, cs + and xAX, 3 + shl xAX, BS3_SEL_RING_SHIFT + add xAX, BS3_SEL_R0_CS64 + + ; setup far return. + push sAX + %if TMPL_BITS == 16 + push dword .sixty_four_bit wrt FLAT + o32 retf + %else + push .sixty_four_bit + retf + %endif + +BS3_SET_BITS 64 +.sixty_four_bit: + + ; Load 64-bit segment registers (SS64==DS64). + add eax, BS3_SEL_R0_DS64 - BS3_SEL_R0_CS64 + mov ss, ax + mov ds, ax + mov es, ax + + ; Update globals. + and byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], ~BS3_MODE_CODE_MASK + or byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_64 + + %if TMPL_BITS == 16 + movzx eax, word [rsp + 8*2+6] + add eax, BS3_ADDR_BS3TEXT16 + mov [rsp + 8*2], rax + %endif + + popfq + pop rax + ret +%endif +BS3_PROC_END_CMN Bs3SwitchTo64Bit + + +;; @todo far 16-bit variant. + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRing0.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRing0.asm new file mode 100644 index 00000000..fd3f1135 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRing0.asm @@ -0,0 +1,73 @@ +; $Id: bs3-cmn-SwitchToRing0.asm $ +;; @file +; BS3Kit - Bs3SwitchToRing0 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_EXTERN_CMN_FAR Bs3SwitchToRingX +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_DECL(void) Bs3SwitchToRing0(void); +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3SwitchToRing0, BS3_PBC_HYBRID_0_ARGS +%if TMPL_BITS == 64 + push rcx + sub rsp, 20h + mov ecx, 0 + mov [rsp], rcx + call Bs3SwitchToRingX + add rsp, 20h + pop rcx +%else + push 0 +TONLY16 push cs + call Bs3SwitchToRingX + add xSP, xCB +%endif + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3SwitchToRing0 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRing1.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRing1.asm new file mode 100644 index 00000000..834992c8 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRing1.asm @@ -0,0 +1,73 @@ +; $Id: bs3-cmn-SwitchToRing1.asm $ +;; @file +; BS3Kit - Bs3SwitchToRing1 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_EXTERN_CMN_FAR Bs3SwitchToRingX +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_DECL(void) Bs3SwitchToRing1(void); +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3SwitchToRing1, BS3_PBC_HYBRID_0_ARGS +%if TMPL_BITS == 64 + push rcx + sub rsp, 20h + mov ecx, 1 + mov [rsp], rcx + call Bs3SwitchToRingX + add rsp, 20h + pop rcx +%else + push 1 +TONLY16 push cs + call Bs3SwitchToRingX + add xSP, xCB +%endif + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3SwitchToRing1 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRing2.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRing2.asm new file mode 100644 index 00000000..a14202d6 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRing2.asm @@ -0,0 +1,73 @@ +; $Id: bs3-cmn-SwitchToRing2.asm $ +;; @file +; BS3Kit - Bs3SwitchToRing2 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_EXTERN_CMN_FAR Bs3SwitchToRingX +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_DECL(void) Bs3SwitchToRing2(void); +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3SwitchToRing2, BS3_PBC_HYBRID_0_ARGS +%if TMPL_BITS == 64 + push rcx + sub rsp, 20h + mov ecx, 2 + mov [rsp], rcx + call Bs3SwitchToRingX + add rsp, 20h + pop rcx +%else + push 2 +TONLY16 push cs + call Bs3SwitchToRingX + add xSP, xCB +%endif + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3SwitchToRing2 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRing3.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRing3.asm new file mode 100644 index 00000000..901be524 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRing3.asm @@ -0,0 +1,73 @@ +; $Id: bs3-cmn-SwitchToRing3.asm $ +;; @file +; BS3Kit - Bs3SwitchToRing3 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_EXTERN_CMN_FAR Bs3SwitchToRingX +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_DECL(void) Bs3SwitchToRing3(void); +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3SwitchToRing3, BS3_PBC_HYBRID_0_ARGS +%if TMPL_BITS == 64 + push rcx + sub rsp, 20h + mov ecx, 3 + mov [rsp], rcx + call Bs3SwitchToRingX + add rsp, 20h + pop rcx +%else + push 3 +TONLY16 push cs + call Bs3SwitchToRingX + add xSP, xCB +%endif + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3SwitchToRing3 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRingX.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRingX.asm new file mode 100644 index 00000000..9c48e0f8 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRingX.asm @@ -0,0 +1,103 @@ +; $Id: bs3-cmn-SwitchToRingX.asm $ +;; @file +; BS3Kit - Bs3SwitchToRingX +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_EXTERN_CMN Bs3Syscall +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_DECL(void) Bs3SwitchToRingX(uint8_t bRing); +; +; @param bRing The target ring (0..3). +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +; @uses No GPRs. +; +BS3_PROC_BEGIN_CMN Bs3SwitchToRingX, BS3_PBC_HYBRID_SAFE + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push xAX + +%if TMPL_BITS == 16 + ; Check the current mode. + mov al, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + + ; If real mode: Nothing we can do, but we'll bitch if the request isn't for ring-0. + cmp al, BS3_MODE_RM + je .return_real_mode + + ; If V8086 mode: Always do syscall and add a lock prefix to make sure it gets to the VMM. + test al, BS3_MODE_CODE_V86 + jnz .just_do_it +%endif + + ; In protected mode: Check the CPL we're currently at skip syscall if ring-0 already. + mov ax, cs + and al, 3 + cmp al, byte [xBP + xCB + cbCurRetAddr] + je .return + +.just_do_it: + mov xAX, BS3_SYSCALL_TO_RING0 + add al, [xBP + xCB + cbCurRetAddr] + call Bs3Syscall + +%ifndef BS3_STRICT +.return_real_mode: +%endif +.return: + pop xAX + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET + +%ifdef BS3_STRICT +; In real mode, only ring-0 makes any sense. +.return_real_mode: + cmp byte [xBP + xCB + cbCurRetAddr], 0 + je .return + int3 + jmp .return +%endif +BS3_PROC_END_CMN Bs3SwitchToRingX + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Syscall.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Syscall.asm new file mode 100644 index 00000000..6fad4703 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Syscall.asm @@ -0,0 +1,94 @@ +; $Id: bs3-cmn-Syscall.asm $ +;; @file +; BS3Kit - Bs3Syscall. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +BS3_EXTERN_DATA16 g_uBs3TrapEipHint +TMPL_BEGIN_TEXT + + +;; +; Worker for doing a syscall - Assembly only. +; +; This worker deals with the needing to use a different opcode +; sequence in v8086 mode as well as the high EIP word hint for +; the weird PE16_32, PP16_32 and PAE16_32 modes. +; +; @uses Whatever the syscall modified (xBX and XBP are always saved). +; +BS3_PROC_BEGIN_CMN Bs3Syscall, BS3_PBC_HYBRID_0_ARGS ; (all parameters are in registers) + push xBP + mov xBP, xSP + push xBX + +%if TMPL_BITS == 32 + mov ebx, .return + xchg ebx, [BS3_DATA16_WRT(g_uBs3TrapEipHint)] +%elif TMPL_BITS == 16 + test byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86 + mov bx, 0 + xchg bx, [2 + BS3_DATA16_WRT(g_uBs3TrapEipHint)] + jz .normal + + db 0xf0 ; Lock prefix for causing #UD in V8086 mode. +%endif +.normal: + int BS3_TRAP_SYSCALL + +.return: + ; Restore the EIP hint so the testcase code doesn't need to set it all the time. +%if TMPL_BITS == 32 + mov [BS3_DATA16_WRT(g_uBs3TrapEipHint)], ebx +%elif TMPL_BITS == 16 + mov [2 + BS3_DATA16_WRT(g_uBs3TrapEipHint)], bx +%endif + + pop xBX + pop xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3Syscall + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestCheckExtCtx.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestCheckExtCtx.c new file mode 100644 index 00000000..7c4b4a0e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestCheckExtCtx.c @@ -0,0 +1,287 @@ +/* $Id: bs3-cmn-TestCheckExtCtx.c $ */ +/** @file + * BS3Kit - Bs3TestCheckExtCtx + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +/** Field descriptors. */ +static struct +{ + uint8_t enmMethod; + uint8_t cb; + uint16_t off; + const char BS3_FAR *pszName; +} const g_aFields[] = +{ +#define BS3EXTCTX_FIELD_ENTRY(a_enmMethod, a_Member) \ + { a_enmMethod, RT_SIZEOFMEMB(BS3EXTCTX, a_Member), RT_OFFSETOF(BS3EXTCTX, a_Member), #a_Member } + BS3EXTCTX_FIELD_ENTRY(BS3EXTCTXMETHOD_END, fXcr0Saved), + +#define BS3EXTCTX_FIELD_ENTRY_CTX(a_enmMethod, a_Member) \ + { a_enmMethod, RT_SIZEOFMEMB(BS3EXTCTX, Ctx.a_Member), RT_OFFSETOF(BS3EXTCTX, Ctx.a_Member), #a_Member } + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.FCW), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.Dummy1), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.FSW), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.Dummy2), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.FTW), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.Dummy3), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.FPUIP), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.CS), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.FOP), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.FPUOO), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.FPUOS), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.regs[0]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.regs[1]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.regs[2]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.regs[3]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.regs[4]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.regs[5]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.regs[6]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_ANCIENT, Ancient.regs[7]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.FCW), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.FSW), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.FTW), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.FOP), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.FPUIP), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.CS), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.Rsrvd1), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.FPUDP), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.DS), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.Rsrvd2), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.MXCSR), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.MXCSR_MASK), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aRegs[0]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aRegs[1]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aRegs[2]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aRegs[3]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aRegs[4]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aRegs[5]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aRegs[6]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aRegs[7]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aXMM[0]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aXMM[1]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aXMM[2]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aXMM[3]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aXMM[4]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aXMM[5]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aXMM[6]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aXMM[7]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aXMM[8]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aXMM[9]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aXMM[10]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aXMM[11]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aXMM[12]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aXMM[13]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aXMM[14]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_FXSAVE, x87.aXMM[15]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.FCW), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.FSW), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.FTW), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.FOP), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.FPUIP), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.CS), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.Rsrvd1), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.FPUDP), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.DS), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.Rsrvd2), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.MXCSR), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.MXCSR_MASK), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aRegs[0]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aRegs[1]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aRegs[2]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aRegs[3]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aRegs[4]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aRegs[5]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aRegs[6]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aRegs[7]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aXMM[0]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aXMM[1]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aXMM[2]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aXMM[3]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aXMM[4]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aXMM[5]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aXMM[6]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aXMM[7]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aXMM[8]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aXMM[9]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aXMM[10]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aXMM[11]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aXMM[12]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aXMM[13]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aXMM[14]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.x87.aXMM[15]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.Hdr.bmXState), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.Hdr.bmXComp), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.u.YmmHi.aYmmHi[0]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.u.YmmHi.aYmmHi[1]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.u.YmmHi.aYmmHi[2]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.u.YmmHi.aYmmHi[3]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.u.YmmHi.aYmmHi[4]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.u.YmmHi.aYmmHi[5]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.u.YmmHi.aYmmHi[6]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.u.YmmHi.aYmmHi[7]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.u.YmmHi.aYmmHi[8]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.u.YmmHi.aYmmHi[9]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.u.YmmHi.aYmmHi[10]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.u.YmmHi.aYmmHi[11]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.u.YmmHi.aYmmHi[12]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.u.YmmHi.aYmmHi[13]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.u.YmmHi.aYmmHi[14]), + BS3EXTCTX_FIELD_ENTRY_CTX(BS3EXTCTXMETHOD_XSAVE, x.u.YmmHi.aYmmHi[15]), +}; + + +#undef Bs3TestCheckExtCtx +BS3_CMN_DEF(bool, Bs3TestCheckExtCtx,(PCBS3EXTCTX pActualExtCtx, PCBS3EXTCTX pExpectedExtCtx, uint16_t fFlags, + const char BS3_FAR *pszMode, uint16_t idTestStep)) +{ + /* + * Make sure the context of a similar and valid before starting. + */ + if (!pActualExtCtx || pActualExtCtx->u16Magic != BS3EXTCTX_MAGIC) + return Bs3TestFailedF("%u - %s: invalid actual context pointer: %p", idTestStep, pszMode, pActualExtCtx); + if (!pExpectedExtCtx || pExpectedExtCtx->u16Magic != BS3EXTCTX_MAGIC) + return Bs3TestFailedF("%u - %s: invalid expected context pointer: %p", idTestStep, pszMode, pExpectedExtCtx); + if ( pActualExtCtx->enmMethod != pExpectedExtCtx->enmMethod + || pActualExtCtx->enmMethod == BS3EXTCTXMETHOD_INVALID + || pActualExtCtx->enmMethod >= BS3EXTCTXMETHOD_END) + return Bs3TestFailedF("%u - %s: mismatching or/and invalid context methods: %d vs %d", + idTestStep, pszMode, pActualExtCtx->enmMethod, pExpectedExtCtx->enmMethod); + if (pActualExtCtx->cb != pExpectedExtCtx->cb) + return Bs3TestFailedF("%u - %s: mismatching context sizes: %#x vs %#x", + idTestStep, pszMode, pActualExtCtx->cb, pExpectedExtCtx->cb); + + /* + * Try get the job done quickly with a memory compare. + */ + if (Bs3MemCmp(pActualExtCtx, pExpectedExtCtx, pActualExtCtx->cb) == 0) + return true; + + Bs3TestFailedF("%u - %s: context memory differs", idTestStep, pszMode); // debug + { + uint8_t const BS3_FAR *pb1 = (uint8_t const BS3_FAR *)pActualExtCtx; + uint8_t const BS3_FAR *pb2 = (uint8_t const BS3_FAR *)pExpectedExtCtx; + unsigned const cb = pActualExtCtx->cb; + unsigned off; + for (off = 0; off < cb; off++) + if (pb1[off] != pb2[off]) + { + unsigned offStart = off++; + const char BS3_FAR *pszName = NULL; + unsigned cbDiff = 0; + unsigned idxField; + for (idxField = 0; idxField < RT_ELEMENTS(g_aFields); idxField++) + if ( offStart - g_aFields[idxField].off < g_aFields[idxField].cb + && ( g_aFields[idxField].enmMethod == BS3EXTCTXMETHOD_END + || g_aFields[idxField].enmMethod == pActualExtCtx->enmMethod)) + { + pszName = g_aFields[idxField].pszName; + cbDiff = g_aFields[idxField].cb; + offStart = g_aFields[idxField].off; + off = offStart + cbDiff; + break; + } + if (!pszName) + { + while (off < cb && pb1[off] != pb2[off]) + off++; + cbDiff = off - offStart; + pszName = "unknown"; + } + switch (cbDiff) + { + case 1: + Bs3TestFailedF("%u - %s: Byte difference at %#x (%s): %#04x, expected %#04x", + idTestStep, pszMode, offStart, pszName, pb1[offStart], pb2[offStart]); + break; + case 2: + Bs3TestFailedF("%u - %s: Word difference at %#x (%s): %#06x, expected %#06x", + idTestStep, pszMode, offStart, pszName, + RT_MAKE_U16(pb1[offStart], pb1[offStart + 1]), + RT_MAKE_U16(pb2[offStart], pb2[offStart + 1])); + break; + case 4: + Bs3TestFailedF("%u - %s: DWord difference at %#x (%s): %#010RX32, expected %#010RX32", + idTestStep, pszMode, offStart, pszName, + RT_MAKE_U32_FROM_U8(pb1[offStart], pb1[offStart + 1], pb1[offStart + 2], pb1[offStart + 3]), + RT_MAKE_U32_FROM_U8(pb2[offStart], pb2[offStart + 1], pb2[offStart + 2], pb2[offStart + 3])); + break; + case 8: + Bs3TestFailedF("%u - %s: QWord difference at %#x (%s): %#018RX64, expected %#018RX64", + idTestStep, pszMode, offStart, pszName, + RT_MAKE_U64_FROM_U8(pb1[offStart], pb1[offStart + 1], pb1[offStart + 2], pb1[offStart + 3], + pb1[offStart + 4], pb1[offStart + 5], pb1[offStart + 6], pb1[offStart + 7]), + RT_MAKE_U64_FROM_U8(pb2[offStart], pb2[offStart + 1], pb2[offStart + 2], pb2[offStart + 3], + pb2[offStart + 4], pb2[offStart + 5], pb2[offStart + 6], pb2[offStart + 7])); + break; + case 16: + Bs3TestFailedF("%u - %s: DQword difference at %#x (%s): \n" + "got %#018RX64'%#018RX64\n" + "expected %#018RX64'%#018RX64", + idTestStep, pszMode, offStart, pszName, + RT_MAKE_U64_FROM_U8(pb1[offStart + 8], pb1[offStart + 9], pb1[offStart + 10], pb1[offStart + 11], + pb1[offStart + 12], pb1[offStart + 13], pb1[offStart + 14], pb1[offStart + 15]), + RT_MAKE_U64_FROM_U8(pb1[offStart], pb1[offStart + 1], pb1[offStart + 2], pb1[offStart + 3], + pb1[offStart + 4], pb1[offStart + 5], pb1[offStart + 6], pb1[offStart + 7]), + + RT_MAKE_U64_FROM_U8(pb2[offStart + 8], pb2[offStart + 9], pb2[offStart + 10], pb2[offStart + 11], + pb2[offStart + 12], pb2[offStart + 13], pb2[offStart + 14], pb2[offStart + 15]), + RT_MAKE_U64_FROM_U8(pb2[offStart], pb2[offStart + 1], pb2[offStart + 2], pb2[offStart + 3], + pb2[offStart + 4], pb2[offStart + 5], pb2[offStart + 6], pb2[offStart + 7]) + ); + break; + + default: + Bs3TestFailedF("%u - %s: %#x..%#x differs (%s)\n" + "got %.*Rhxs\n" + "expected %.*Rhxs", + idTestStep, pszMode, offStart, off - 1, pszName, + off - offStart, &pb1[offStart], + off - offStart, &pb2[offStart]); + break; + } + } + } + return false; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestCheckRegCtxEx.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestCheckRegCtxEx.c new file mode 100644 index 00000000..d75b49f7 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestCheckRegCtxEx.c @@ -0,0 +1,107 @@ +/* $Id: bs3-cmn-TestCheckRegCtxEx.c $ */ +/** @file + * BS3Kit - TestCheckRegCtxEx + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3TestCheckRegCtxEx +BS3_CMN_DEF(bool, Bs3TestCheckRegCtxEx,(PCBS3REGCTX pActualCtx, PCBS3REGCTX pExpectedCtx, uint16_t cbPcAdjust, int16_t cbSpAcjust, + uint32_t fExtraEfl, const char BS3_FAR *pszMode, uint16_t idTestStep)) +{ + uint16_t const cErrorsBefore = Bs3TestSubErrorCount(); + uint8_t const fbFlags = pActualCtx->fbFlags | pExpectedCtx->fbFlags; + +#define CHECK_MEMBER(a_szName, a_szFmt, a_Actual, a_Expected) \ + do { \ + if ((a_Actual) == (a_Expected)) { /* likely */ } \ + else Bs3TestFailedF("%u - %s: " a_szName "=" a_szFmt " expected " a_szFmt, idTestStep, pszMode, (a_Actual), (a_Expected)); \ + } while (0) + + CHECK_MEMBER("rax", "%08RX64", pActualCtx->rax.u, pExpectedCtx->rax.u); + CHECK_MEMBER("rcx", "%08RX64", pActualCtx->rcx.u, pExpectedCtx->rcx.u); + CHECK_MEMBER("rdx", "%08RX64", pActualCtx->rdx.u, pExpectedCtx->rdx.u); + CHECK_MEMBER("rbx", "%08RX64", pActualCtx->rbx.u, pExpectedCtx->rbx.u); + CHECK_MEMBER("rsp", "%08RX64", pActualCtx->rsp.u, pExpectedCtx->rsp.u + cbSpAcjust); + CHECK_MEMBER("rbp", "%08RX64", pActualCtx->rbp.u, pExpectedCtx->rbp.u); + CHECK_MEMBER("rsi", "%08RX64", pActualCtx->rsi.u, pExpectedCtx->rsi.u); + CHECK_MEMBER("rdi", "%08RX64", pActualCtx->rdi.u, pExpectedCtx->rdi.u); + if (!(fbFlags & BS3REG_CTX_F_NO_AMD64)) + { + CHECK_MEMBER("r8", "%08RX64", pActualCtx->r8.u, pExpectedCtx->r8.u); + CHECK_MEMBER("r9", "%08RX64", pActualCtx->r9.u, pExpectedCtx->r9.u); + CHECK_MEMBER("r10", "%08RX64", pActualCtx->r10.u, pExpectedCtx->r10.u); + CHECK_MEMBER("r11", "%08RX64", pActualCtx->r11.u, pExpectedCtx->r11.u); + CHECK_MEMBER("r12", "%08RX64", pActualCtx->r12.u, pExpectedCtx->r12.u); + CHECK_MEMBER("r13", "%08RX64", pActualCtx->r13.u, pExpectedCtx->r13.u); + CHECK_MEMBER("r14", "%08RX64", pActualCtx->r14.u, pExpectedCtx->r14.u); + CHECK_MEMBER("r15", "%08RX64", pActualCtx->r15.u, pExpectedCtx->r15.u); + } + CHECK_MEMBER("rflags", "%08RX64", pActualCtx->rflags.u, pExpectedCtx->rflags.u | fExtraEfl); + CHECK_MEMBER("rip", "%08RX64", pActualCtx->rip.u, pExpectedCtx->rip.u + cbPcAdjust); + CHECK_MEMBER("cs", "%04RX16", pActualCtx->cs, pExpectedCtx->cs); + CHECK_MEMBER("ds", "%04RX16", pActualCtx->ds, pExpectedCtx->ds); + CHECK_MEMBER("es", "%04RX16", pActualCtx->es, pExpectedCtx->es); + CHECK_MEMBER("fs", "%04RX16", pActualCtx->fs, pExpectedCtx->fs); + CHECK_MEMBER("gs", "%04RX16", pActualCtx->gs, pExpectedCtx->gs); + + if (!(fbFlags & BS3REG_CTX_F_NO_TR_LDTR)) + { + CHECK_MEMBER("tr", "%04RX16", pActualCtx->tr, pExpectedCtx->tr); + CHECK_MEMBER("ldtr", "%04RX16", pActualCtx->ldtr, pExpectedCtx->ldtr); + } + CHECK_MEMBER("bMode", "%#04x", pActualCtx->bMode, pExpectedCtx->bMode); + CHECK_MEMBER("bCpl", "%u", pActualCtx->bCpl, pExpectedCtx->bCpl); + + if (!(fbFlags & BS3REG_CTX_F_NO_CR0_IS_MSW)) + CHECK_MEMBER("cr0", "%08RX64", pActualCtx->cr0.u, pExpectedCtx->cr0.u); + else + CHECK_MEMBER("msw", "%08RX16", pActualCtx->cr0.u16, pExpectedCtx->cr0.u16); + if (!(fbFlags & BS3REG_CTX_F_NO_CR2_CR3)) + { + CHECK_MEMBER("cr2", "%08RX64", pActualCtx->cr2.u, pExpectedCtx->cr2.u); + CHECK_MEMBER("cr3", "%08RX64", pActualCtx->cr3.u, pExpectedCtx->cr3.u); + } + if (!(fbFlags & BS3REG_CTX_F_NO_CR4)) + CHECK_MEMBER("cr4", "%08RX64", pActualCtx->cr4.u, pExpectedCtx->cr4.u); +#undef CHECK_MEMBER + + return Bs3TestSubErrorCount() == cErrorsBefore; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestData.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestData.c new file mode 100644 index 00000000..8ff06dec --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestData.c @@ -0,0 +1,135 @@ +/* $Id: bs3-cmn-TestData.c $ */ +/** @file + * BS3Kit - Test Data. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-test.h" + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +#if ARCH_BITS == 16 + +/** Indicates whether the VMMDev is operational. */ +bool g_fbBs3VMMDevTesting = true; + +/** Alignment padding. */ +bool g_fTestDataPadding0 = true; + +/** The number of tests that have failed. */ +uint16_t g_cusBs3TestErrors = 0; + +/** The start error count of the current subtest. */ +uint16_t g_cusBs3SubTestAtErrors = 0; + +/** Whether we've reported the sub-test result or not. */ +bool g_fbBs3SubTestReported = true; +/** Whether the sub-test has been skipped or not. */ +bool g_fbBs3SubTestSkipped = false; + +/** The number of sub tests. */ +uint16_t g_cusBs3SubTests = 0; + +/** The number of sub tests that failed. */ +uint16_t g_cusBs3SubTestsFailed = 0; + +/** VMMDEV_TESTING_UNIT_XXX -> string */ +char const g_aszBs3TestUnitNames[][12] = +{ + "inv", + "%", + "bytes", + "bytes/s", + "KB", + "KB/s", + "MB", + "MB/s", + "packets", + "packets/s", + "frames", + "frames/", + "occ", + "occ/s", + "rndtrp", + "calls", + "calls/s", + "s", + "ms", + "ns", + "ns/call", + "ns/frame", + "ns/occ", + "ns/packet", + "ns/rndtrp", + "ins", + "ins/s", + "", /* none */ + "pp1k", + "pp10k", + "ppm", + "ppb", + "ticks", + "ticks/call", + "ticks/occ", + "pages", + "pages/s", + "ticks/page", + "ns/page", + "ps", + "ps/call", + "ps/frame", + "ps/occ", + "ps/packet", + "ps/rndtrp", + "ps/page", +}; + + +/** The subtest name. */ +char g_szBs3SubTest[64]; + +/** The current test step. */ +uint16_t g_usBs3TestStep; + +#endif /* ARCH_BITS == 16 */ + +/** The test name. */ +const char BS3_FAR *BS3_CMN_NM(g_pszBs3Test) = NULL; + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestDoModesByOneHlp.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestDoModesByOneHlp.asm new file mode 100644 index 00000000..46dd230a --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestDoModesByOneHlp.asm @@ -0,0 +1,253 @@ +; $Id: bs3-cmn-TestDoModesByOneHlp.asm $ +;; @file +; BS3Kit - Bs3TestDoModesByOne Helpers for switching to the bit-count of the worker function. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* Global Variables * +;********************************************************************************************************************************* +BS3_BEGIN_DATA16 +BS3_GLOBAL_NAME_EX BS3_CMN_NM(g_pfnBs3TestDoModesByOneCurrent),,0 + RTCCPTR_DEF 0 + + +;********************************************************************************************************************************* +;* Exported Symbols * +;********************************************************************************************************************************* +%ifdef BS3_STRICT +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif + +%if TMPL_BITS == 16 +BS3_BEGIN_TEXT16 +extern _Bs3SelRealModeCodeToProtMode_c16 +%endif + + +;; +; @cproto FNBS3TESTDOMODE +; +; @param bMode The current mode +; @uses What allowed by calling convention and possibly mode, caller deals with it. +; + +%if TMPL_BITS == 16 + ; + ; For 16-bit workers. + ; +BS3_BEGIN_TEXT16 + +BS3_SET_BITS 32 +BS3_PROC_BEGIN _Bs3TestCallDoerTo16_c32 + push xBP + mov xBP, xSP + + ; Load bMode into eax. + movzx eax, byte [xBP + xCB*2] + %ifdef BS3_STRICT + cmp al, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + je .ok_mode + int3 +.ok_mode: + %endif + ; Switch to 16-bit. + extern _Bs3SwitchTo16Bit_c32 + call _Bs3SwitchTo16Bit_c32 + BS3_SET_BITS 16 + + push ax ; Worker bMode argument. + + ; Assuming real mode far pointer, convert protected mode before calling it. + push word [2 + BS3_DATA16_WRT(BS3_CMN_NM(g_pfnBs3TestDoModesByOneCurrent))] + call _Bs3SelRealModeCodeToProtMode_c16 + add sp, 2 + + push cs ; return selector + push word .return ; return address + + push ax ; call converted selector + push word [BS3_DATA16_WRT(BS3_CMN_NM(g_pfnBs3TestDoModesByOneCurrent))] ; call offset + retf + +.return: + ; Switch back to 32-bit mode. + extern _Bs3SwitchTo32Bit_c16 + call _Bs3SwitchTo32Bit_c16 + BS3_SET_BITS 32 + + leave + ret +BS3_PROC_END _Bs3TestCallDoerTo16_c32 + + +BS3_SET_BITS 64 +BS3_PROC_BEGIN _Bs3TestCallDoerTo16_c64 + push xBP + mov xBP, xSP + + ; Load bMode into eax. + movzx eax, cl + %ifdef BS3_STRICT + cmp al, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + je .ok_mode + int3 +.ok_mode: + %endif + ; Switch to 16-bit. + extern _Bs3SwitchTo16Bit_c64 + call _Bs3SwitchTo16Bit_c64 + BS3_SET_BITS 16 + + push ax ; Worker bMode argument. + + ; Assuming real mode far pointer, convert protected mode before calling it. + push word [2 + BS3_DATA16_WRT(BS3_CMN_NM(g_pfnBs3TestDoModesByOneCurrent))] + call _Bs3SelRealModeCodeToProtMode_c16 + add sp, 2 + + push cs ; return selector + push word .return ; return address + push ax ; call converted selector + push word [BS3_DATA16_WRT(BS3_CMN_NM(g_pfnBs3TestDoModesByOneCurrent))] ; call offset + retf + +.return: + ; Switch back to 64-bit mode. + extern _Bs3SwitchTo64Bit_c16 + call _Bs3SwitchTo64Bit_c16 + BS3_SET_BITS 64 + + leave + ret +BS3_PROC_END _Bs3TestCallDoerTo16_c64 + + +%elif TMPL_BITS == 32 + ; + ; For 32-bit workers. + ; + +BS3_BEGIN_TEXT16 +BS3_SET_BITS 16 +BS3_PROC_BEGIN _Bs3TestCallDoerTo32_f16 + push xBP + mov xBP, xSP + + ; Load bMode into eax. + movzx eax, byte [xBP + xCB + sCB] + %ifdef BS3_STRICT + cmp al, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + je .ok_mode + int3 +.ok_mode: + %endif + ; Switch to 32-bit. + extern _Bs3SwitchTo32Bit_c16 + call _Bs3SwitchTo32Bit_c16 + BS3_SET_BITS 32 + + push eax ; Worker bMode argument. + + test al, BS3_MODE_CODE_V86 + jnz .return_to_v86 ; Need to figure this while we still have the mode value. + + call [BS3_DATA16_WRT(BS3_CMN_NM(g_pfnBs3TestDoModesByOneCurrent))] + + ; Switch back to 16-bit mode. + extern _Bs3SwitchTo16Bit_c32 + call _Bs3SwitchTo16Bit_c32 + BS3_SET_BITS 16 +.return: + leave + retf + + BS3_SET_BITS 32 +.return_to_v86: + call [BS3_DATA16_WRT(BS3_CMN_NM(g_pfnBs3TestDoModesByOneCurrent))] + + ; Switch back to v8086 mode. + extern _Bs3SwitchTo16BitV86_c32 + call _Bs3SwitchTo16BitV86_c32 + BS3_SET_BITS 16 + jmp .return +BS3_PROC_END _Bs3TestCallDoerTo32_f16 + + +BS3_BEGIN_TEXT32 +BS3_SET_BITS 64 +BS3_PROC_BEGIN _Bs3TestCallDoerTo32_c64 + push xBP + mov xBP, xSP + + ; Load bMode into eax. + movzx eax, cl + %ifdef BS3_STRICT + cmp al, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + je .ok_mode + int3 +.ok_mode: + %endif + ; Switch to 32-bit. + extern _Bs3SwitchTo32Bit_c64 + call _Bs3SwitchTo32Bit_c64 + BS3_SET_BITS 32 + + push eax ; Worker bMode argument. + call [BS3_DATA16_WRT(BS3_CMN_NM(g_pfnBs3TestDoModesByOneCurrent))] + + ; Switch back to 64-bit mode. + extern _Bs3SwitchTo64Bit_c32 + call _Bs3SwitchTo64Bit_c32 + BS3_SET_BITS 64 + + leave + ret +BS3_PROC_END _Bs3TestCallDoerTo32_c64 + + +%elif TMPL_BITS == 64 +; +; 64-bit workers makes no sense, so skip that. +; +%else + %error "TMPL_BITS!" +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestFailed.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestFailed.c new file mode 100644 index 00000000..2fc104fa --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestFailed.c @@ -0,0 +1,151 @@ +/* $Id: bs3-cmn-TestFailed.c $ */ +/** @file + * BS3Kit - Bs3TestFailed, Bs3TestFailedF, Bs3TestFailedV. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-test.h" +#include <iprt/asm-amd64-x86.h> + + +/** + * @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'; +} + + +/** + * Equivalent to RTTestIFailedV. + */ +#undef Bs3TestFailedV +BS3_CMN_DEF(bool, Bs3TestFailedV,(const char *pszFormat, va_list BS3_FAR va)) +{ + BS3TESTFAILEDBUF Buf; + + if (!++g_cusBs3TestErrors) + g_cusBs3TestErrors++; + + if (g_fbBs3VMMDevTesting) +#if ARCH_BITS == 16 + ASMOutU16(VMMDEV_TESTING_IOPORT_CMD, (uint16_t)VMMDEV_TESTING_CMD_FAILED); +#else + ASMOutU32(VMMDEV_TESTING_IOPORT_CMD, VMMDEV_TESTING_CMD_FAILED); +#endif + + Buf.fNewLine = false; + Buf.cchBuf = 0; + Bs3StrFormatV(pszFormat, va, bs3TestFailedStrOutput, &Buf); + return false; +} + + +/** + * Equivalent to RTTestIFailedF. + */ +#undef Bs3TestFailedF +BS3_CMN_DEF(bool, Bs3TestFailedF,(const char *pszFormat, ...)) +{ + va_list va; + va_start(va, pszFormat); + BS3_CMN_NM(Bs3TestFailedV)(pszFormat, va); + va_end(va); + return false; +} + + +/** + * Equivalent to RTTestIFailed. + */ +#undef Bs3TestFailed +BS3_CMN_DEF(bool, Bs3TestFailed,(const char *pszMessage)) +{ + return BS3_CMN_NM(Bs3TestFailedF)("%s", pszMessage); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestHostPrintf.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestHostPrintf.c new file mode 100644 index 00000000..73622683 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestHostPrintf.c @@ -0,0 +1,114 @@ +/* $Id: bs3-cmn-TestHostPrintf.c $ */ +/** @file + * BS3Kit - BS3TestPrintf, BS3TestPrintfV + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-test.h" + +#include <iprt/asm-amd64-x86.h> + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +/** Output state for Bs3TestHostPrintfV. */ +typedef struct BS3TESTHOSTPRINTF +{ + bool fNewCmd; +} BS3TESTHOSTPRINTF; + + +/** + * @callback_method_impl{FNBS3STRFORMATOUTPUT, Prints to screen and VMMDev} + */ +static BS3_DECL_CALLBACK(size_t) bs3TestPrintfStrOutput(char ch, void BS3_FAR *pvUser) +{ + BS3TESTHOSTPRINTF BS3_FAR *pState = (BS3TESTHOSTPRINTF BS3_FAR *)pvUser; + + /* + * VMMDev first. We do line by line processing to avoid running out of + * string buffer on the host side. + */ + if (g_fbBs3VMMDevTesting) + { + if (ch != '\n' && !pState->fNewCmd) + ASMOutU8(VMMDEV_TESTING_IOPORT_DATA, ch); + else if (ch != '\0') + { + if (pState->fNewCmd) + { +#if ARCH_BITS == 16 + ASMOutU16(VMMDEV_TESTING_IOPORT_CMD, (uint16_t)VMMDEV_TESTING_CMD_PRINT); +#else + ASMOutU32(VMMDEV_TESTING_IOPORT_CMD, VMMDEV_TESTING_CMD_PRINT); +#endif + pState->fNewCmd = false; + } + ASMOutU8(VMMDEV_TESTING_IOPORT_DATA, ch); + if (ch == '\n') + { + ASMOutU8(VMMDEV_TESTING_IOPORT_DATA, '\0'); + pState->fNewCmd = true; + } + } + } + + return ch != '\0'; +} + + +#undef Bs3TestHostPrintfV +BS3_CMN_DEF(void, Bs3TestHostPrintfV,(const char BS3_FAR *pszFormat, va_list BS3_FAR va)) +{ + BS3TESTHOSTPRINTF State; + State.fNewCmd = true; + Bs3StrFormatV(pszFormat, va, bs3TestPrintfStrOutput, &State); +} + + + +#undef Bs3TestHostPrintf +BS3_CMN_DEF(void, Bs3TestHostPrintf,(const char BS3_FAR *pszFormat, ...)) +{ + va_list va; + va_start(va, pszFormat); + BS3_CMN_NM(Bs3TestHostPrintfV)(pszFormat, va); + va_end(va); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestInit.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestInit.c new file mode 100644 index 00000000..ad9b4123 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestInit.c @@ -0,0 +1,77 @@ +/* $Id: bs3-cmn-TestInit.c $ */ +/** @file + * BS3Kit - Bs3TestInit + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-test.h" + + +/** + * Equivalent to RTTestCreate + RTTestBanner. + * + * @param pszTest The test name. + */ +#undef Bs3TestInit +BS3_CMN_DEF(void, Bs3TestInit,(const char BS3_FAR *pszTest)) +{ + /* + * Initialize the globals. + */ + BS3_CMN_NM(g_pszBs3Test) = pszTest; + g_szBs3SubTest[0] = '\0'; + g_cusBs3TestErrors = 0; + g_cusBs3SubTestAtErrors = 0; + g_fbBs3SubTestReported = true; + g_fbBs3SubTestSkipped = false; + g_cusBs3SubTests = 0; + g_cusBs3SubTestsFailed = 0; + g_fbBs3VMMDevTesting = bs3TestIsVmmDevTestingPresent(); + + /* + * Print the name - RTTestBanner. + */ + Bs3PrintStr(pszTest); + Bs3PrintStr(": TESTING...\n"); + + /* + * Report it to the VMMDev. + */ + bs3TestSendCmdWithStr(VMMDEV_TESTING_CMD_INIT, pszTest); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestIsVmmDevTestingPresent.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestIsVmmDevTestingPresent.asm new file mode 100644 index 00000000..08c089db --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestIsVmmDevTestingPresent.asm @@ -0,0 +1,78 @@ +; $Id: bs3-cmn-TestIsVmmDevTestingPresent.asm $ +;; @file +; BS3Kit - bs3TestIsVmmDevTestingPresent +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" +%include "VBox/VMMDevTesting.mac" + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_EXTERN_DATA16 g_uBs3CpuDetected +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_DECL(bool) bs3TestIsVmmDevTestingPresent_c16(void); +; +BS3_PROC_BEGIN_CMN bs3TestIsVmmDevTestingPresent, BS3_PBC_HYBRID_0_ARGS + BS3_CALL_CONV_PROLOG 2 + push xBP + mov xBP, xSP + push xDX + + ; Check the response from the NOP port. + mov dx, VMMDEV_TESTING_IOPORT_NOP + cmp byte [g_uBs3CpuDetected], BS3CPU_80386 + jb .ancient_cpu + in eax, dx + cmp eax, VMMDEV_TESTING_NOP_RET +.set_ax_and_return: + mov ax, 0 + jne .return + mov ax, 1 + +.return: + pop xDX + pop xBP + BS3_CALL_CONV_EPILOG 2 + BS3_HYBRID_RET + +.ancient_cpu: + in ax, dx + cmp ax, (VMMDEV_TESTING_NOP_RET & 0xffff) + jmp .set_ax_and_return +BS3_PROC_END_CMN bs3TestIsVmmDevTestingPresent + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestNow.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestNow.asm new file mode 100644 index 00000000..c5ab98fe --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestNow.asm @@ -0,0 +1,113 @@ +; $Id: bs3-cmn-TestNow.asm $ +;; @file +; BS3Kit - Bs3TestNow. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" +%include "VBox/VMMDevTesting.mac" + +BS3_EXTERN_DATA16 g_fbBs3VMMDevTesting +TMPL_BEGIN_TEXT + +;; +; @cproto BS3_DECL(uint64_t) Bs3TestNow(void); +; +; @uses eflags, return register(s) +; +BS3_PROC_BEGIN_CMN Bs3TestNow, BS3_PBC_HYBRID + BS3_CALL_CONV_PROLOG 0 + push xBP + mov xBP, xSP +%if __BITS__ == 16 +BONLY16 push sAX +%else + push xCX +BONLY64 push xDX +%endif + + cmp byte [BS3_DATA16_WRT(g_fbBs3VMMDevTesting)], 0 + je .no_vmmdev + + ; Read the lower timestamp. + mov dx, VMMDEV_TESTING_IOPORT_TS_LOW + in eax, dx +%if __BITS__ == 16 + mov bx, ax ; Save the first word in BX (returned in DX). + shr eax, 16 + mov cx, ax ; The second word is returned in CX. +%else + mov ecx, eax +%endif + + ; Read the high timestamp (latached in above read). + mov dx, VMMDEV_TESTING_IOPORT_TS_HIGH + in eax, dx +%if __BITS__ == 16 + mov dx, bx ; The first word is returned in DX. + mov bx, ax ; The third word is returned in BX. + shr eax, 16 ; The fourth word is returned in AX. +%elif __BITS__ == 32 + mov edx, eax + mov eax, ecx +%else + shl rax, 32 + or rax, rcx +%endif + +.return: +%if __BITS__ == 16 + mov [bp - sCB], ax ; Update the AX part of the saved EAX. + pop sAX +%else + pop xCX +BONLY64 pop xDX +%endif + pop xBP + BS3_CALL_CONV_EPILOG 0 + BS3_HYBRID_RET + +.no_vmmdev: + ; No fallback, just zero the result. +%if __BITS__ == 16 + xor ax, ax + xor bx, bx + xor cx, cx + xor dx, dx +%else + xor eax, eax +BONLY32 xor edx, edx +%endif + jmp .return +BS3_PROC_END_CMN Bs3TestNow + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestPrintf.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestPrintf.c new file mode 100644 index 00000000..4b7df136 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestPrintf.c @@ -0,0 +1,146 @@ +/* $Id: bs3-cmn-TestPrintf.c $ */ +/** @file + * BS3Kit - BS3TestPrintf, BS3TestPrintfV + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-test.h" + +#include <iprt/asm-amd64-x86.h> + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +#define SMALL_BUFFER 1 + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +/** Output buffering for Bs3TestPrintfV. */ +typedef struct BS3TESTPRINTBUF +{ + bool fNewCmd; +#if SMALL_BUFFER + uint8_t cchBuf; + char achBuf[78]; +#else + uint16_t cchBuf; + char achBuf[512]; +#endif +} BS3TESTPRINTBUF; + + +/** + * @callback_method_impl{FNBS3STRFORMATOUTPUT, Prints to screen and VMMDev} + */ +static BS3_DECL_CALLBACK(size_t) bs3TestPrintfStrOutput(char ch, void BS3_FAR *pvUser) +{ + BS3TESTPRINTBUF BS3_FAR *pBuf = (BS3TESTPRINTBUF BS3_FAR *)pvUser; + + /* + * VMMDev first. We do line by line processing to avoid running out of + * string buffer on the host side. + */ + if (g_fbBs3VMMDevTesting) + { + if (ch != '\n' && !pBuf->fNewCmd) + ASMOutU8(VMMDEV_TESTING_IOPORT_DATA, ch); + else if (ch != '\0') + { + if (pBuf->fNewCmd) + { +#if ARCH_BITS == 16 + ASMOutU16(VMMDEV_TESTING_IOPORT_CMD, (uint16_t)VMMDEV_TESTING_CMD_PRINT); +#else + ASMOutU32(VMMDEV_TESTING_IOPORT_CMD, VMMDEV_TESTING_CMD_PRINT); +#endif + pBuf->fNewCmd = false; + } + ASMOutU8(VMMDEV_TESTING_IOPORT_DATA, ch); + if (ch == '\n') + { + ASMOutU8(VMMDEV_TESTING_IOPORT_DATA, '\0'); + pBuf->fNewCmd = true; + } + } + } + + /* + * 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) + && (!SMALL_BUFFER || ch != '\n') ) + return 1; + } + BS3_ASSERT(pBuf->cchBuf <= RT_ELEMENTS(pBuf->achBuf)); + Bs3PrintStrN(&pBuf->achBuf[0], pBuf->cchBuf); + pBuf->cchBuf = 0; + return ch != '\0'; +} + + + +#undef Bs3TestPrintfV +BS3_CMN_DEF(void, Bs3TestPrintfV,(const char BS3_FAR *pszFormat, va_list BS3_FAR va)) +{ + BS3TESTPRINTBUF Buf; + Buf.fNewCmd = true; + Buf.cchBuf = 0; + Bs3StrFormatV(pszFormat, va, bs3TestPrintfStrOutput, &Buf); +} + + + +#undef Bs3TestPrintf +BS3_CMN_DEF(void, Bs3TestPrintf,(const char BS3_FAR *pszFormat, ...)) +{ + va_list va; + va_start(va, pszFormat); + BS3_CMN_NM(Bs3TestPrintfV)(pszFormat, va); + va_end(va); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestQueryCfgU32.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestQueryCfgU32.asm new file mode 100644 index 00000000..953b1e6d --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestQueryCfgU32.asm @@ -0,0 +1,94 @@ +; $Id: bs3-cmn-TestQueryCfgU32.asm $ +;; @file +; BS3Kit - Bs3TestQueryCfgU8. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" +%include "VBox/VMMDevTesting.mac" + +BS3_EXTERN_DATA16 g_fbBs3VMMDevTesting +TMPL_BEGIN_TEXT + +;; +; @cproto BS3_DECL(uint32_t) Bs3TestQueryCfgU32(uint16_t uCfg); +; +BS3_PROC_BEGIN_CMN Bs3TestQueryCfgU32, BS3_PBC_HYBRID + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP +TNOT16 push xDX + + cmp byte [BS3_DATA16_WRT(g_fbBs3VMMDevTesting)], 0 + je .no_vmmdev + + ; Issue the query command. + mov dx, VMMDEV_TESTING_IOPORT_CMD +%if TMPL_BITS == 16 + mov ax, VMMDEV_TESTING_CMD_QUERY_CFG - VMMDEV_TESTING_CMD_MAGIC_HI_WORD + out dx, ax +%else + mov eax, VMMDEV_TESTING_CMD_QUERY_CFG + out dx, eax +%endif + + ; Write what we wish to query. + mov ax, [xBP + xCB + cbCurRetAddr] + mov dx, VMMDEV_TESTING_IOPORT_DATA + out dx, ax + + ; Read back the result. +%if TMPL_BITS == 16 + in ax, dx + push ax + in ax, dx + mov dx, ax + pop ax +%else + in eax, dx +%endif + +.return: +TNOT16 pop xDX + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET + +.no_vmmdev: + xor xAX, xAX +%if TMPL_BITS == 16 + xor xDX, xDX +%endif + jmp .return +BS3_PROC_END_CMN Bs3TestQueryCfgU32 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestQueryCfgU8.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestQueryCfgU8.asm new file mode 100644 index 00000000..ea4aab19 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestQueryCfgU8.asm @@ -0,0 +1,86 @@ +; $Id: bs3-cmn-TestQueryCfgU8.asm $ +;; @file +; BS3Kit - Bs3TestQueryCfgU8, Bs3TestQueryCfgBool. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" +%include "VBox/VMMDevTesting.mac" + +BS3_EXTERN_DATA16 g_fbBs3VMMDevTesting +TMPL_BEGIN_TEXT + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestQueryCfgU8(uint16_t uCfg); +; @cproto BS3_DECL(bool) Bs3TestQueryCfgBool(uint16_t uCfg); +; +BS3_GLOBAL_NAME_EX BS3_CMN_NM(Bs3TestQueryCfgBool), function, 3 +BS3_PROC_BEGIN_CMN Bs3TestQueryCfgU8, BS3_PBC_HYBRID + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push xDX + + xor al, al + cmp byte [BS3_DATA16_WRT(g_fbBs3VMMDevTesting)], 0 + je .no_vmmdev + + ; Issue the query command. + mov dx, VMMDEV_TESTING_IOPORT_CMD +%if TMPL_BITS == 16 + mov ax, VMMDEV_TESTING_CMD_QUERY_CFG - VMMDEV_TESTING_CMD_MAGIC_HI_WORD + out dx, ax +%else + mov eax, VMMDEV_TESTING_CMD_QUERY_CFG + out dx, eax +%endif + + ; Write what we wish to query. + mov ax, [xBP + xCB + cbCurRetAddr] + mov dx, VMMDEV_TESTING_IOPORT_DATA + out dx, ax + + ; Read back the result. + in al, dx + +.no_vmmdev: + pop xDX + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3TestQueryCfgU8 + +%if TMPL_BITS == 16 +BS3_GLOBAL_NAME_EX BS3_CMN_NM_FAR(Bs3TestQueryCfgBool), function, 3 + jmp BS3_CMN_NM_FAR(Bs3TestQueryCfgU8) +%endif diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSendCmdWithStr.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSendCmdWithStr.asm new file mode 100644 index 00000000..4f61abc6 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSendCmdWithStr.asm @@ -0,0 +1,90 @@ +; $Id: bs3-cmn-TestSendCmdWithStr.asm $ +;; @file +; BS3Kit - bs3TestSendStrCmd. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" +%include "VBox/VMMDevTesting.mac" + +BS3_EXTERN_DATA16 g_fbBs3VMMDevTesting +TMPL_BEGIN_TEXT + +;; +; @cproto BS3_DECL(void) bs3TestSendCmdWithStr_c16(uint32_t uCmd, const char BS3_FAR *pszString); +; +BS3_PROC_BEGIN_CMN bs3TestSendCmdWithStr, BS3_PBC_HYBRID + BS3_CALL_CONV_PROLOG 2 + push xBP + mov xBP, xSP + push xAX + push xDX + push xSI +BONLY16 push ds + + cmp byte [BS3_DATA16_WRT(g_fbBs3VMMDevTesting)], 0 + je .no_vmmdev + + ; The command (uCmd). + mov dx, VMMDEV_TESTING_IOPORT_CMD +%if TMPL_BITS == 16 + mov ax, [xBP + xCB + cbCurRetAddr] ; We ignore the top bits in 16-bit mode. + out dx, ax +%else + mov eax, [xBP + xCB + cbCurRetAddr] + out dx, eax +%endif + + ; The string. + mov dx, VMMDEV_TESTING_IOPORT_DATA +%if TMPL_BITS == 16 + lds si, [xBP + xCB + cbCurRetAddr + sCB] +%else + mov xSI, [xBP + xCB + cbCurRetAddr + sCB] +%endif +.next_char: + lodsb + out dx, al + test al, al + jnz .next_char + +.no_vmmdev: +BONLY16 pop ds + pop xSI + pop xDX + pop xAX + pop xBP + BS3_CALL_CONV_EPILOG 2 + BS3_HYBRID_RET +BS3_PROC_END_CMN bs3TestSendCmdWithStr + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSendCmdWithU32.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSendCmdWithU32.asm new file mode 100644 index 00000000..4062c1dc --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSendCmdWithU32.asm @@ -0,0 +1,88 @@ +; $Id: bs3-cmn-TestSendCmdWithU32.asm $ +;; @file +; BS3Kit - bs3TestSendCmdWithU32. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" +%include "VBox/VMMDevTesting.mac" + +BS3_EXTERN_DATA16 g_fbBs3VMMDevTesting +TMPL_BEGIN_TEXT + +;; +; @cproto BS3_DECL(void) bs3TestSendCmdWithU32_c16(uint32_t uCmd, uint32_t uValue); +; +BS3_PROC_BEGIN_CMN bs3TestSendCmdWithU32, BS3_PBC_HYBRID + BS3_CALL_CONV_PROLOG 2 + push xBP + mov xBP, xSP + push xAX + push xDX + push xSI + + cmp byte [BS3_DATA16_WRT(g_fbBs3VMMDevTesting)], 0 + je .no_vmmdev + + ; The command (uCmd) - + mov dx, VMMDEV_TESTING_IOPORT_CMD +%if TMPL_BITS == 16 + mov ax, [xBP + xCB + cbCurRetAddr] ; We ignore the top bits in 16-bit mode. + out dx, ax +%else + mov eax, [xBP + xCB*2] + out dx, eax +%endif + + + ; The value (uValue). + mov dx, VMMDEV_TESTING_IOPORT_DATA +%if TMPL_BITS == 16 + mov ax, [xBP + xCB + cbCurRetAddr + sCB] + out dx, ax + mov ax, [xBP + xCB + cbCurRetAddr + sCB + 2] + out dx, ax +%else + mov eax, [xBP + xCB*2 + sCB] + out dx, eax +%endif + +.no_vmmdev: + pop xSI + pop xDX + pop xAX + pop xBP + BS3_CALL_CONV_EPILOG 2 + BS3_HYBRID_RET +BS3_PROC_END_CMN bs3TestSendCmdWithU32 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSkipped.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSkipped.c new file mode 100644 index 00000000..4d7f0ec3 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSkipped.c @@ -0,0 +1,100 @@ +/* $Id: bs3-cmn-TestSkipped.c $ */ +/** @file + * BS3Kit - Bs3TestSkipped + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-test.h" +#include <iprt/asm-amd64-x86.h> + + +/** + * Equivalent to RTTestSkippedV. + */ +#undef Bs3TestSkippedV +BS3_CMN_DEF(void, Bs3TestSkippedV,(const char *pszFormat, va_list BS3_FAR va)) +{ + if (g_cusBs3TestErrors == g_cusBs3SubTestAtErrors) + { + /* Just mark it as skipped and deal with it when the sub-test is done. */ + g_fbBs3SubTestSkipped = true; + + /* Tell VMMDev */ + if (g_fbBs3VMMDevTesting) +#if ARCH_BITS == 16 + ASMOutU16(VMMDEV_TESTING_IOPORT_CMD, (uint16_t)VMMDEV_TESTING_CMD_SKIPPED); +#else + ASMOutU32(VMMDEV_TESTING_IOPORT_CMD, VMMDEV_TESTING_CMD_SKIPPED); +#endif + + /* The reason why it was skipped is optional. */ + if (pszFormat) + { + BS3TESTFAILEDBUF Buf; + Buf.fNewLine = false; + Buf.cchBuf = 0; + Bs3StrFormatV(pszFormat, va, bs3TestFailedStrOutput, &Buf); + } + else if (g_fbBs3VMMDevTesting) + ASMOutU8(VMMDEV_TESTING_IOPORT_DATA, 0); + } +} + + +/** + * Equivalent to RTTestSkipped. + */ +#undef Bs3TestSkippedF +BS3_CMN_DEF(void, Bs3TestSkippedF,(const char *pszFormat, ...)) +{ + va_list va; + va_start(va, pszFormat); + BS3_CMN_NM(Bs3TestSkippedV)(pszFormat, va); + va_end(va); +} + + +/** + * Equivalent to RTTestSkipped. + */ +#undef Bs3TestSkipped +BS3_CMN_DEF(void, Bs3TestSkipped,(const char *pszWhy)) +{ + BS3_CMN_NM(Bs3TestSkippedF)(pszWhy ? "%s" : NULL, pszWhy); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSub.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSub.c new file mode 100644 index 00000000..0f76b5b3 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSub.c @@ -0,0 +1,105 @@ +/* $Id: bs3-cmn-TestSub.c $ */ +/** @file + * BS3Kit - Bs3TestSub, Bs3TestSubF, Bs3TestSubV. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-test.h" + + + +/** + * Equivalent to RTTestISubV. + */ +#undef Bs3TestSubV +BS3_CMN_DEF(void, Bs3TestSubV,(const char *pszFormat, va_list BS3_FAR va)) +{ + size_t cch; + + /* + * Cleanup any previous sub-test. + */ + bs3TestSubCleanup(); + + /* + * Format the sub-test name and update globals. + */ + cch = Bs3StrPrintfV(g_szBs3SubTest, sizeof(g_szBs3SubTest), pszFormat, va); + g_cusBs3SubTestAtErrors = g_cusBs3TestErrors; + BS3_ASSERT(!g_fbBs3SubTestSkipped); + g_cusBs3SubTests++; + + /* + * Tell VMMDev and output to the console. + */ + bs3TestSendCmdWithStr(VMMDEV_TESTING_CMD_SUB_NEW, g_szBs3SubTest); + + Bs3PrintStr(g_szBs3SubTest); + Bs3PrintChr(':'); + do + Bs3PrintChr(' '); + while (cch++ < 48); + Bs3PrintStr(" TESTING\n"); + + /* The sub-test result is not yet reported. */ + g_fbBs3SubTestReported = false; +} + + +/** + * Equivalent to RTTestIFailedF. + */ +#undef Bs3TestSubF +BS3_CMN_DEF(void, Bs3TestSubF,(const char *pszFormat, ...)) +{ + va_list va; + va_start(va, pszFormat); + BS3_CMN_NM(Bs3TestSubV)(pszFormat, va); + va_end(va); +} + + +/** + * Equivalent to RTTestISub. + */ +#undef Bs3TestSub +BS3_CMN_DEF(void, Bs3TestSub,(const char *pszMessage)) +{ + BS3_CMN_NM(Bs3TestSubF)("%s", pszMessage); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSubDone.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSubDone.c new file mode 100644 index 00000000..e49d298d --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSubDone.c @@ -0,0 +1,54 @@ +/* $Id: bs3-cmn-TestSubDone.c $ */ +/** @file + * BS3Kit - Bs3TestSubDone. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-test.h" + + + +/** + * Equivalent to RTTestISubDone. + */ +#undef Bs3TestSubDone +BS3_CMN_DEF(void, Bs3TestSubDone,(void)) +{ + bs3TestSubCleanup(); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSubErrorCount.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSubErrorCount.c new file mode 100644 index 00000000..27d54f75 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSubErrorCount.c @@ -0,0 +1,54 @@ +/* $Id: bs3-cmn-TestSubErrorCount.c $ */ +/** @file + * BS3Kit - Bs3TestSubErrorCount. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-test.h" + + + +/** + * Equivalent to RTTestSubErrorCount. + */ +#undef Bs3TestSubErrorCount +BS3_CMN_DEF(uint16_t, Bs3TestSubErrorCount,(void)) +{ + return g_cusBs3TestErrors - g_cusBs3SubTestAtErrors; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestTerm.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestTerm.c new file mode 100644 index 00000000..1c2519ec --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestTerm.c @@ -0,0 +1,117 @@ +/* $Id: bs3-cmn-TestTerm.c $ */ +/** @file + * BS3Kit - Bs3TestTerm + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-test.h" + + + +/** + * Equivalent to rtTestSubCleanup + rtTestSubTestReport. + */ +BS3_DECL(void) bs3TestSubCleanup(void) +{ + if (g_szBs3SubTest[0] != '\0') + { + if (!g_fbBs3SubTestReported) + { + size_t cch; + uint16_t cErrors = g_cusBs3TestErrors - g_cusBs3SubTestAtErrors; + + /* Tell VMMDev. */ + bs3TestSendCmdWithU32(VMMDEV_TESTING_CMD_SUB_DONE, cErrors); + + /* Print result to the console. */ + Bs3PrintStr(g_szBs3SubTest); + Bs3PrintChr(':'); + cch = Bs3StrLen(g_szBs3SubTest); + do + Bs3PrintChr(' '); + while (cch++ < 49); + + if (!cErrors) + Bs3PrintStr(!g_fbBs3SubTestSkipped ? "PASSED\n" : "SKIPPED\n"); + else + { + g_cusBs3SubTestsFailed++; + Bs3Printf("FAILED (%u errors)\n", g_szBs3SubTest, cErrors); + } + } + + /* Reset the sub-test. */ + g_fbBs3SubTestReported = true; + g_fbBs3SubTestSkipped = false; + g_szBs3SubTest[0] = '\0'; + } +} + + +/** + * Equivalent to RTTestSummaryAndDestroy. + */ +#undef Bs3TestTerm +BS3_CMN_DEF(void, Bs3TestTerm,(void)) +{ + /* + * Close any current sub-test. + */ + bs3TestSubCleanup(); + + /* + * Report summary. + */ + if (BS3_CMN_NM(g_pszBs3Test)) + { + Bs3PrintStr(BS3_CMN_NM(g_pszBs3Test)); + if (g_cusBs3TestErrors == 0) + Bs3Printf(": SUCCESS (%u tests)\n", g_cusBs3SubTests); + else + Bs3Printf(": FAILURE - %u (%u of %u tests)\n", + g_cusBs3TestErrors, g_cusBs3SubTestsFailed, g_cusBs3SubTests); + } + + /* + * Tell VMMDev. + */ + bs3TestSendCmdWithU32(VMMDEV_TESTING_CMD_TERM, g_cusBs3TestErrors); + + BS3_CMN_NM(g_pszBs3Test) = NULL; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestValue.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestValue.c new file mode 100644 index 00000000..ad98aaab --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestValue.c @@ -0,0 +1,86 @@ +/* $Id: bs3-cmn-TestValue.c $ */ +/** @file + * BS3Kit - Bs3TestValue + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-test.h" + +#include <iprt/asm-amd64-x86.h> + + +#undef Bs3TestValue +BS3_CMN_DEF(void, Bs3TestValue,(const char BS3_FAR *pszName, uint64_t u64Value, uint8_t bUnit)) +{ + const char * const pszUnit = g_aszBs3TestUnitNames[bUnit]; + Bs3Printf(" %-48s: %'16llu %s\n", pszName, u64Value, pszUnit); + + /* + * Report it to the host. + */ + if (g_fbBs3VMMDevTesting) + { +#if ARCH_BITS == 16 + ASMOutU16(VMMDEV_TESTING_IOPORT_CMD, (uint16_t)VMMDEV_TESTING_CMD_VALUE); + ASMOutU16(VMMDEV_TESTING_IOPORT_DATA, (uint16_t)u64Value); + ASMOutU16(VMMDEV_TESTING_IOPORT_DATA, (uint16_t)(u64Value >> 16)); + ASMOutU16(VMMDEV_TESTING_IOPORT_DATA, (uint16_t)(u64Value >> 32)); + ASMOutU16(VMMDEV_TESTING_IOPORT_DATA, (uint16_t)(u64Value >> 48)); + ASMOutU16(VMMDEV_TESTING_IOPORT_DATA, (uint16_t)bUnit); + ASMOutU16(VMMDEV_TESTING_IOPORT_DATA, 0); +# if 1 + ASMOutStrU8(VMMDEV_TESTING_IOPORT_DATA, pszName, Bs3StrLen(pszName) + 1); +# else + for (;;) + { + uint8_t const b = *pszName++; + ASMOutU8(VMMDEV_TESTING_IOPORT_DATA, b); + if (!b) + break; + } +# endif +#else + ASMOutU32(VMMDEV_TESTING_IOPORT_CMD, VMMDEV_TESTING_CMD_VALUE); + ASMOutU32(VMMDEV_TESTING_IOPORT_DATA, (uint32_t)u64Value); + ASMOutU32(VMMDEV_TESTING_IOPORT_DATA, (uint32_t)(u64Value >> 32)); + ASMOutU32(VMMDEV_TESTING_IOPORT_DATA, (uint32_t)bUnit); + ASMOutStrU8(VMMDEV_TESTING_IOPORT_DATA, pszName, Bs3StrLen(pszName) + 1); +#endif + } +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap16Init.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap16Init.c new file mode 100644 index 00000000..be43260e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap16Init.c @@ -0,0 +1,129 @@ +/* $Id: bs3-cmn-Trap16Init.c $ */ +/** @file + * BS3Kit - Bs3Trap16Init + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +/* We ASSUME that BS3CLASS16CODE is 64KB aligned, so the low 16-bit of the + flat address matches. Also, these symbols are defined both with + and without underscore prefixes. */ +extern BS3_DECL(void) BS3_FAR_CODE Bs3Trap16DoubleFaultHandler80386(void); +extern BS3_DECL(void) BS3_FAR_CODE Bs3Trap16DoubleFaultHandler80286(void); +extern BS3_DECL(void) BS3_FAR_CODE Bs3Trap16GenericEntries(void); + +/* These two are ugly. Need data access for patching purposes. */ +extern uint8_t BS3_FAR_DATA bs3Trap16GenericTrapOrInt[]; + + +#undef Bs3Trap16InitEx +BS3_CMN_DEF(void, Bs3Trap16InitEx,(bool f386Plus)) +{ + X86TSS16 BS3_FAR *pTss; + unsigned iIdt; + + /* + * If 386 or later, patch the trap handler code to not jump to the 80286 + * code but continue with the next instruction (the 386+ code). + */ + if (f386Plus) + { + uint8_t BS3_FAR_DATA *pbFunction = &bs3Trap16GenericTrapOrInt[0]; +#if ARCH_BITS == 16 + if (g_bBs3CurrentMode != BS3_MODE_RM) + pbFunction = (uint8_t BS3_FAR_DATA *)BS3_FP_MAKE(BS3_SEL_TILED + 1, BS3_FP_OFF(pbFunction)); +#endif + pbFunction[1] = 0; + pbFunction[2] = 0; + } + + /* + * IDT entries, except the system call gate. + */ + for (iIdt = 0; iIdt < 256; iIdt++) + if (iIdt != BS3_TRAP_SYSCALL) + Bs3Trap16SetGate(iIdt, X86_SEL_TYPE_SYS_286_INT_GATE, 0 /*bDpl*/, + BS3_SEL_R0_CS16, (uint16_t)(uintptr_t)Bs3Trap16GenericEntries + iIdt * 8, 0 /*cParams*/); + + /* + * Initialize the normal TSS so we can do ring transitions via the IDT. + */ + pTss = &Bs3Tss16; + Bs3MemZero(pTss, sizeof(*pTss)); + pTss->sp0 = BS3_ADDR_STACK_R0; + pTss->ss0 = BS3_SEL_R0_SS16; + pTss->sp1 = BS3_ADDR_STACK_R1; + pTss->ss1 = BS3_SEL_R1_SS16 | 1; + pTss->sp2 = BS3_ADDR_STACK_R2; + pTss->ss2 = BS3_SEL_R2_SS16 | 2; + + /* + * Initialize the double fault TSS. + * cr3 is filled in by switcher code, when needed. + */ + pTss = &Bs3Tss16DoubleFault; + Bs3MemZero(pTss, sizeof(*pTss)); + pTss->sp0 = BS3_ADDR_STACK_R0; + pTss->ss0 = BS3_SEL_R0_SS16; + pTss->sp1 = BS3_ADDR_STACK_R1; + pTss->ss1 = BS3_SEL_R1_SS16 | 1; + pTss->sp2 = BS3_ADDR_STACK_R2; + pTss->ss2 = BS3_SEL_R2_SS16 | 2; + pTss->ip = (uint16_t)(uintptr_t)(f386Plus ? &Bs3Trap16DoubleFaultHandler80386 : &Bs3Trap16DoubleFaultHandler80286); + pTss->flags = X86_EFL_1; + pTss->sp = BS3_ADDR_STACK_R0_IST1; + pTss->es = BS3_SEL_R0_DS16; + pTss->ds = BS3_SEL_R0_DS16; + pTss->cs = BS3_SEL_R0_CS16; + pTss->ss = BS3_SEL_R0_SS16; + pTss->dx = f386Plus; + + Bs3Trap16SetGate(X86_XCPT_DF, X86_SEL_TYPE_SYS_TASK_GATE, 0 /*bDpl*/, BS3_SEL_TSS16_DF, 0, 0 /*cParams*/); +} + + +#undef Bs3Trap16Init +BS3_CMN_DEF(void, Bs3Trap16Init,(void)) +{ + BS3_CMN_NM(Bs3Trap16InitEx)((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap16SetGate.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap16SetGate.c new file mode 100644 index 00000000..1f70a2a5 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap16SetGate.c @@ -0,0 +1,62 @@ +/* $Id: bs3-cmn-Trap16SetGate.c $ */ +/** @file + * BS3Kit - Bs3Trap16SetGate + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3Trap16SetGate +BS3_CMN_DEF(void, Bs3Trap16SetGate,(uint8_t iIdt, uint8_t bType, uint8_t bDpl, uint16_t uSel, uint16_t off, uint8_t cParams)) +{ + X86DESC BS3_FAR *pIdte = &Bs3Idt16[iIdt]; + + BS3_ASSERT(bDpl <= 3); + BS3_ASSERT(bType <= 15); + BS3_ASSERT(cParams <= 15); + pIdte->Gate.u16OffsetLow = (uint16_t)off; + pIdte->Gate.u16OffsetHigh = 0; + pIdte->Gate.u16Sel = uSel; + pIdte->Gate.u5ParmCount = cParams; + pIdte->Gate.u4Type = bType; + pIdte->Gate.u2Dpl = bDpl; + pIdte->Gate.u3Reserved = 0; + pIdte->Gate.u1DescType = 0; /* system */ + pIdte->Gate.u1Present = 1; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap32Init.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap32Init.c new file mode 100644 index 00000000..3cf1ec82 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap32Init.c @@ -0,0 +1,101 @@ +/* $Id: bs3-cmn-Trap32Init.c $ */ +/** @file + * BS3Kit - Bs3Trap32Init + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +/********************************************************************************************************************************* +* External Symbols * +*********************************************************************************************************************************/ +#define g_Bs3Trap32DoubleFaultHandlerFlatAddr BS3_DATA_NM(g_Bs3Trap32DoubleFaultHandlerFlatAddr) +extern uint32_t g_Bs3Trap32DoubleFaultHandlerFlatAddr; + + +#undef Bs3Trap32Init +BS3_CMN_DEF(void, Bs3Trap32Init,(void)) +{ + X86TSS32 BS3_FAR *pTss; + unsigned iIdt; + + /* + * IDT entries, except the system call gate. + */ + for (iIdt = 0; iIdt < BS3_TRAP_SYSCALL; iIdt++) + Bs3Trap32SetGate(iIdt, X86_SEL_TYPE_SYS_386_INT_GATE, 0 /*bDpl*/, + BS3_SEL_R0_CS32, g_Bs3Trap32GenericEntriesFlatAddr + iIdt * 10, 0 /*cParams*/); + for (iIdt = BS3_TRAP_SYSCALL + 1; iIdt < 256; iIdt++) + Bs3Trap32SetGate(iIdt, X86_SEL_TYPE_SYS_386_INT_GATE, 0 /*bDpl*/, + BS3_SEL_R0_CS32, g_Bs3Trap32GenericEntriesFlatAddr + iIdt * 10, 0 /*cParams*/); + + /* + * Initialize the normal TSS so we can do ring transitions via the IDT. + */ + pTss = &Bs3Tss32; + Bs3MemZero(pTss, sizeof(*pTss)); + pTss->esp0 = BS3_ADDR_STACK_R0; + pTss->ss0 = BS3_SEL_R0_SS32; + pTss->esp1 = BS3_ADDR_STACK_R1; + pTss->ss1 = BS3_SEL_R1_SS32 | 1; + pTss->esp2 = BS3_ADDR_STACK_R2; + pTss->ss2 = BS3_SEL_R2_SS32 | 2; + + /* + * Initialize the double fault TSS. + * cr3 is filled in by switcher code, when needed. + */ + pTss = &Bs3Tss32DoubleFault; + Bs3MemZero(pTss, sizeof(*pTss)); + pTss->esp0 = BS3_ADDR_STACK_R0; + pTss->ss0 = BS3_SEL_R0_SS32; + pTss->esp1 = BS3_ADDR_STACK_R1; + pTss->ss1 = BS3_SEL_R1_SS32 | 1; + pTss->esp2 = BS3_ADDR_STACK_R2; + pTss->ss2 = BS3_SEL_R2_SS32 | 2; + pTss->eip = g_Bs3Trap32DoubleFaultHandlerFlatAddr; + pTss->eflags = X86_EFL_1; + pTss->esp = BS3_ADDR_STACK_R0_IST1; + pTss->es = BS3_SEL_R0_DS32; + pTss->ds = BS3_SEL_R0_DS32; + pTss->cs = BS3_SEL_R0_CS32; + pTss->ss = BS3_SEL_R0_SS32; + + Bs3Trap32SetGate(X86_XCPT_DF, X86_SEL_TYPE_SYS_TASK_GATE, 0 /*bDpl*/, BS3_SEL_TSS32_DF, 0, 0 /*cParams*/); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap32SetGate.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap32SetGate.c new file mode 100644 index 00000000..2501ea17 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap32SetGate.c @@ -0,0 +1,62 @@ +/* $Id: bs3-cmn-Trap32SetGate.c $ */ +/** @file + * BS3Kit - Bs3Trap32SetGate + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3Trap32SetGate +BS3_CMN_DEF(void, Bs3Trap32SetGate,(uint8_t iIdt, uint8_t bType, uint8_t bDpl, uint16_t uSel, uint32_t off, uint8_t cParams)) +{ + X86DESC BS3_FAR *pIdte = &Bs3Idt32[iIdt]; + + BS3_ASSERT(bDpl <= 3); + BS3_ASSERT(bType <= 15); + BS3_ASSERT(cParams <= 15); + pIdte->Gate.u16OffsetLow = (uint16_t)off; + pIdte->Gate.u16OffsetHigh = (uint16_t)(off >> 16); + pIdte->Gate.u16Sel = uSel; + pIdte->Gate.u5ParmCount = cParams; + pIdte->Gate.u4Type = bType; + pIdte->Gate.u2Dpl = bDpl; + pIdte->Gate.u3Reserved = 0; + pIdte->Gate.u1DescType = 0; /* system */ + pIdte->Gate.u1Present = 1; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap64Init.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap64Init.c new file mode 100644 index 00000000..98aad56d --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap64Init.c @@ -0,0 +1,109 @@ +/* $Id: bs3-cmn-Trap64Init.c $ */ +/** @file + * BS3Kit - Bs3Trap64Init + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3Trap64Init +BS3_CMN_DEF(void, Bs3Trap64Init,(void)) +{ + Bs3Trap64InitEx(false); +} + +#undef Bs3Trap64InitEx +BS3_CMN_DEF(void, Bs3Trap64InitEx,(bool fMoreIstUsage)) +{ + static const uint8_t s_aAssignments[] = + { + /* [X86_XCPT_DE] = */ 3, + /* [X86_XCPT_DB] = */ 2, + /* [X86_XCPT_NMI] = */ 0, + /* [X86_XCPT_BP] = */ 2, + /* [X86_XCPT_OF] = */ 3, + /* [X86_XCPT_BR] = */ 3, + /* [X86_XCPT_UD] = */ 4, + /* [X86_XCPT_NM] = */ 3, + /* [X86_XCPT_DF] = */ 1, + /* [0x09] = */ 0, + /* [X86_XCPT_TS] = */ 1, + /* [X86_XCPT_NP] = */ 5, + /* [X86_XCPT_SS] = */ 5, + /* [X86_XCPT_GP] = */ 6, + /* [X86_XCPT_PF] = */ 7, + /* [0x0f] = */ 0, + /* [X86_XCPT_MF] = */ 0, + /* [X86_XCPT_AC] = */ 3, + /* [X86_XCPT_MC] = */ 0, + /* [X86_XCPT_XF] = */ 0, + /* [X86_XCPT_VE] = */ 0, + /* [X86_XCPT_CP] = */ 6, + }; + X86TSS64 BS3_FAR *pTss; + unsigned iIdt; + + /* + * IDT entries, except the system call gate. + * The #DF entry get IST=1, all others IST=0. + */ + for (iIdt = 0; iIdt < BS3_TRAP_SYSCALL; iIdt++) + Bs3Trap64SetGate(iIdt, AMD64_SEL_TYPE_SYS_INT_GATE, 0 /*bDpl*/, + BS3_SEL_R0_CS64, g_Bs3Trap64GenericEntriesFlatAddr + iIdt * 8, + !fMoreIstUsage ? iIdt == X86_XCPT_DF : iIdt < RT_ELEMENTS(s_aAssignments) ? s_aAssignments[iIdt] : 0); + for (iIdt = BS3_TRAP_SYSCALL + 1; iIdt < 256; iIdt++) + Bs3Trap64SetGate(iIdt, AMD64_SEL_TYPE_SYS_INT_GATE, 0 /*bDpl*/, + BS3_SEL_R0_CS64, g_Bs3Trap64GenericEntriesFlatAddr + iIdt * 8, 0); + + /* + * Initialize the normal TSS so we can do ring transitions via the IDT. + */ + pTss = &Bs3Tss64; + Bs3MemZero(pTss, sizeof(*pTss)); + pTss->rsp0 = BS3_ADDR_STACK_R0; + pTss->rsp1 = BS3_ADDR_STACK_R1; + pTss->rsp2 = BS3_ADDR_STACK_R2; + pTss->ist1 = BS3_ADDR_STACK_R0_IST1; + pTss->ist2 = BS3_ADDR_STACK_R0_IST2; + pTss->ist3 = BS3_ADDR_STACK_R0_IST3; + pTss->ist4 = BS3_ADDR_STACK_R0_IST4; + pTss->ist5 = BS3_ADDR_STACK_R0_IST5; + pTss->ist6 = BS3_ADDR_STACK_R0_IST6; + pTss->ist7 = BS3_ADDR_STACK_R0_IST7; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap64SetGate.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap64SetGate.c new file mode 100644 index 00000000..6ca6d960 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap64SetGate.c @@ -0,0 +1,65 @@ +/* $Id: bs3-cmn-Trap64SetGate.c $ */ +/** @file + * BS3Kit - Bs3Trap64SetGate + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3Trap64SetGate +BS3_CMN_DEF(void, Bs3Trap64SetGate,(uint8_t iIdt, uint8_t bType, uint8_t bDpl, uint16_t uSel, uint64_t off, uint8_t bIst)) +{ + X86DESC64 BS3_FAR *pIdte = &Bs3Idt64[iIdt]; + + BS3_ASSERT(bDpl <= 3); + BS3_ASSERT(bType <= 15); + BS3_ASSERT(bIst <= 7); + pIdte->Gate.u16OffsetLow = (uint16_t)off; + pIdte->Gate.u16OffsetHigh = (uint16_t)((uint32_t)off >> 16); + pIdte->Gate.u32OffsetTop = (uint32_t)(off >> 32); + pIdte->Gate.u16Sel = uSel; + pIdte->Gate.u3IST = bIst; + pIdte->Gate.u4Type = bType; + pIdte->Gate.u2Dpl = bDpl; + pIdte->Gate.u5Reserved = 0; + pIdte->Gate.u1DescType = 0; /* system */ + pIdte->Gate.u1Present = 1; + pIdte->Gate.u32Reserved = 0; + +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapDefaultHandler.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapDefaultHandler.c new file mode 100644 index 00000000..76a5bdbd --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapDefaultHandler.c @@ -0,0 +1,331 @@ +/* $Id: bs3-cmn-TrapDefaultHandler.c $ */ +/** @file + * BS3Kit - Bs3TrapDefaultHandler + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#if TMPL_BITS != 64 +# include <VBox/VMMDevTesting.h> +# include <iprt/asm-amd64-x86.h> +#endif + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +#define g_pBs3TrapSetJmpFrame BS3_DATA_NM(g_pBs3TrapSetJmpFrame) +extern uint32_t g_pBs3TrapSetJmpFrame; + +#define g_Bs3TrapSetJmpCtx BS3_DATA_NM(g_Bs3TrapSetJmpCtx) +extern BS3REGCTX g_Bs3TrapSetJmpCtx; + + +#if TMPL_BITS != 64 +/** + * V86 syscall handler. + */ +static void bs3TrapDefaultHandlerV8086Syscall(PBS3TRAPFRAME pTrapFrame) +{ + /* Minimal syscall. */ + uint16_t uSyscallNo = pTrapFrame->Ctx.rax.u16; + if (uSyscallNo == BS3_SYSCALL_PRINT_CHR) + Bs3PrintChr(pTrapFrame->Ctx.rcx.u8); + else if (uSyscallNo == BS3_SYSCALL_PRINT_STR) + Bs3PrintStrN(Bs3XptrFlatToCurrent(((uint32_t)pTrapFrame->Ctx.rcx.u16 << 4) + pTrapFrame->Ctx.rsi.u16), + pTrapFrame->Ctx.rdx.u16); + else if (uSyscallNo == BS3_SYSCALL_RESTORE_CTX) + Bs3RegCtxRestore(Bs3XptrFlatToCurrent(((uint32_t)pTrapFrame->Ctx.rcx.u16 << 4) + pTrapFrame->Ctx.rsi.u16), + pTrapFrame->Ctx.rdx.u16); + else if ( uSyscallNo == BS3_SYSCALL_TO_RING0 + || uSyscallNo == BS3_SYSCALL_TO_RING1 + || uSyscallNo == BS3_SYSCALL_TO_RING2 + || uSyscallNo == BS3_SYSCALL_TO_RING3) + { + Bs3RegCtxConvertToRingX(&pTrapFrame->Ctx, pTrapFrame->Ctx.rax.u16 - BS3_SYSCALL_TO_RING0); + } + else if (uSyscallNo == BS3_SYSCALL_SET_DRX) + { + uint32_t uValue = pTrapFrame->Ctx.rsi.u32; + switch (pTrapFrame->Ctx.rdx.u8) + { + case 0: ASMSetDR0(uValue); break; + case 1: ASMSetDR1(uValue); break; + case 2: ASMSetDR2(uValue); break; + case 3: ASMSetDR3(uValue); break; + case 6: ASMSetDR6(uValue); break; + case 7: ASMSetDR7(uValue); break; + default: Bs3Panic(); + } + } + else if (uSyscallNo == BS3_SYSCALL_GET_DRX) + { + uint32_t uValue; + switch (pTrapFrame->Ctx.rdx.u8) + { + case 0: uValue = ASMGetDR0(); break; + case 1: uValue = ASMGetDR1(); break; + case 2: uValue = ASMGetDR2(); break; + case 3: uValue = ASMGetDR3(); break; + case 6: uValue = ASMGetDR6(); break; + case 7: uValue = ASMGetDR7(); break; + default: uValue = 0; Bs3Panic(); + } + pTrapFrame->Ctx.rax.u32 = uValue; + pTrapFrame->Ctx.rdx.u32 = uValue >> 16; + } + else if (uSyscallNo == BS3_SYSCALL_SET_CRX) + { + uint32_t uValue = pTrapFrame->Ctx.rsi.u32; + switch (pTrapFrame->Ctx.rdx.u8) + { + case 0: ASMSetCR0(uValue); pTrapFrame->Ctx.cr0.u32 = uValue; break; + case 2: ASMSetCR2(uValue); pTrapFrame->Ctx.cr2.u32 = uValue; break; + case 3: ASMSetCR3(uValue); pTrapFrame->Ctx.cr3.u32 = uValue; break; + case 4: ASMSetCR4(uValue); pTrapFrame->Ctx.cr4.u32 = uValue; break; + default: Bs3Panic(); + } + } + else if (uSyscallNo == BS3_SYSCALL_GET_CRX) + { + uint32_t uValue; + switch (pTrapFrame->Ctx.rdx.u8) + { + case 0: uValue = ASMGetCR0(); break; + case 2: uValue = ASMGetCR2(); break; + case 3: uValue = ASMGetCR3(); break; + case 4: uValue = ASMGetCR4(); break; + default: uValue = 0; Bs3Panic(); + } + pTrapFrame->Ctx.rax.u32 = uValue; + pTrapFrame->Ctx.rdx.u32 = uValue >> 16; + } + else if (uSyscallNo == BS3_SYSCALL_SET_TR) + { + Bs3RegSetTr(pTrapFrame->Ctx.rdx.u16); + pTrapFrame->Ctx.tr = pTrapFrame->Ctx.rdx.u16; + } + else if (uSyscallNo == BS3_SYSCALL_GET_TR) + pTrapFrame->Ctx.rax.u16 = ASMGetTR(); + else if (uSyscallNo == BS3_SYSCALL_SET_LDTR) + { + Bs3RegSetLdtr(pTrapFrame->Ctx.rdx.u16); + pTrapFrame->Ctx.ldtr = pTrapFrame->Ctx.rdx.u16; + } + else if (uSyscallNo == BS3_SYSCALL_GET_LDTR) + pTrapFrame->Ctx.rax.u16 = ASMGetLDTR(); + else if (uSyscallNo == BS3_SYSCALL_SET_XCR0) + ASMSetXcr0(RT_MAKE_U64(pTrapFrame->Ctx.rsi.u32, pTrapFrame->Ctx.rdx.u32)); + else if (uSyscallNo == BS3_SYSCALL_GET_XCR0) + { + uint64_t const uValue = ASMGetXcr0(); + pTrapFrame->Ctx.rax.u32 = (uint32_t)uValue; + pTrapFrame->Ctx.rdx.u32 = (uint32_t)(uValue >> 32); + } + else + Bs3Panic(); +} +#endif + +#undef Bs3TrapDefaultHandler +BS3_CMN_DEF(void, Bs3TrapDefaultHandler,(PBS3TRAPFRAME pTrapFrame)) +{ +#if TMPL_BITS != 64 + /* + * v8086 VMM tasks. + */ + //Bs3TestHostPrintf("Bs3____DefaultHandler: %02xh %04RX16:%08RX32 %08RX32 %04RX16:%08RX32 %d %d\n", pTrapFrame->bXcpt, + // pTrapFrame->Ctx.cs, pTrapFrame->Ctx.rip.u32, pTrapFrame->Ctx.rflags.u32, pTrapFrame->Ctx.ss, + // pTrapFrame->Ctx.rsp.u32, g_fBs3TrapNoV86Assist, 42); + if ((pTrapFrame->Ctx.rflags.u32 & X86_EFL_VM)) + { + bool fHandled = true; + uint8_t cBitsOpcode = 16; + uint8_t bOpCode; + uint8_t const BS3_FAR *pbCodeStart; + uint8_t const BS3_FAR *pbCode; + uint16_t BS3_FAR *pusStack; + + pusStack = (uint16_t BS3_FAR *)BS3_MAKE_PROT_R0PTR_FROM_REAL(pTrapFrame->Ctx.ss, pTrapFrame->Ctx.rsp.u16); + pbCode = (uint8_t const BS3_FAR *)BS3_MAKE_PROT_R0PTR_FROM_REAL(pTrapFrame->Ctx.cs, pTrapFrame->Ctx.rip.u16); + pbCodeStart = pbCode; + + /* + * Deal with GPs in V8086 mode. + */ + if ( pTrapFrame->bXcpt == X86_XCPT_GP + && !g_fBs3TrapNoV86Assist) + { + bOpCode = *pbCode++; + if (bOpCode == 0x66) + { + cBitsOpcode = 32; + bOpCode = *pbCode++; + } + + /* INT xx: Real mode behaviour, but intercepting and implementing most of our syscall interface. */ + if (bOpCode == 0xcd) + { + uint8_t bVector = *pbCode++; + if (bVector == BS3_TRAP_SYSCALL) + bs3TrapDefaultHandlerV8086Syscall(pTrapFrame); + else + { + /* Real mode behaviour. */ + uint16_t BS3_FAR *pusIvte = (uint16_t BS3_FAR *)BS3_MAKE_PROT_R0PTR_FROM_REAL(0, 0); + pusIvte += (uint16_t)bVector *2; + + pusStack[0] = pTrapFrame->Ctx.rflags.u16; + pusStack[1] = pTrapFrame->Ctx.cs; + pusStack[2] = pTrapFrame->Ctx.rip.u16 + (uint16_t)(pbCode - pbCodeStart); + + pTrapFrame->Ctx.rip.u16 = pusIvte[0]; + pTrapFrame->Ctx.cs = pusIvte[1]; + pTrapFrame->Ctx.rflags.u16 &= ~X86_EFL_IF; /** @todo this isn't all, but it'll do for now, I hope. */ + Bs3RegCtxRestore(&pTrapFrame->Ctx, 0/*fFlags*/); /* does not return. */ + } + } + /* PUSHF: Real mode behaviour. */ + else if (bOpCode == 0x9c) + { + if (cBitsOpcode == 32) + *pusStack++ = pTrapFrame->Ctx.rflags.au16[1] & ~(X86_EFL_VM | X86_EFL_RF); + *pusStack++ = pTrapFrame->Ctx.rflags.u16; + pTrapFrame->Ctx.rsp.u16 += cBitsOpcode / 8; + } + /* POPF: Real mode behaviour. */ + else if (bOpCode == 0x9d) + { + if (cBitsOpcode == 32) + { + pTrapFrame->Ctx.rflags.u32 &= ~X86_EFL_POPF_BITS; + pTrapFrame->Ctx.rflags.u32 |= X86_EFL_POPF_BITS & *(uint32_t const *)pusStack; + } + else + { + pTrapFrame->Ctx.rflags.u32 &= ~(X86_EFL_POPF_BITS | UINT32_C(0xffff0000)) & ~X86_EFL_RF; + pTrapFrame->Ctx.rflags.u16 |= (uint16_t)X86_EFL_POPF_BITS & *pusStack; + } + pTrapFrame->Ctx.rsp.u16 -= cBitsOpcode / 8; + } + /* CLI: Real mode behaviour. */ + else if (bOpCode == 0xfa) + pTrapFrame->Ctx.rflags.u16 &= ~X86_EFL_IF; + /* STI: Real mode behaviour. */ + else if (bOpCode == 0xfb) + pTrapFrame->Ctx.rflags.u16 |= X86_EFL_IF; + /* OUT: byte I/O to VMMDev. */ + else if ( bOpCode == 0xee + && ((unsigned)(pTrapFrame->Ctx.rdx.u16 - VMMDEV_TESTING_IOPORT_BASE) < (unsigned)VMMDEV_TESTING_IOPORT_COUNT)) + ASMOutU8(pTrapFrame->Ctx.rdx.u16, pTrapFrame->Ctx.rax.u8); + /* OUT: [d]word I/O to VMMDev. */ + else if ( bOpCode == 0xef + && ((unsigned)(pTrapFrame->Ctx.rdx.u16 - VMMDEV_TESTING_IOPORT_BASE) < (unsigned)VMMDEV_TESTING_IOPORT_COUNT)) + { + if (cBitsOpcode != 32) + ASMOutU16(pTrapFrame->Ctx.rdx.u16, pTrapFrame->Ctx.rax.u16); + else + ASMOutU32(pTrapFrame->Ctx.rdx.u16, pTrapFrame->Ctx.rax.u32); + } + /* IN: byte I/O to VMMDev. */ + else if ( bOpCode == 0xec + && ((unsigned)(pTrapFrame->Ctx.rdx.u16 - VMMDEV_TESTING_IOPORT_BASE) < (unsigned)VMMDEV_TESTING_IOPORT_COUNT)) + pTrapFrame->Ctx.rax.u8 = ASMInU8(pTrapFrame->Ctx.rdx.u16); + /* IN: [d]word I/O to VMMDev. */ + else if ( bOpCode == 0xed + && ((unsigned)(pTrapFrame->Ctx.rdx.u16 - VMMDEV_TESTING_IOPORT_BASE) < (unsigned)VMMDEV_TESTING_IOPORT_COUNT)) + { + if (cBitsOpcode != 32) + pTrapFrame->Ctx.rax.u16 = ASMInU16(pTrapFrame->Ctx.rdx.u16); + else + pTrapFrame->Ctx.rax.u32 = ASMInU32(pTrapFrame->Ctx.rdx.u32); + } + /* Unexpected. */ + else + fHandled = false; + } + /* + * Deal with lock prefixed int xxh syscall in v8086 mode. + */ + else if ( pTrapFrame->bXcpt == X86_XCPT_UD + && pTrapFrame->Ctx.cs == BS3_SEL_TEXT16 + && pTrapFrame->Ctx.rax.u16 <= BS3_SYSCALL_LAST + && pbCode[0] == 0xf0 + && pbCode[1] == 0xcd + && pbCode[2] == BS3_TRAP_SYSCALL) + { + pbCode += 3; + bs3TrapDefaultHandlerV8086Syscall(pTrapFrame); + } + else + { + fHandled = false; + } + if (fHandled) + { + pTrapFrame->Ctx.rip.u16 += (uint16_t)(pbCode - pbCodeStart); +# if 0 + Bs3Printf("Calling Bs3RegCtxRestore\n"); + Bs3RegCtxPrint(&pTrapFrame->Ctx); +# endif + Bs3RegCtxRestore(&pTrapFrame->Ctx, 0 /*fFlags*/); /* does not return. */ + return; + } + } +#endif + + /* + * Any pending setjmp? + */ + if (g_pBs3TrapSetJmpFrame != 0) + { + PBS3TRAPFRAME pSetJmpFrame = (PBS3TRAPFRAME)Bs3XptrFlatToCurrent(g_pBs3TrapSetJmpFrame); + //Bs3Printf("Calling longjmp: pSetJmpFrame=%p (%#lx)\n", pSetJmpFrame, g_pBs3TrapSetJmpFrame); + g_pBs3TrapSetJmpFrame = 0; + Bs3MemCpy(pSetJmpFrame, pTrapFrame, sizeof(*pSetJmpFrame)); + //Bs3RegCtxPrint(&g_Bs3TrapSetJmpCtx); + Bs3RegCtxRestore(&g_Bs3TrapSetJmpCtx, 0 /*fFlags*/); + } + + /* + * Fatal. + */ + Bs3TestPrintf("*** GURU ***\n"); + Bs3TrapPrintFrame(pTrapFrame); + Bs3Panic(); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapHandlersData.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapHandlersData.asm new file mode 100644 index 00000000..89bfa799 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapHandlersData.asm @@ -0,0 +1,52 @@ +; $Id: bs3-cmn-TrapHandlersData.asm $ +;; @file +; BS3Kit - Per bit-count trap data. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + + +BS3_BEGIN_DATA16 + BS3_SET_BITS ARCH_BITS ; Override the 16-bit mode that BS3_BEGIN_DATA16 implies so we get a correct xCB value. + +;; Pointer C trap handlers. +;; Note! The 16-bit ones are all near so we can share them between real, v86 and prot mode. +;; Note! Must be in 16-bit data because of BS3TrapSetHandlerEx. +BS3_GLOBAL_NAME_EX BS3_CMN_NM(g_apfnBs3TrapHandlers), , 256 * xCB + resb (256 * xCB) + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapPrintFrame.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapPrintFrame.c new file mode 100644 index 00000000..ab3af490 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapPrintFrame.c @@ -0,0 +1,89 @@ +/* $Id: bs3-cmn-TrapPrintFrame.c $ */ +/** @file + * BS3Kit - Bs3TrapPrintFrame + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3TrapPrintFrame +BS3_CMN_DEF(void, Bs3TrapPrintFrame,(PCBS3TRAPFRAME pTrapFrame)) +{ +#if 1 + Bs3TestPrintf("Trap %#04x errcd=%#06RX64 at %04x:%016RX64 - test step %d (%#x)\n" + "Handler: ss:rsp=%04x:%08RX64 cs=%04x cbIret=%#x rflags=%#06RX64\n" + , + pTrapFrame->bXcpt, + pTrapFrame->uErrCd, + pTrapFrame->Ctx.cs, + pTrapFrame->Ctx.rip.u64, + g_usBs3TestStep, g_usBs3TestStep, + pTrapFrame->uHandlerSs, + pTrapFrame->uHandlerRsp, + pTrapFrame->uHandlerCs, + pTrapFrame->cbIretFrame, + pTrapFrame->fHandlerRfl); + Bs3RegCtxPrint(&pTrapFrame->Ctx); +#else + /* This is useful if having trouble returning from real mode. */ + PCBS3REGCTX pRegCtx = &pTrapFrame->Ctx; + Bs3TestPrintf("Trap %#04x errcd=%#06RX64 at %04x:%016RX64 - test step %d (%#x)\n" + "eax=%08RX32 ebx=%08RX32 ecx=%08RX32 edx=%08RX32 esi=%08RX32 edi=%08RX32\n" + "eip=%08RX32 esp=%08RX32 ebp=%08RX32 efl=%08RX32 cr0=%08RX32 cr2=%08RX32\n" + "cs=%04RX16 ds=%04RX16 es=%04RX16 fs=%04RX16 gs=%04RX16 ss=%04RX16 cr3=%08RX32 cr4=%08RX32\n" + "tr=%04RX16 ldtr=%04RX16 cpl=%d mode=%#x fbFlags=%#x\n" + , + pTrapFrame->bXcpt, + pTrapFrame->uErrCd, + pTrapFrame->Ctx.cs, + pTrapFrame->Ctx.rip.u64, + g_usBs3TestStep, g_usBs3TestStep + , + pRegCtx->rax.u32, pRegCtx->rbx.u32, pRegCtx->rcx.u32, pRegCtx->rdx.u32, pRegCtx->rsi.u32, pRegCtx->rdi.u32 + , + pRegCtx->rip.u32, pRegCtx->rsp.u32, pRegCtx->rbp.u32, pRegCtx->rflags.u32, + pRegCtx->cr0.u32, pRegCtx->cr2.u32 + , + pRegCtx->cs, pRegCtx->ds, pRegCtx->es, pRegCtx->fs, pRegCtx->gs, pRegCtx->ss, + pRegCtx->cr3.u32, pRegCtx->cr4.u32 + , + pRegCtx->tr, pRegCtx->ldtr, pRegCtx->bCpl, pRegCtx->bMode, pRegCtx->fbFlags); + +#endif +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapReInit.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapReInit.c new file mode 100644 index 00000000..879de0fb --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapReInit.c @@ -0,0 +1,65 @@ +/* $Id: bs3-cmn-TrapReInit.c $ */ +/** @file + * BS3Kit - Bs3TrapReInit + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3TrapReInit +BS3_CMN_DEF(void, Bs3TrapReInit,(void)) +{ + if (BS3_MODE_IS_RM_SYS(g_bBs3CurrentMode)) + Bs3TrapRmV86Init(); + else if (BS3_MODE_IS_16BIT_SYS(g_bBs3CurrentMode)) + { + Bs3TrapRmV86Init(); + Bs3Trap16Init(); + } + else if (BS3_MODE_IS_32BIT_SYS(g_bBs3CurrentMode)) + { + Bs3TrapRmV86Init(); + Bs3Trap32Init(); + } + else + { + BS3_ASSERT(BS3_MODE_IS_64BIT_SYS(g_bBs3CurrentMode)); + Bs3Trap64Init(); + } +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapRmV86Init.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapRmV86Init.c new file mode 100644 index 00000000..38dc3a5a --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapRmV86Init.c @@ -0,0 +1,122 @@ +/* $Id: bs3-cmn-TrapRmV86Init.c $ */ +/** @file + * BS3Kit - Bs3TrapRmV86Init + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +/* We ASSUME that BS3CLASS16CODE is 64KB aligned, so the low 16-bit of the + flat address matches. Also, these symbols are defined both with + and without underscore prefixes. */ +extern BS3_DECL(void) BS3_FAR_CODE Bs3TrapRmV86GenericEntries(void); + +/* These two are ugly. Need data access for patching purposes. */ +extern uint8_t BS3_FAR_DATA bs3TrapRmV86GenericTrapOrInt[]; + +/* bs3-cmn-TrapRmV86Data.c: */ +#define g_fBs3RmIvtCopied BS3_DATA_NM(g_fBs3RmIvtCopied) +extern bool g_fBs3RmIvtCopied; + + +#undef Bs3TrapRmV86InitEx +BS3_CMN_DEF(void, Bs3TrapRmV86InitEx,(bool f386Plus)) +{ + RTFAR16 BS3_FAR *paIvt = Bs3XptrFlatToCurrent(0); + unsigned iIvt; + + /* + * Copy the real mode IVT the first time we are here. + */ + if (!g_fBs3RmIvtCopied) + { + Bs3MemCpy(g_aBs3RmIvtOriginal, paIvt, sizeof(g_aBs3RmIvtOriginal)); + g_fBs3RmIvtCopied = true; + } + /* + * The rest of the times, we copy back the original and modify it. + */ + else + Bs3MemCpy(paIvt, g_aBs3RmIvtOriginal, sizeof(g_aBs3RmIvtOriginal)); + + + /* + * If 386 or later, patch the trap handler code to not jump to the 80286 + * code but continue with the next instruction (the 386+ code). + */ + if (f386Plus) + { + uint8_t BS3_FAR_DATA *pbFunction = &bs3TrapRmV86GenericTrapOrInt[0]; +#if ARCH_BITS == 16 + if (g_bBs3CurrentMode != BS3_MODE_RM) + pbFunction = (uint8_t BS3_FAR_DATA *)BS3_FP_MAKE(BS3_SEL_TILED + 1, BS3_FP_OFF(pbFunction)); +#endif + pbFunction[1] = 0; + pbFunction[2] = 0; + } + + /* + * Since we want to play with V86 mode as well as 8086 and 186 CPUs, we + * cannot move the IVT from its default location. So, modify it in place. + * + * Note! We must keep INT 10h working, which is easy since the CPU does + * use it (well, it's been reserved for 30+ years). + * Turns out we must not hook INT 6Dh either then, as some real VGA + * BIOS installs their INT 10h handler there as well, and seemingly + * must be using it internally or something. + * + * We also keep 15h working for memory interfaces (see bs3-mode-BiosInt15*). + */ + for (iIvt = 0; iIvt < 256; iIvt++) + if (iIvt != 0x10 && iIvt != 0x15 && iIvt != 0x6d && iIvt != BS3_TRAP_SYSCALL) + { + paIvt[iIvt].off = (uint16_t)(uintptr_t)Bs3TrapRmV86GenericEntries + iIvt * 8; + paIvt[iIvt].sel = BS3_SEL_TEXT16; + } +} + + +#undef Bs3TrapRmV86Init +BS3_CMN_DEF(void, Bs3TrapRmV86Init,(void)) +{ + BS3_CMN_NM(Bs3TrapRmV86InitEx)((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapRmV86SetGate.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapRmV86SetGate.c new file mode 100644 index 00000000..a8198298 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapRmV86SetGate.c @@ -0,0 +1,51 @@ +/* $Id: bs3-cmn-TrapRmV86SetGate.c $ */ +/** @file + * BS3Kit - Bs3TrapRmV86SetGate + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3TrapRmV86SetGate +BS3_CMN_DEF(void, Bs3TrapRmV86SetGate,(uint8_t iIvt, uint16_t uSeg, uint16_t off)) +{ + RTFAR16 BS3_FAR *paIvt = Bs3XptrFlatToCurrent(0); + paIvt[iIvt].off = off; + paIvt[iIvt].sel = uSeg; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetDpl.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetDpl.c new file mode 100644 index 00000000..9038ce7e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetDpl.c @@ -0,0 +1,57 @@ +/* $Id: bs3-cmn-TrapSetDpl.c $ */ +/** @file + * BS3Kit - Bs3TrapSetDpl + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3TrapSetDpl +BS3_CMN_DEF(uint8_t, Bs3TrapSetDpl,(uint8_t iIdt, uint8_t bDpl)) +{ + uint8_t bRet; + BS3_ASSERT(bDpl <= 3); + + Bs3Idt16[iIdt].Gate.u2Dpl = bDpl; + Bs3Idt32[iIdt].Gate.u2Dpl = bDpl; + bRet = Bs3Idt64[iIdt].Gate.u2Dpl; + Bs3Idt64[iIdt].Gate.u2Dpl = bDpl; + + return bRet; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetHandler.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetHandler.c new file mode 100644 index 00000000..1f4956d0 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetHandler.c @@ -0,0 +1,57 @@ +/* $Id: bs3-cmn-TrapSetHandler.c $ */ +/** @file + * BS3Kit - Bs3Trap32SetHandler + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +/********************************************************************************************************************************* +* External Symbols * +*********************************************************************************************************************************/ +extern PFNBS3TRAPHANDLER BS3_DATA_NM(BS3_CMN_NM(g_apfnBs3TrapHandlers))[256]; + + +#undef Bs3TrapSetHandler +BS3_CMN_DEF(PFNBS3TRAPHANDLER, Bs3TrapSetHandler,(uint8_t iIdt, PFNBS3TRAPHANDLER pfnHandler)) +{ + PFNBS3TRAPHANDLER pfnOld = BS3_DATA_NM(BS3_CMN_NM(g_apfnBs3TrapHandlers))[iIdt]; + BS3_DATA_NM(BS3_CMN_NM(g_apfnBs3TrapHandlers))[iIdt] = pfnHandler; + return pfnOld; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetHandlerEx.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetHandlerEx.c new file mode 100644 index 00000000..a80c380e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetHandlerEx.c @@ -0,0 +1,71 @@ +/* $Id: bs3-cmn-TrapSetHandlerEx.c $ */ +/** @file + * BS3Kit - Bs3Trap32SetHandlerEx + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include <iprt/asm-amd64-x86.h> + + +/********************************************************************************************************************************* +* External Symbols * +*********************************************************************************************************************************/ +extern uint16_t BS3_DATA_NM(g_apfnBs3TrapHandlers_c16)[256]; +extern uint32_t BS3_DATA_NM(g_apfnBs3TrapHandlers_c32)[256]; +extern uint64_t BS3_DATA_NM(g_apfnBs3TrapHandlers_c64)[256]; + + +#undef Bs3TrapSetHandlerEx +BS3_CMN_DEF(void, Bs3TrapSetHandlerEx,(uint8_t iIdt, PFNBS3TRAPHANDLER16 pfnHandler16, + PFNBS3TRAPHANDLER32 pfnHandler32, PFNBS3TRAPHANDLER64 pfnHandler64)) +{ + RTCCUINTREG fFlags = ASMIntDisableFlags(); +#if ARCH_BITS == 16 + /* Far real mode pointers as input. */ + g_apfnBs3TrapHandlers_c16[iIdt] = (uint16_t)pfnHandler16; + g_apfnBs3TrapHandlers_c32[iIdt] = Bs3SelRealModeCodeToFlat((PFNBS3FARADDRCONV)pfnHandler32); + g_apfnBs3TrapHandlers_c64[iIdt] = Bs3SelRealModeCodeToFlat((PFNBS3FARADDRCONV)pfnHandler64); +#else + /* Flat pointers as input. */ + g_apfnBs3TrapHandlers_c16[iIdt] = (uint16_t)Bs3SelFlatCodeToProtFar16((uintptr_t)pfnHandler16); + g_apfnBs3TrapHandlers_c32[iIdt] = (uint32_t)(uintptr_t)pfnHandler32; + g_apfnBs3TrapHandlers_c64[iIdt] = (uintptr_t)pfnHandler64; +#endif + ASMSetFlags(fFlags); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmp.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmp.asm new file mode 100644 index 00000000..495f77d1 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmp.asm @@ -0,0 +1,143 @@ +; $Id: bs3-cmn-TrapSetJmp.asm $ +;; @file +; BS3Kit - Bs3TrapSetJmp. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_EXTERN_CMN Bs3RegCtxSave +%if TMPL_BITS == 16 +BS3_EXTERN_CMN_FAR Bs3SelFar32ToFlat32 +%endif +BS3_EXTERN_DATA16 g_Bs3TrapSetJmpCtx +BS3_EXTERN_DATA16 g_pBs3TrapSetJmpFrame +TMPL_BEGIN_TEXT + + +;; +; Sets up a one-shot set-jmp-on-trap. +; +; @uses See, applicable C calling convention. +; +BS3_PROC_BEGIN_CMN Bs3TrapSetJmp, BS3_PBC_HYBRID + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + push xBX +BONLY64 sub xSP, 20h + + ; + ; Save the current register context. + ; +BONLY16 push ds + BS3_LEA_MOV_WRT_RIP(xAX, BS3_DATA16_WRT(g_Bs3TrapSetJmpCtx)) + push xAX + BS3_CALL Bs3RegCtxSave, 1 + add xSP, sCB + + ; + ; Adjust the return context a little. + ; + BS3_LEA_MOV_WRT_RIP(xBX, BS3_DATA16_WRT(g_Bs3TrapSetJmpCtx)) + mov xAX, [xBP + xCB] ; The return address of this function + mov [xBX + BS3REGCTX.rip], xAX +%if TMPL_BITS == 16 + mov xAX, [xBP + xCB+2] ; The return address CS of this function. + mov [xBX + BS3REGCTX.cs], xAX +%endif + mov xAX, [xBP] + mov [xBX + BS3REGCTX.rbp], xAX + lea xAX, [xBP + xCB + cbCurRetAddr] + mov [xBX + BS3REGCTX.rsp], xAX + mov xAX, [xBP - xCB] + mov [xBX + BS3REGCTX.rbx], xAX + xor xAX, xAX + mov [xBX + BS3REGCTX.rax], xAX ; the return value. + + ; + ; Fill the trap frame return structure. + ; + push xDI +%if TMPL_BITS == 16 + push es + les di, [xBP + xCB + cbCurRetAddr] + mov cx, BS3TRAPFRAME_size / 2 + mov ax, 0faceh + rep stosw + pop es +%else + mov xDI, [xBP + xCB*2] + mov ecx, BS3TRAPFRAME_size / 4 + mov xAX, 0feedfaceh + rep stosd +%endif + pop xDI + + ; + ; Save the (flat) pointer to the trap frame return structure. + ; +%if TMPL_BITS == 16 + xor ax, ax + push word [xBP + xCB + cbCurRetAddr + 2] + push ax + push word [xBP + xCB + cbCurRetAddr] + push cs + call Bs3SelFar32ToFlat32 + add sp, 6h + mov [BS3_DATA16_WRT(g_pBs3TrapSetJmpFrame)], ax + mov [2 + BS3_DATA16_WRT(g_pBs3TrapSetJmpFrame)], dx +%else + mov xAX, [xBP + xCB*2] + mov [BS3_DATA16_WRT(g_pBs3TrapSetJmpFrame)], eax +%endif + + ; + ; Return 'true'. + ; + mov xAX, 1 +BONLY64 add xSP, 20h + pop xBX + pop xBP + BS3_CALL_CONV_EPILOG 1 + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3TrapSetJmp + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestore.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestore.c new file mode 100644 index 00000000..74c03371 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestore.c @@ -0,0 +1,56 @@ +/* $Id: bs3-cmn-TrapSetJmpAndRestore.c $ */ +/** @file + * BS3Kit - Bs3TrapSetJmpAndRestore + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3TrapSetJmpAndRestore +BS3_CMN_DEF(void, Bs3TrapSetJmpAndRestore,(PCBS3REGCTX pCtxRestore, PBS3TRAPFRAME pTrapFrame)) +{ + if (Bs3TrapSetJmp(pTrapFrame)) + { +#if TMPL_BITS == 32 + g_uBs3TrapEipHint = pCtxRestore->rip.u32; +#endif + Bs3RegCtxRestore(pCtxRestore, BS3REGCTXRESTORE_F_NO_V86_ASSIST); + } + g_fBs3TrapNoV86Assist = false; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestoreInRm.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestoreInRm.c new file mode 100644 index 00000000..bd8175c9 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestoreInRm.c @@ -0,0 +1,133 @@ +/* $Id: bs3-cmn-TrapSetJmpAndRestoreInRm.c $ */ +/** @file + * BS3Kit - Bs3TrapSetJmpAndRestoreInRm + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +/********************************************************************************************************************************* +* Internal Functions * +*********************************************************************************************************************************/ +/* assembly helpers */ +BS3_MODE_PROTO_NOSB(void, Bs3TrapSetJmpAndRestoreInRmAsm, (uint32_t, uint32_t)); + + +#undef Bs3TrapSetJmpAndRestoreInRm +BS3_CMN_DEF(void, Bs3TrapSetJmpAndRestoreInRm,(PCBS3REGCTX pCtxRestore, PBS3TRAPFRAME pTrapFrame)) +{ +#if TMPL_BITS == 16 + if (g_bBs3CurrentMode == BS3_MODE_RM) + Bs3TrapSetJmpAndRestore(pCtxRestore, pTrapFrame); + else +#endif + { + uint32_t const pfRealModeCtxRestore = Bs3SelFlatDataToRealMode(Bs3SelPtrToFlat((PBS3REGCTX)pCtxRestore)); + uint32_t const pfRealModeTrapFrame = Bs3SelFlatDataToRealMode(Bs3SelPtrToFlat(pTrapFrame)); + +#if TMPL_BITS == 16 + switch (g_bBs3CurrentMode & BS3_MODE_SYS_MASK) + { + case BS3_MODE_SYS_PE16: + Bs3TrapSetJmpAndRestoreInRmAsm_pe16(pfRealModeCtxRestore, pfRealModeTrapFrame); + break; + case BS3_MODE_SYS_PE32: + Bs3TrapSetJmpAndRestoreInRmAsm_pe32_16(pfRealModeCtxRestore, pfRealModeTrapFrame); + break; + case BS3_MODE_SYS_PP16: + Bs3TrapSetJmpAndRestoreInRmAsm_pp16(pfRealModeCtxRestore, pfRealModeTrapFrame); + break; + case BS3_MODE_SYS_PP32: + Bs3TrapSetJmpAndRestoreInRmAsm_pp32_16(pfRealModeCtxRestore, pfRealModeTrapFrame); + break; + case BS3_MODE_SYS_PAE16: + Bs3TrapSetJmpAndRestoreInRmAsm_pae16(pfRealModeCtxRestore, pfRealModeTrapFrame); + break; + case BS3_MODE_SYS_PAE32: + Bs3TrapSetJmpAndRestoreInRmAsm_pae32_16(pfRealModeCtxRestore, pfRealModeTrapFrame); + break; + case BS3_MODE_SYS_LM: + Bs3TrapSetJmpAndRestoreInRmAsm_lm16(pfRealModeCtxRestore, pfRealModeTrapFrame); + break; + default: + BS3_ASSERT(0); + } + +#elif TMPL_BITS == 32 + switch (g_bBs3CurrentMode & BS3_MODE_SYS_MASK) + { + case BS3_MODE_SYS_PE16: + Bs3TrapSetJmpAndRestoreInRmAsm_pe16_32(pfRealModeCtxRestore, pfRealModeTrapFrame); + break; + case BS3_MODE_SYS_PE32: + Bs3TrapSetJmpAndRestoreInRmAsm_pe32(pfRealModeCtxRestore, pfRealModeTrapFrame); + break; + case BS3_MODE_SYS_PP16: + Bs3TrapSetJmpAndRestoreInRmAsm_pp16_32(pfRealModeCtxRestore, pfRealModeTrapFrame); + break; + case BS3_MODE_SYS_PP32: + Bs3TrapSetJmpAndRestoreInRmAsm_pp32(pfRealModeCtxRestore, pfRealModeTrapFrame); + break; + case BS3_MODE_SYS_PAE16: + Bs3TrapSetJmpAndRestoreInRmAsm_pae16_32(pfRealModeCtxRestore, pfRealModeTrapFrame); + break; + case BS3_MODE_SYS_PAE32: + Bs3TrapSetJmpAndRestoreInRmAsm_pae32(pfRealModeCtxRestore, pfRealModeTrapFrame); + break; + case BS3_MODE_SYS_LM: + Bs3TrapSetJmpAndRestoreInRmAsm_lm32(pfRealModeCtxRestore, pfRealModeTrapFrame); + break; + default: + BS3_ASSERT(0); + } + +#elif TMPL_BITS == 64 + switch (g_bBs3CurrentMode & BS3_MODE_SYS_MASK) + { + case BS3_MODE_SYS_LM: + Bs3TrapSetJmpAndRestoreInRmAsm_lm64(pfRealModeCtxRestore, pfRealModeTrapFrame); + break; + default: + BS3_ASSERT(0); + } +#else +# error Bogus TMPL_BITS +#endif + } +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestoreWithExtCtx.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestoreWithExtCtx.c new file mode 100644 index 00000000..1b9dae0e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestoreWithExtCtx.c @@ -0,0 +1,61 @@ +/* $Id: bs3-cmn-TrapSetJmpAndRestoreWithExtCtx.c $ */ +/** @file + * BS3Kit - Bs3TrapSetJmpAndRestoreWithExtCtx + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3TrapSetJmpAndRestoreWithExtCtx +BS3_CMN_DEF(void, Bs3TrapSetJmpAndRestoreWithExtCtx,(PCBS3REGCTX pCtxRestore, PCBS3EXTCTX pExtCtxRestore, + PBS3TRAPFRAME pTrapFrame, PBS3EXTCTX pExtCtxTrap)) +{ + /* ASSUMES compile emits no SSE instructions between the calls here + (only a potential issue in 64-bit mode). */ + Bs3ExtCtxRestoreEx(pExtCtxRestore); + if (Bs3TrapSetJmp(pTrapFrame)) + { +#if TMPL_BITS == 32 + g_uBs3TrapEipHint = pCtxRestore->rip.u32; +#endif + Bs3RegCtxRestore(pCtxRestore, BS3REGCTXRESTORE_F_NO_V86_ASSIST); + } + g_fBs3TrapNoV86Assist = false; + Bs3ExtCtxSaveEx(pExtCtxTrap); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestoreWithExtCtxAndRm.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestoreWithExtCtxAndRm.c new file mode 100644 index 00000000..95d038a2 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestoreWithExtCtxAndRm.c @@ -0,0 +1,66 @@ +/* $Id: bs3-cmn-TrapSetJmpAndRestoreWithExtCtxAndRm.c $ */ +/** @file + * BS3Kit - Bs3TrapSetJmpAndRestoreWithExtCtxAndRm + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3TrapSetJmpAndRestoreWithExtCtxAndRm +BS3_CMN_DEF(void, Bs3TrapSetJmpAndRestoreWithExtCtxAndRm,(PCBS3REGCTX pCtxRestore, PCBS3EXTCTX pExtCtxRestore, + PBS3TRAPFRAME pTrapFrame, PBS3EXTCTX pExtCtxTrap)) +{ + if ( pCtxRestore->bMode != BS3_MODE_RM +#if ARCH_BITS == 16 + || g_bBs3CurrentMode == BS3_MODE_RM +#endif + ) + { + BS3_ASSERT((pCtxRestore->bMode & BS3_MODE_SYS_MASK) == (g_bBs3CurrentMode & BS3_MODE_SYS_MASK)); + Bs3TrapSetJmpAndRestoreWithExtCtx(pCtxRestore, pExtCtxRestore, pTrapFrame, pExtCtxTrap); + } + else + { + /* ASSUMES compile emits no SSE instructions between the calls here + (only a potential issue in 64-bit mode). */ + Bs3ExtCtxRestoreEx(pExtCtxRestore); + Bs3TrapSetJmpAndRestoreInRm(pCtxRestore, pTrapFrame); + Bs3ExtCtxSaveEx(pExtCtxTrap); + } +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestoreWithRm.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestoreWithRm.c new file mode 100644 index 00000000..c059690e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestoreWithRm.c @@ -0,0 +1,59 @@ +/* $Id: bs3-cmn-TrapSetJmpAndRestoreWithRm.c $ */ +/** @file + * BS3Kit - Bs3TrapSetJmpAndRestoreWithRm + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3TrapSetJmpAndRestoreWithRm +BS3_CMN_DEF(void, Bs3TrapSetJmpAndRestoreWithRm,(PCBS3REGCTX pCtxRestore, PBS3TRAPFRAME pTrapFrame)) +{ + if ( pCtxRestore->bMode != BS3_MODE_RM +#if ARCH_BITS == 16 + || g_bBs3CurrentMode == BS3_MODE_RM +#endif + ) + { + BS3_ASSERT((pCtxRestore->bMode & BS3_MODE_SYS_MASK) == (g_bBs3CurrentMode & BS3_MODE_SYS_MASK)); + Bs3TrapSetJmpAndRestore(pCtxRestore, pTrapFrame); + } + else + Bs3TrapSetJmpAndRestoreInRm(pCtxRestore, pTrapFrame); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapUnsetJmp.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapUnsetJmp.c new file mode 100644 index 00000000..8d26c905 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapUnsetJmp.c @@ -0,0 +1,58 @@ +/* $Id: bs3-cmn-TrapUnsetJmp.c $ */ +/** @file + * BS3Kit - Bs3TrapUnsetJmp + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +#ifndef DOXYGEN_RUNNING +# define g_pBs3TrapSetJmpFrame BS3_DATA_NM(g_pBs3TrapSetJmpFrame) +#endif +extern uint32_t g_pBs3TrapSetJmpFrame; + + +#undef Bs3TrapUnsetJmp +BS3_CMN_DEF(void, Bs3TrapUnsetJmp,(void)) +{ + g_pBs3TrapSetJmpFrame = 0; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-UInt32Div.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-UInt32Div.c new file mode 100644 index 00000000..73080a80 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-UInt32Div.c @@ -0,0 +1,50 @@ +/* $Id: bs3-cmn-UInt32Div.c $ */ +/** @file + * BS3Kit - Unsigned 32-bit division (compiler support routine helper). + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <bs3kit.h> +#include <iprt/uint32.h> + + +#undef Bs3UInt32Div +BS3_CMN_DEF(void, Bs3UInt32Div,(RTUINT32U uDividend, RTUINT32U uDivisor, RTUINT32U BS3_FAR *paQuotientReminder)) +{ + RTUInt32DivRem(&paQuotientReminder[0], &paQuotientReminder[1], &uDividend, &uDivisor); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-UInt64Div.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-UInt64Div.c new file mode 100644 index 00000000..6d705209 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-UInt64Div.c @@ -0,0 +1,50 @@ +/* $Id: bs3-cmn-UInt64Div.c $ */ +/** @file + * BS3Kit - Unsigned 64-bit division (compiler support routine helper). + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <bs3kit.h> +#include <iprt/uint64.h> + + +#undef Bs3UInt64Div +BS3_CMN_DEF(void, Bs3UInt64Div,(RTUINT64U uDividend, RTUINT64U uDivisor, RTUINT64U BS3_FAR *paQuotientReminder)) +{ + RTUInt64DivRem(&paQuotientReminder[0], &paQuotientReminder[1], &uDividend, &uDivisor); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-UtilSetFullGdtr.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-UtilSetFullGdtr.asm new file mode 100644 index 00000000..235329cf --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-UtilSetFullGdtr.asm @@ -0,0 +1,195 @@ +; $Id: bs3-cmn-UtilSetFullGdtr.asm $ +;; @file +; BS3Kit - Bs3UtilSetFullGdtr +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_uBs3CpuDetected +%endif +%if TMPL_BITS != 64 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + + +;; +; @cproto BS3_CMN_PROTO_NOSB(void, Bs3UtilSetFullGdtr,(uint16_t cbLimit, uint64_t uBase)); +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; @uses eax/rax; cbLimit on stack in 32-bit mode. +; +BS3_PROC_BEGIN_CMN Bs3UtilSetFullGdtr, BS3_PBC_HYBRID +TONLY16 inc xBP + push xBP + mov xBP, xSP + +%if TMPL_BITS == 64 + ; + ; It doesn't (currently) get any better than 64-bit mode. + ; + push rdx + mov rax, rcx + shl rax, 48 + push rax + lgdt [rsp + 6] + add rsp, 10h + + +%elif TMPL_BITS == 32 + ; + ; Move the limit up two bytes so we can use it directly. + ; + shl dword [xBP + xCB + cbCurRetAddr], 16 + + ; + ; If the system is currently running in long mode, we have to switch to + ; it in order to do the job with the highest precision. + ; + mov al, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + and al, BS3_MODE_SYS_MASK + cmp al, BS3_MODE_SYS_LM + je .do_64bit + + ; 32-bit is the best we can do. +.do_32bit: + lgdt [xBP + xCB + cbCurRetAddr + 2] + jmp .return + + ; Must switch to long mode and do it there. +.do_64bit: + jmp BS3_SEL_R0_CS64:.in_64bit wrt FLAT +.in_64bit: + BS3_SET_BITS 64 + lgdt [xSP + 4 + cbCurRetAddr + 2] + push BS3_SEL_R0_CS32 + push .return wrt FLAT + o64 retf + BS3_SET_BITS 32 + + +%elif TMPL_BITS == 16 + ; + ; All options are open here, we can be in any 16-bit mode, + ; including real mode. + ; + mov al, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + test al, BS3_MODE_CODE_V86 + jnz .do_v8086 + and al, BS3_MODE_SYS_MASK + cmp al, BS3_MODE_SYS_LM + je .do_64bit + cmp al, BS3_MODE_SYS_RM + je .do_16bit + cmp byte [ BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80386 + jae .do_32bit + + ; + ; We're in real mode or in 16-bit protected mode on a 286. + ; +.do_16bit: ;ba x 1 127f5 + lgdt [xBP + xCB + cbCurRetAddr] + jmp .return + + ; + ; We're in some kind of protected mode on a 386 or better. + ; +.do_32bit: + jmp dword BS3_SEL_R0_CS32:.in_32bit wrt FLAT +.in_32bit: + BS3_SET_BITS 32 + lgdt [bp + 2 + cbCurRetAddr] + jmp BS3_SEL_R0_CS16:.return wrt CGROUP16 + BS3_SET_BITS 16 + + ; + ; V8086 mode - need to switch to 32-bit kernel code to do stuff here. + ; +.do_v8086: + BS3_EXTERN_CMN Bs3SwitchTo32Bit + call Bs3SwitchTo32Bit + BS3_SET_BITS 32 + + lgdt [xSP + 2 + cbCurRetAddr] + + extern _Bs3SwitchTo16BitV86_c32 + call _Bs3SwitchTo16BitV86_c32 + BS3_SET_BITS 16 + jmp .return + + ; + ; System is in long mode, so we can switch to 64-bit mode and do the job there. + ; +.do_64bit: + push edx ; save + push ss + push 0 + push bp + BS3_EXTERN_CMN Bs3SelFar32ToFlat32NoClobber + call Bs3SelFar32ToFlat32NoClobber + add sp, 6 + shl edx, 16 + mov dx, ax + mov eax, edx ; eax = flattened ss:bp + pop edx ; restore + jmp dword BS3_SEL_R0_CS64:.in_64bit wrt FLAT +.in_64bit: + BS3_SET_BITS 64 + lgdt [rax + 2 + cbCurRetAddr] + + push BS3_SEL_R0_CS16 + push .return wrt CGROUP16 + o64 retf + BS3_SET_BITS 16 + +%else + %error "TMPL_BITS!" +%endif + +.return: + pop xBP +TONLY16 dec xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3UtilSetFullGdtr + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-UtilSetFullIdtr.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-UtilSetFullIdtr.asm new file mode 100644 index 00000000..d383e0ce --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-UtilSetFullIdtr.asm @@ -0,0 +1,195 @@ +; $Id: bs3-cmn-UtilSetFullIdtr.asm $ +;; @file +; BS3Kit - Bs3UtilSetFullIdtr +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_uBs3CpuDetected +%endif +%if TMPL_BITS != 64 +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%endif +TMPL_BEGIN_TEXT + + + +;; +; @cproto BS3_CMN_PROTO_NOSB(void, Bs3UtilSetFullIdtr,(uint16_t cbLimit, uint64_t uBase)); +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; @uses eax/rax; cbLimit on stack in 32-bit mode. +; +BS3_PROC_BEGIN_CMN Bs3UtilSetFullIdtr, BS3_PBC_HYBRID +TONLY16 inc xBP + push xBP + mov xBP, xSP + +%if TMPL_BITS == 64 + ; + ; It doesn't (currently) get any better than 64-bit mode. + ; + push rdx + mov rax, rcx + shl rax, 48 + push rax + lidt [rsp + 6] + add rsp, 10h + + +%elif TMPL_BITS == 32 + ; + ; Move the limit up two bytes so we can use it directly. + ; + shl dword [xBP + xCB + cbCurRetAddr], 16 + + ; + ; If the system is currently running in long mode, we have to switch to + ; it in order to do the job with the highest precision. + ; + mov al, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + and al, BS3_MODE_SYS_MASK + cmp al, BS3_MODE_SYS_LM + je .do_64bit + + ; 32-bit is the best we can do. +.do_32bit: + lidt [xBP + xCB + cbCurRetAddr + 2] + jmp .return + + ; Must switch to long mode and do it there. +.do_64bit: + jmp BS3_SEL_R0_CS64:.in_64bit wrt FLAT +.in_64bit: + BS3_SET_BITS 64 + lidt [xSP + 4 + cbCurRetAddr + 2] + push BS3_SEL_R0_CS32 + push .return wrt FLAT + o64 retf + BS3_SET_BITS 32 + + +%elif TMPL_BITS == 16 + ; + ; All options are open here, we can be in any 16-bit mode, + ; including real mode. + ; + mov al, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + test al, BS3_MODE_CODE_V86 + jnz .do_v8086 + and al, BS3_MODE_SYS_MASK + cmp al, BS3_MODE_SYS_LM + je .do_64bit + cmp al, BS3_MODE_SYS_RM + je .do_16bit + cmp byte [ BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80386 + jae .do_32bit + + ; + ; We're in real mode or in 16-bit protected mode on a 286. + ; +.do_16bit: ;ba x 1 127f5 + lidt [xBP + xCB + cbCurRetAddr] + jmp .return + + ; + ; We're in some kind of protected mode on a 386 or better. + ; +.do_32bit: + jmp dword BS3_SEL_R0_CS32:.in_32bit wrt FLAT +.in_32bit: + BS3_SET_BITS 32 + lidt [bp + 2 + cbCurRetAddr] + jmp BS3_SEL_R0_CS16:.return wrt CGROUP16 + BS3_SET_BITS 16 + + ; + ; V8086 mode - need to switch to 32-bit kernel code to do stuff here. + ; +.do_v8086: + BS3_EXTERN_CMN Bs3SwitchTo32Bit + call Bs3SwitchTo32Bit + BS3_SET_BITS 32 + + lidt [xSP + 2 + cbCurRetAddr] + + extern _Bs3SwitchTo16BitV86_c32 + call _Bs3SwitchTo16BitV86_c32 + BS3_SET_BITS 16 + jmp .return + + ; + ; System is in long mode, so we can switch to 64-bit mode and do the job there. + ; +.do_64bit: + push edx ; save + push ss + push 0 + push bp + BS3_EXTERN_CMN Bs3SelFar32ToFlat32NoClobber + call Bs3SelFar32ToFlat32NoClobber + add sp, 6 + shl edx, 16 + mov dx, ax + mov eax, edx ; eax = flattened ss:bp + pop edx ; restore + jmp dword BS3_SEL_R0_CS64:.in_64bit wrt FLAT +.in_64bit: + BS3_SET_BITS 64 + lidt [rax + 2 + cbCurRetAddr] + + push BS3_SEL_R0_CS16 + push .return wrt CGROUP16 + o64 retf + BS3_SET_BITS 16 + +%else + %error "TMPL_BITS!" +%endif + +.return: + pop xBP +TONLY16 dec xBP + BS3_HYBRID_RET +BS3_PROC_END_CMN Bs3UtilSetFullIdtr + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-hexdigits.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-hexdigits.c new file mode 100644 index 00000000..003394f8 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-hexdigits.c @@ -0,0 +1,42 @@ +/* $Id: bs3-cmn-hexdigits.c $ */ +/** @file + * BS3Kit - Hex digits constants. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit-template-header.h" + + +char const g_achBs3HexDigits[16+1] = "0123456789abcdef"; +char const g_achBs3HexDigitsUpper[16+1] = "0123456789ABCDEF"; + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate-common.h b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate-common.h new file mode 100644 index 00000000..6a19cc9d --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate-common.h @@ -0,0 +1,214 @@ +/* $Id: bs3-cmn-instantiate-common.h $ */ +/** @file + * BS3Kit - Common template instantiator body. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/* + * Instantiating common code (c16, c32, c64). + * This must be done first. + */ + +/** @def BS3_INSTANTIATING_CMN + * @ingroup grp_bs3kit_tmpl + * Indicates that we're instantiating common code (c16, c32, c64). + */ +#define BS3_INSTANTIATING_CMN + +#ifdef BS3_CMN_INSTANTIATE_FILE1 + +# define BS3_CMN_INSTANTIATE_FILE1_B <BS3_CMN_INSTANTIATE_FILE1> + +# if ARCH_BITS == 16 /* 16-bit - real mode. */ +# define TMPL_MODE BS3_MODE_RM +# include <bs3kit/bs3kit-template-header.h> +# include BS3_CMN_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> +# endif + +# if ARCH_BITS == 32 /* 32-bit - paged protected mode. */ +# define TMPL_MODE BS3_MODE_PP32 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_CMN_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> +# endif + +# if ARCH_BITS == 64 /* 64-bit. */ +# define TMPL_MODE BS3_MODE_LM64 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_CMN_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> +# endif + +#endif + +#undef BS3_INSTANTIATING_CMN + + +/* + * Instantiating code for each individual mode (rm, pe16, pe16_32, ...). + */ + +/** @def BS3_INSTANTIATING_MODE + * @ingroup grp_bs3kit_tmpl + * Indicates that we're instantiating mode specific code (rm, pe16, ...). + */ +#define BS3_INSTANTIATING_MODE + +#ifdef BS3_MODE_INSTANTIATE_FILE1 + +# define BS3_MODE_INSTANTIATE_FILE1_B <BS3_MODE_INSTANTIATE_FILE1> + +# if ARCH_BITS == 16 /* 16-bit */ + +# define TMPL_MODE BS3_MODE_RM +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_PE16 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_PE16_V86 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_PE32_16 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_PEV86 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_PP16 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_PP16_V86 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_PP32_16 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_PPV86 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_PAE16 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_PAE16_V86 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_PAE32_16 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_PAEV86 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_LM16 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# endif + +# if ARCH_BITS == 32 /* 32-bit */ + +# define TMPL_MODE BS3_MODE_PE16_32 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_PE32 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_PP16_32 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_PP32 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_PAE16_32 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_PAE32 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# define TMPL_MODE BS3_MODE_LM32 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> + +# endif + +# if ARCH_BITS == 64 /* 64-bit. */ +# define TMPL_MODE BS3_MODE_LM64 +# include <bs3kit/bs3kit-template-header.h> +# include BS3_MODE_INSTANTIATE_FILE1_B +# include <bs3kit/bs3kit-template-footer.h> +# endif + +#endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate-x0.c16 b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate-x0.c16 new file mode 100644 index 00000000..352b9be7 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate-x0.c16 @@ -0,0 +1,39 @@ +/* $Id: bs3-cmn-instantiate-x0.c16 $ */ +/** @file + * BS3Kit - 16-bit common C template instantiator, using the BS3X0TEXT16 segment. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#define BS3_USE_X0_TEXT_SEG 1 +#include "bs3-cmn-instantiate-common.h" + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate-x1.c16 b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate-x1.c16 new file mode 100644 index 00000000..631a3673 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate-x1.c16 @@ -0,0 +1,39 @@ +/* $Id: bs3-cmn-instantiate-x1.c16 $ */ +/** @file + * BS3Kit - 16-bit common C template instantiator, using the BS3X1TEXT16 segment. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#define BS3_USE_X1_TEXT_SEG 1 +#include "bs3-cmn-instantiate-common.h" + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate.c16 b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate.c16 new file mode 100644 index 00000000..4c2bdee2 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate.c16 @@ -0,0 +1,39 @@ +/* $Id: bs3-cmn-instantiate.c16 $ */ +/** @file + * BS3Kit - 16-bit common C template instantiator. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +#include "bs3-cmn-instantiate-common.h" + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate.c32 b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate.c32 new file mode 100644 index 00000000..00988062 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate.c32 @@ -0,0 +1,39 @@ +/* $Id: bs3-cmn-instantiate.c32 $ */ +/** @file + * BS3Kit - 32-bit common C template instantiator. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +#include "bs3-cmn-instantiate-common.h" + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate.c64 b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate.c64 new file mode 100644 index 00000000..efeb3f17 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate.c64 @@ -0,0 +1,39 @@ +/* $Id: bs3-cmn-instantiate.c64 $ */ +/** @file + * BS3Kit - 64-bit common C template instantiator. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +#include "bs3-cmn-instantiate-common.h" + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-memory.h b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-memory.h new file mode 100644 index 00000000..efcf459b --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-memory.h @@ -0,0 +1,109 @@ +/* $Id: bs3-cmn-memory.h $ */ +/** @file + * BS3Kit - Internal Memory Structures, Variables and Functions. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#ifndef BS3KIT_INCLUDED_bs3_cmn_memory_h +#define BS3KIT_INCLUDED_bs3_cmn_memory_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "bs3kit.h" +#include <iprt/asm.h> + +RT_C_DECLS_BEGIN; + + +typedef union BS3SLABCTLLOW +{ + BS3SLABCTL Core; + uint32_t au32Alloc[(sizeof(BS3SLABCTL) + (0xA0000 / _4K / 8) ) / 4]; +} BS3SLABCTLLOW; +#ifndef DOXYGEN_RUNNING +# define g_Bs3Mem4KLow BS3_DATA_NM(g_Bs3Mem4KLow) +#endif +extern BS3SLABCTLLOW g_Bs3Mem4KLow; + + +typedef union BS3SLABCTLUPPERTILED +{ + BS3SLABCTL Core; + uint32_t au32Alloc[(sizeof(BS3SLABCTL) + ((BS3_SEL_TILED_AREA_SIZE - _1M) / _4K / 8) ) / 4]; +} BS3SLABCTLUPPERTILED; +#ifndef DOXYGEN_RUNNING +# define g_Bs3Mem4KUpperTiled BS3_DATA_NM(g_Bs3Mem4KUpperTiled) +#endif +extern BS3SLABCTLUPPERTILED g_Bs3Mem4KUpperTiled; + + +/** The number of chunk sizes used by the slab list arrays + * (g_aBs3LowSlabLists, g_aBs3UpperTiledSlabLists, more?). */ +#define BS3_MEM_SLAB_LIST_COUNT 6 + +#ifndef DOXYGEN_RUNNING +# define g_aiBs3SlabListsByPowerOfTwo BS3_DATA_NM(g_aiBs3SlabListsByPowerOfTwo) +# define g_acbBs3SlabLists BS3_DATA_NM(g_acbBs3SlabLists) +# define g_aBs3LowSlabLists BS3_DATA_NM(g_aBs3LowSlabLists) +# define g_aBs3UpperTiledSlabLists BS3_DATA_NM(g_aBs3UpperTiledSlabLists) +# define g_cbBs3SlabCtlSizesforLists BS3_DATA_NM(g_cbBs3SlabCtlSizesforLists) +#endif +extern uint8_t const g_aiBs3SlabListsByPowerOfTwo[12]; +extern uint16_t const g_acbBs3SlabLists[BS3_MEM_SLAB_LIST_COUNT]; +extern BS3SLABHEAD g_aBs3LowSlabLists[BS3_MEM_SLAB_LIST_COUNT]; +extern BS3SLABHEAD g_aBs3UpperTiledSlabLists[BS3_MEM_SLAB_LIST_COUNT]; +extern uint16_t const g_cbBs3SlabCtlSizesforLists[BS3_MEM_SLAB_LIST_COUNT]; + + +/** + * Translates a allocation request size to a slab list index. + * + * @returns Slab list index if small request, UINT8_MAX if large. + * @param cbRequest The number of bytes requested. + */ +DECLINLINE(uint8_t) bs3MemSizeToSlabListIndex(size_t cbRequest) +{ + if (cbRequest <= g_acbBs3SlabLists[BS3_MEM_SLAB_LIST_COUNT - 1]) + { + unsigned idx = cbRequest ? ASMBitLastSetU16((uint16_t)(cbRequest - 1)) : 0; + return g_aiBs3SlabListsByPowerOfTwo[idx]; + } + return UINT8_MAX; +} + + +RT_C_DECLS_END; + +#endif /* !BS3KIT_INCLUDED_bs3_cmn_memory_h */ + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-paging.h b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-paging.h new file mode 100644 index 00000000..7962b1cf --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-paging.h @@ -0,0 +1,69 @@ +/* $Id: bs3-cmn-paging.h $ */ +/** @file + * BS3Kit - Internal Paging Structures, Variables and Functions. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#ifndef BS3KIT_INCLUDED_bs3_cmn_paging_h +#define BS3KIT_INCLUDED_bs3_cmn_paging_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "bs3kit.h" +#include <iprt/asm.h> + +RT_C_DECLS_BEGIN + +/** Root directory for page protected mode. + * UINT32_MAX if not initialized. */ +extern uint32_t g_PhysPagingRootPP; +/** Root directory pointer table for PAE mode. + * UINT32_MAX if not initialized. */ +extern uint32_t g_PhysPagingRootPAE; +/** Root table (level 4) for long mode. + * UINT32_MAX if not initialized. */ +extern uint32_t g_PhysPagingRootLM; + +#undef bs3PagingGetLegacyPte +BS3_CMN_PROTO_STUB(X86PTE BS3_FAR *, bs3PagingGetLegacyPte,(RTCCUINTXREG cr3, uint32_t uFlat, bool fUseInvlPg, int *prc)); +#undef bs3PagingGetPaePte +BS3_CMN_PROTO_STUB(X86PTEPAE BS3_FAR *, bs3PagingGetPaePte,(RTCCUINTXREG cr3, uint8_t bMode, uint64_t uFlat, + bool fUseInvlPg, int *prc)); + +RT_C_DECLS_END + +#include "bs3kit-mangling-code.h" + +#endif /* !BS3KIT_INCLUDED_bs3_cmn_paging_h */ + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-pic-data.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-pic-data.c new file mode 100644 index 00000000..fbef9fbb --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-pic-data.c @@ -0,0 +1,52 @@ +/* $Id: bs3-cmn-pic-data.c $ */ +/** @file + * BS3Kit - PIC Data. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include "bs3-cmn-pic.h" + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +#if ARCH_BITS == 16 +/** Set by the first call to Bs3PicSetup. */ +bool g_fBs3PicConfigured = false; +#endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-pic.h b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-pic.h new file mode 100644 index 00000000..f515a772 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-pic.h @@ -0,0 +1,70 @@ +/* $Id: bs3-cmn-pic.h $ */ +/** @file + * BS3Kit - Internal PIC Defines, Variables and Functions. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#ifndef BS3KIT_INCLUDED_bs3_cmn_pic_h +#define BS3KIT_INCLUDED_bs3_cmn_pic_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "bs3kit.h" + + +/** The master PIC port (base). */ +#define BS3_PIC_PORT_MASTER UINT8_C(0x20) +/** The slave PIC port (base). */ +#define BS3_PIC_PORT_SLAVE UINT8_C(0xa0) + +/** The init command. */ +#define BS3_PIC_CMD_INIT UINT8_C(0x10) +/** 4th init step option for the init command. */ +#define BS3_PIC_CMD_INIT_F_4STEP UINT8_C(0x01) + +/** Auto end of interrupt flag for the 4th init step. */ +#define BS3_PIC_I4_F_AUTO_EOI UINT8_C(0x01) + + +RT_C_DECLS_BEGIN + +extern bool g_fBs3PicConfigured; + +RT_C_DECLS_END + + +#include "bs3kit-mangling-code.h" + +#endif /* !BS3KIT_INCLUDED_bs3_cmn_pic_h */ + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-pit.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-pit.c new file mode 100644 index 00000000..9c0060a7 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-pit.c @@ -0,0 +1,170 @@ +/* $Id: bs3-cmn-pit.c $ */ +/** @file + * BS3Kit - PIT Setup and Disable code. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" +#include <iprt/asm-amd64-x86.h> + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +#define BS3_PIT_PORT_CMD 0x43 +#define BS3_PIT_PORT_CH0_DATA 0x40 +#define BS3_PIT_HZ UINT32_C(1193182) + + +/********************************************************************************************************************************* +* External Symbols * +*********************************************************************************************************************************/ +extern FNBS3TRAPHANDLER16 bs3PitIrqHandler_c16; +extern FNBS3TRAPHANDLER32 bs3PitIrqHandler_c32; +extern FNBS3TRAPHANDLER64 bs3PitIrqHandler_c64; + + +#undef Bs3PitSetupAndEnablePeriodTimer +BS3_CMN_DEF(void, Bs3PitSetupAndEnablePeriodTimer,(uint16_t cHzDesired)) +{ + RTCCUINTREG fSaved; + uint16_t cCount; + uint16_t cMsInterval; + uint32_t cNsInterval; + + /* + * Disable the PIT and make sure we've configured the IRQ handlers. + */ + Bs3PitDisable(); + Bs3PicSetup(false /*fForcedReInit*/); + Bs3TrapSetHandlerEx(0x70, bs3PitIrqHandler_c16, bs3PitIrqHandler_c32, bs3PitIrqHandler_c64); + + /* + * Reset the counters. + */ + g_cBs3PitNs = 0; + g_cBs3PitMs = 0; + g_cBs3PitTicks = 0; + + /* + * Calculate an interval. + */ + if (cHzDesired <= 18) + { + cCount = 0; /* 1193182 / 65536 = 18.206512451171875 Hz */ + cHzDesired = 18; + cNsInterval = UINT32_C(54925401); /* 65536 / 1193182 = 0.054925401154224586022920225078823 seconds */ + cMsInterval = 55; + } + else + { + cCount = BS3_PIT_HZ / cHzDesired; + cHzDesired = BS3_PIT_HZ / cCount; + /* 1s/1193182 = 0.000 000 838 095 110 38550698887512550474278 */ +#if ARCH_BITS == 64 + cNsInterval = cCount * UINT64_C(838095110) / 1000000; +#elif ARCH_BITS == 32 + cNsInterval = cCount * UINT32_C(8381) / 10; +#else + cNsInterval = cCount * 838; +#endif + if (cCount <= 1194) + cMsInterval = 1; /* Must not be zero! */ + else + cMsInterval = cCount / 1194; + } + + + /* + * Do the reprogramming. + */ + fSaved = ASMIntDisableFlags(); + ASMOutU8(BS3_PIT_PORT_CMD, + (0 << 6) /* select: channel 0 */ + | (3 << 4) /* access mode: lobyte/hibyte */ + | (2 << 1) /* operation: Mode 2 */ + | 0 /* binary mode */ + ); + ASMOutU8(BS3_PIT_PORT_CH0_DATA, (uint8_t)cCount); + ASMOutU8(BS3_PIT_PORT_CH0_DATA, (uint8_t)(cCount >> 8)); + + g_cBs3PitIntervalNs = cNsInterval; + g_cBs3PitIntervalHz = cHzDesired; + g_cBs3PitIntervalMs = cMsInterval; + + Bs3PicUpdateMask(UINT16_C(0xfffe), 0); + + ASMSetFlags(fSaved); +} + + +#undef Bs3PitDisable +BS3_CMN_DEF(void, Bs3PitDisable,(void)) +{ + if (g_cBs3PitIntervalHz != 0) + { + RTCCUINTREG fSaved = ASMIntDisableFlags(); + + /* + * Not entirely sure what's the best way to do this, but let's try reprogram + * it to a no-reload mode like 0 and set the count to 1. + */ + g_cBs3PitIntervalMs = 0; + ASMOutU8(BS3_PIT_PORT_CMD, + (0 << 6) /* select: channel 0 */ + | (1 << 4) /* access mode: lobyte */ + | (0 << 1) /* operation: Mode 0 */ + | 0 /* binary mode */ + ); + ASMOutU8(BS3_PIT_PORT_CH0_DATA, (uint8_t)1); + + /* + * Then mask the PIT IRQ on the PIC. + */ + Bs3PicUpdateMask(UINT16_C(0xffff), 1); + + ASMSetFlags(fSaved); + } + + /* + * Reset the interval values (leave the ticks and elapsed ns/ms values as-is). + */ + g_cBs3PitIntervalNs = 0; + g_cBs3PitIntervalMs = 0; + g_cBs3PitIntervalHz = 0; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-test.h b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-test.h new file mode 100644 index 00000000..135baebc --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-test.h @@ -0,0 +1,179 @@ +/* $Id: bs3-cmn-test.h $ */ +/** @file + * BS3Kit - Bs3Test internal header. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#ifndef BS3KIT_INCLUDED_bs3_cmn_test_h +#define BS3KIT_INCLUDED_bs3_cmn_test_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "bs3kit.h" +#include <VBox/VMMDevTesting.h> + + +/** Indicates whether the VMMDev is operational. */ +#ifndef DOXYGEN_RUNNING +# define g_fbBs3VMMDevTesting BS3_DATA_NM(g_fbBs3VMMDevTesting) +#endif +extern bool g_fbBs3VMMDevTesting; + +/** The number of tests that have failed. */ +#ifndef DOXYGEN_RUNNING +# define g_cusBs3TestErrors BS3_DATA_NM(g_cusBs3TestErrors) +#endif +extern uint16_t g_cusBs3TestErrors; + +/** The start error count of the current subtest. */ +#ifndef DOXYGEN_RUNNING +# define g_cusBs3SubTestAtErrors BS3_DATA_NM(g_cusBs3SubTestAtErrors) +#endif +extern uint16_t g_cusBs3SubTestAtErrors; + +/** Whether we've reported the sub-test result or not. */ +#ifndef DOXYGEN_RUNNING +# define g_fbBs3SubTestReported BS3_DATA_NM(g_fbBs3SubTestReported) +#endif +extern bool g_fbBs3SubTestReported; +/** Whether the sub-test has been skipped or not. */ +#ifndef DOXYGEN_RUNNING +# define g_fbBs3SubTestSkipped BS3_DATA_NM(g_fbBs3SubTestSkipped) +#endif +extern bool g_fbBs3SubTestSkipped; + +/** The number of sub tests. */ +#ifndef DOXYGEN_RUNNING +# define g_cusBs3SubTests BS3_DATA_NM(g_cusBs3SubTests) +#endif +extern uint16_t g_cusBs3SubTests; + +/** The number of sub tests that failed. */ +#ifndef DOXYGEN_RUNNING +# define g_cusBs3SubTestsFailed BS3_DATA_NM(g_cusBs3SubTestsFailed) +#endif +extern uint16_t g_cusBs3SubTestsFailed; + +/** VMMDEV_TESTING_UNIT_XXX -> string */ +#ifndef DOXYGEN_RUNNING +# define g_aszBs3TestUnitNames BS3_DATA_NM(g_aszBs3TestUnitNames) +#endif +extern char const g_aszBs3TestUnitNames[][12]; + +/** The test name. */ +extern const char BS3_FAR *g_pszBs3Test_c16; +extern const char *g_pszBs3Test_c32; +extern const char *g_pszBs3Test_c64; + +/** The subtest name. */ +#ifndef DOXYGEN_RUNNING +# define g_szBs3SubTest BS3_DATA_NM(g_szBs3SubTest) +#endif +extern char g_szBs3SubTest[64]; + + +/** + * Sends a command to VMMDev followed by a single string. + * + * If the VMMDev is not present or is not being used, this function will + * do nothing. + * + * @param uCmd The command. + * @param pszString The string. + */ +#ifndef DOXYGEN_RUNNING +# define bs3TestSendCmdWithStr BS3_CMN_NM(bs3TestSendCmdWithStr) +#endif +BS3_DECL(void) bs3TestSendCmdWithStr(uint32_t uCmd, const char BS3_FAR *pszString); + +/** + * Sends a command to VMMDev followed by a 32-bit unsigned integer value. + * + * If the VMMDev is not present or is not being used, this function will + * do nothing. + * + * @param uCmd The command. + * @param uValue The value. + */ +#ifndef DOXYGEN_RUNNING +# define bs3TestSendCmdWithU32 BS3_CMN_NM(bs3TestSendCmdWithU32) +#endif +BS3_DECL(void) bs3TestSendCmdWithU32(uint32_t uCmd, uint32_t uValue); + +/** + * Checks if the VMMDev is configured for testing. + * + * @returns true / false. + */ +#ifndef DOXYGEN_RUNNING +# define bs3TestIsVmmDevTestingPresent BS3_CMN_NM(bs3TestIsVmmDevTestingPresent) +#endif +BS3_DECL(bool) bs3TestIsVmmDevTestingPresent(void); + +/** + * Similar to rtTestSubCleanup. + */ +#ifndef DOXYGEN_RUNNING +# define bs3TestSubCleanup BS3_CMN_NM(bs3TestSubCleanup) +#endif +BS3_DECL(void) bs3TestSubCleanup(void); + +/** + * @callback_method_impl{FNBS3STRFORMATOUTPUT, + * Used by Bs3TestFailedV and Bs3TestSkippedV. + * + * The @a pvUser parameter must point a BS3TESTFAILEDBUF structure. } + */ +#ifndef DOXYGEN_RUNNING +# define bs3TestFailedStrOutput BS3_CMN_NM(bs3TestFailedStrOutput) +#endif +BS3_DECL_CALLBACK(size_t) bs3TestFailedStrOutput(char ch, void BS3_FAR *pvUser); + +/** + * Output buffering for bs3TestFailedStrOutput. + */ +typedef struct BS3TESTFAILEDBUF +{ + /** Initialize to false. */ + bool fNewLine; + /** Initialize to zero. */ + uint8_t cchBuf; + /** Buffer, uninitialized. */ + char achBuf[128]; +} BS3TESTFAILEDBUF; +/** Pointer to a bs3TestFailedStrOutput buffer. */ +typedef BS3TESTFAILEDBUF BS3_FAR *PBS3TESTFAILEDBUF; + +#endif /* !BS3KIT_INCLUDED_bs3_cmn_test_h */ + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-common.mac b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-common.mac new file mode 100644 index 00000000..1cc40765 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-common.mac @@ -0,0 +1,281 @@ +; $Id: bs3-first-common.mac $ +;; @file +; BS3Kit - First Object, common stuff. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +%define BS3_BEGIN_TEXT16_WITHOUT_GROUP +%define BS3_BEGIN_DATA16_WITHOUT_GROUP +%define BS3_BEGIN_RMTEXT16_WITHOUT_GROUP +%define BS3_BEGIN_X0TEXT16_WITHOUT_GROUP +%define BS3_BEGIN_X1TEXT16_WITHOUT_GROUP + +%include "bs3kit.mac" + + +; +; +; Define all the segments and their grouping, just to get that right once at +; the start of everything. +; +; + +; +; 16-bit text +; +%ifndef BS3_IS_DOS_EXE +BS3_BEGIN_TEXT16 +%else +section BEGTEXT align=2 CLASS=BS3CLASS16CODE PUBLIC USE16 +BS3_BEGIN_TEXT16 +section BEGTEXT +%endif +BS3_GLOBAL_DATA Bs3Text16_StartOfSegment, 0 + +; Entry point with eye-catcher. +GLOBALNAME start +global __ImageBase ; for MS compiler - must be first! +__ImageBase: +global ___begtext ; for DOS EXEs (causes harmless duplicate symbol warning) +___begtext: +%ifndef BS3_IS_DOS_EXE + jmp .after_eye_catcher +%else + int3 + jmp __ImageBase +%endif + db 10,13,'eye-catcher: BS3TEXT16',10,13 +BS3_BEGIN_TEXT16 +.after_eye_catcher: + +section _TEXT align=2 CLASS=BS3CLASS16CODE PUBLIC USE16 +section BS3TEXT16_NEARSTUBS align=1 CLASS=BS3CLASS16CODE PUBLIC USE16 +section BS3TEXT16_FARSTUBS align=1 CLASS=BS3CLASS16CODE PUBLIC USE16 +section BS3TEXT16_END align=1 CLASS=BS3CLASS16CODE PUBLIC USE16 + +BS3_GLOBAL_DATA Bs3Text16_EndOfSegment, 0 + +%ifndef BS3_IS_DOS_EXE +GROUP CGROUP16 BS3TEXT16 _TEXT BS3TEXT16_NEARSTUBS BS3TEXT16_FARSTUBS BS3TEXT16_END +%else +GROUP CGROUP16 BEGTEXT BS3TEXT16 _TEXT BS3TEXT16_NEARSTUBS BS3TEXT16_FARSTUBS BS3TEXT16_END +%endif + + +; +; 16-bit data +; +BS3_BEGIN_DATA16 +BS3_GLOBAL_DATA Bs3Data16_StartOfSegment, 0 + db 10,13,'eye-catcher: BS3DATA16',10,13 + +ALIGNDATA(16) +BS3_GLOBAL_DATA Bs3Data16_Size, 4 + dd BS3_DATA_NM(Bs3Data16_EndOfSegment) wrt BS3KIT_GRPNM_DATA16 +BS3_GLOBAL_DATA Bs3Data16Thru64Text32And64_TotalSize, 4 + dd BS3_DATA_NM(Bs3Data64_EndOfSegment) wrt BS3KIT_GRPNM_DATA16 +BS3_GLOBAL_DATA Bs3TotalImageSize, 4 + dd BS3_DATA_NM(Bs3Text64_EndOfSegment) wrt CGROUP16 ; ASSUMES TEXT64 is last. + +BS3_GLOBAL_DATA Bs3Text16_Size, 2 + dw BS3_DATA_NM(Bs3Text16_EndOfSegment) wrt CGROUP16 +BS3_GLOBAL_DATA Bs3RmText16_Size, 2 + dw BS3_DATA_NM(Bs3RmText16_EndOfSegment) wrt BS3GROUPRMTEXT16 +BS3_GLOBAL_DATA Bs3X0Text16_Size, 2 + dw BS3_DATA_NM(Bs3X0Text16_EndOfSegment) wrt BS3GROUPX0TEXT16 +BS3_GLOBAL_DATA Bs3X1Text16_Size, 2 + dw BS3_DATA_NM(Bs3X1Text16_EndOfSegment) wrt BS3GROUPX1TEXT16 + +BS3_GLOBAL_DATA Bs3RmText16_FlatAddr, 4 + dd BS3_DATA_NM(Bs3RmText16_StartOfSegment) wrt BS3FLAT +BS3_GLOBAL_DATA Bs3X0Text16_FlatAddr, 4 + dd BS3_DATA_NM(Bs3X0Text16_StartOfSegment) wrt BS3FLAT +BS3_GLOBAL_DATA Bs3X1Text16_FlatAddr, 4 + dd BS3_DATA_NM(Bs3X1Text16_StartOfSegment) wrt BS3FLAT + +section BS3DATA16CONST align=2 CLASS=BS3KIT_CLASS_DATA16 PUBLIC USE16 +section BS3DATA16CONST2 align=2 CLASS=BS3KIT_CLASS_DATA16 PUBLIC USE16 +section BS3DATA16_DATA align=2 CLASS=BS3KIT_CLASS_DATA16 PUBLIC USE16 +%ifdef BS3_IS_DOS_EXE +section _NULL align=16 CLASS=BEGDATA PUBLIC USE16 +section _AFTERNULL align=2 CLASS=BEGDATA PUBLIC USE16 +%endif +section CONST align=2 CLASS=DATA PUBLIC USE16 +section CONST2 align=2 CLASS=DATA PUBLIC USE16 +section _DATA align=2 CLASS=DATA PUBLIC USE16 +%ifdef BS3_IS_DOS_EXE +section XIB align=1 CLASS=DATA PUBLIC USE16 +section XI align=1 CLASS=DATA PUBLIC USE16 +section XIE align=1 CLASS=DATA PUBLIC USE16 +section YIB align=1 CLASS=DATA PUBLIC USE16 +section YI align=1 CLASS=DATA PUBLIC USE16 +section YIE align=1 CLASS=DATA PUBLIC USE16 +%endif +section STRINGS align=2 CLASS=DATA PUBLIC USE16 +section DATA align=2 CLASS=DATA PUBLIC USE16 +section _BSS align=2 CLASS=BS3KIT_CLASS_BSS16 PUBLIC USE16 +section BSS align=2 CLASS=BS3KIT_CLASS_BSS16 PUBLIC USE16 +%ifdef BS3_IS_DOS_EXE +section STACK align=16 CLASS=STACK STACK USE16 +%endif +section BS3DATA16_END align=2 CLASS=BS3KIT_CLASS_BSS16 PUBLIC USE16 + +BS3_GLOBAL_DATA Bs3Data16_EndOfSegment, 0 + +%ifndef BS3_IS_DOS_EXE +GROUP BS3KIT_GRPNM_DATA16 BS3DATA16 BS3DATA16_DATA _DATA DATA BS3DATA16CONST CONST BS3DATA16CONST2 CONST2 STRINGS _BSS BSS BS3DATA16_END +%else +GROUP BS3KIT_GRPNM_DATA16 \ + _NULL _AFTERNULL \ + CONST BS3DATA16CONST CONST2 BS3DATA16CONST2 _DATA XIB XI XIE YIB YI YIE STRINGS DATA BS3DATA16 BS3DATA16_DATA \ + _BSS BSS BS3DATA16_END \ + STACK +%endif + +; +; 16-bit real-mode text +; +section BS3RMTEXT16_START align=16 CLASS=BS3CLASS16RMCODE PUBLIC USE16 +BS3_GLOBAL_DATA Bs3RmText16_StartOfSegment, 0 + ;db 10,13,'eye-catcher: BS3RMTEXT16',10,13 - messes up switch in C code. Alt. is fConvertFixupp VBoxBs3ObjConverter.cpp. +BS3_BEGIN_RMTEXT16 +section BS3RMTEXT16_END align=1 CLASS=BS3CLASS16RMCODE PUBLIC USE16 +BS3_GLOBAL_DATA Bs3RmText16_EndOfSegment, 0 +GROUP BS3GROUPRMTEXT16 BS3RMTEXT16_START BS3RMTEXT16 BS3RMTEXT16_END + + +; +; 16-bit extra text segment #0. +; +section BS3X0TEXT16_START align=16 CLASS=BS3CLASS16X0CODE PUBLIC USE16 +BS3_GLOBAL_DATA Bs3X0Text16_StartOfSegment, 0 + ;db 10,13,'eye-catcher: BS3X0TEXT16',10,13 - messes up switch in C code. Alt. is fConvertFixupp VBoxBs3ObjConverter.cpp. +BS3_BEGIN_X0TEXT16 4 +section BS3X0TEXT16_END align=16 CLASS=BS3CLASS16X0CODE PUBLIC USE16 +BS3_GLOBAL_DATA Bs3X0Text16_EndOfSegment, 0 +GROUP BS3GROUPX0TEXT16 BS3X0TEXT16_START BS3X0TEXT16 BS3X0TEXT16_END + + +; +; 16-bit extra text segment #1. +; +section BS3X1TEXT16_START align=16 CLASS=BS3CLASS16X1CODE PUBLIC USE16 +BS3_GLOBAL_DATA Bs3X1Text16_StartOfSegment, 0 + ;db 10,13,'eye-catcher: BS3X1TEXT16',10,13 - messes up switch in C code. Alt. is fConvertFixupp VBoxBs3ObjConverter.cpp. +BS3_BEGIN_X1TEXT16 4 +section BS3X1TEXT16_END align=16 CLASS=BS3CLASS16X1CODE PUBLIC USE16 +BS3_GLOBAL_DATA Bs3X1Text16_EndOfSegment, 0 +GROUP BS3GROUPX1TEXT16 BS3X1TEXT16_START BS3X1TEXT16 BS3X1TEXT16_END + + +; +; 32-bit text +; +BS3_BEGIN_TEXT32 +BS3_GLOBAL_DATA Bs3Text32_StartOfSegment, 0 + db 10,13,'eye-catcher: BS3TEXT32',10,13 +section BS3TEXT32_END align=1 CLASS=BS3CLASS32CODE PUBLIC USE32 FLAT +BS3_GLOBAL_DATA Bs3Text32_EndOfSegment, 0 + + +; +; This is a hack to separate the 32-bit and 64-bit text segments when linking, +; such that they don't share the same base frame because they're both assigned +; to the AUTO group by the linker. +; +section BS3SEPARATE32AND64BITCODE align=16 CLASS=BS3CLASSSEPARATE32AND64BITCODE PUBLIC USE16 +BS3_GLOBAL_DATA Bs3Separate32And64BitCode_StartOfSegment, 0 + db 10,13,'eye-catcher: 32-64 wedge',10,13 +section BS3SEPARATE32AND64BITCODE_END align=16 CLASS=BS3CLASSSEPARATE32AND64BITCODE PUBLIC USE16 +BS3_GLOBAL_DATA Bs3Separate32And64BitCode_EndOfSegment, 0 +GROUP BS3SEPARATE32AND64BITCODEGROUP BS3SEPARATE32AND64BITCODE BS3SEPARATE32AND64BITCODE_END + + +; +; 64-bit text +; +BS3_BEGIN_TEXT64 +BS3_GLOBAL_DATA Bs3Text64_StartOfSegment, 0 + db 10,13,'eye-catcher: BS3TEXT64',10,13 +section BS3TEXT64_END align=1 CLASS=BS3CLASS64CODE PUBLIC USE32 FLAT +BS3_GLOBAL_DATA Bs3Text64_EndOfSegment, 0 + + +; +; FAR_DATA segment in DOS EXEs should be near the other FAR_DATA class segments. +; +%ifdef BS3_IS_DOS_EXE +section FAR_DATA align=1 CLASS=FAR_DATA PUBLIC USE16 +%endif + +; +; 32-bit data +; +BS3_BEGIN_DATA32 +BS3_GLOBAL_DATA Bs3Data32_StartOfSegment, 0 + db 10,13,'eye-catcher: BS3DATA32',10,13 +section BS3DATA32CONST align=16 CLASS=FAR_DATA PUBLIC USE32 +section BS3DATA32CONST2 align=16 CLASS=FAR_DATA PUBLIC USE32 +section BS3DATA32_DATA align=16 CLASS=FAR_DATA PUBLIC USE32 +section BS3DATA32_BSS align=16 CLASS=FAR_DATA PUBLIC USE32 +section BS3DATA32_END align=16 CLASS=FAR_DATA PUBLIC USE32 +BS3_GLOBAL_DATA Bs3Data32_EndOfSegment, 0 +GROUP BS3DATA32_GROUP BS3DATA32 BS3DATA32_DATA BS3DATA32CONST BS3DATA32CONST2 BS3DATA32_BSS BS3DATA32_END + +; +; 64-bit data +; +BS3_BEGIN_DATA64 +BS3_GLOBAL_DATA Bs3Data64_StartOfSegment, 0 + db 10,13,'eye-catcher: BS3DATA64',10,13 +section BS3DATA64CONST align=16 CLASS=FAR_DATA PUBLIC USE32 +section BS3DATA64_BSS align=16 CLASS=FAR_DATA PUBLIC USE32 +section BS3DATA64_END align=16 CLASS=FAR_DATA PUBLIC USE32 +BS3_GLOBAL_DATA Bs3Data64_EndOfSegment, 0 +GROUP BS3DATA64_GROUP BS3DATA64 BS3DATA64CONST BS3DATA64_BSS BS3DATA64_END + + +; +; 16-bit accessible system data. +; No need to do anything here. +; +BS3_BEGIN_SYSTEM16 + + +; +; Switch back to the 16-bit code segment and the startup code. +; +BS3_BEGIN_TEXT16 +BS3_GLOBAL_NAME_EX Bs3KitEntryPoint, function, 0 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-dosexe.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-dosexe.asm new file mode 100644 index 00000000..165cde49 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-dosexe.asm @@ -0,0 +1,43 @@ +; $Id: bs3-first-dosexe.asm $ +;; @file +; BS3Kit - First Object for DOS executables, defines segments only. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +; +; Segment defs, grouping and related variables. +; Defines the entry point 'start' as well, leaving us in BS3TEXT16. +; +%include "bs3-first-common.mac" + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-init-all-lm64.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-init-all-lm64.asm new file mode 100644 index 00000000..21227cf9 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-init-all-lm64.asm @@ -0,0 +1,91 @@ +; $Id: bs3-first-init-all-lm64.asm $ +;; @file +; BS3Kit - First Object, calling 32-bit paged protected mode main() after full init. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +; +; Segment defs, grouping and related variables. +; Defines the entry point 'start' as well, leaving us in BS3TEXT16. +; +%include "bs3-first-common.mac" + +extern NAME(Bs3InitAll_rm) +extern NAME(Bs3SwitchToLM64_rm) +extern NAME(Main_lm64) +extern NAME(Bs3Shutdown_c64) +extern BS3_DATA_NM(g_uBs3CpuDetected) +extern NAME(Bs3PrintStrN_c16) +extern NAME(Bs3Panic_c16) + +;; Entry point. + push word 0 ; zero return address. + push word 0 ; zero caller BP + mov bp, sp + + ; + ; Init all while we're in real mode. + ; + mov ax, BS3_SEL_DATA16 + mov es, ax + mov ds, ax + call NAME(Bs3InitAll_rm) + + ; + ; Check that long mode is supported. + ; + test word [BS3_DATA_NM(g_uBs3CpuDetected)], BS3CPU_F_LONG_MODE + jnz .long_mode_supported + push .s_szLongModeError_End - .s_szLongModeError + push cs + push .s_szLongModeError wrt CGROUP16 + call NAME(Bs3PrintStrN_c16) + call NAME(Bs3Panic_c16) +.long_mode_supported: + + ; + ; Switch to LM64 and call main. + ; + call _Bs3SwitchToLM64_rm + BITS 64 + call NAME(Main_lm64) + + ; Try shutdown if it returns. + call NAME(Bs3Shutdown_c64) + +.s_szLongModeError: + db 'BS3 Error! Long mode not supported!', 0ah, 0dh +.s_szLongModeError_End: + db 00h + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-init-all-pe32.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-init-all-pe32.asm new file mode 100644 index 00000000..dd638056 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-init-all-pe32.asm @@ -0,0 +1,69 @@ +; $Id: bs3-first-init-all-pe32.asm $ +;; @file +; BS3Kit - First Object, calling 32-bit protected mode main() after full init. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +; +; Segment defs, grouping and related variables. +; Defines the entry point 'start' as well, leaving us in BS3TEXT16. +; +%include "bs3-first-common.mac" + +extern NAME(Bs3InitAll_rm) +extern NAME(Bs3SwitchToPE32_rm) + +;; Entry point. + push word 0 ; zero return address. + push word 0 ; zero caller BP + mov bp, sp + + ; + ; Init all while we're in real mode. + ; + mov ax, BS3_SEL_DATA16 + mov es, ax + mov ds, ax + call NAME(Bs3InitAll_rm) + + ; + ; Switch to 32-bit protected mode and call main. + ; + call NAME(Bs3SwitchToPE32_rm) + BS3_SET_BITS 32 + call _Main_pe32 +extern _Main_pe32 +BS3_EXTERN_CMN Bs3Shutdown + call Bs3Shutdown + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-init-all-pp32.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-init-all-pp32.asm new file mode 100644 index 00000000..39b288ab --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-init-all-pp32.asm @@ -0,0 +1,69 @@ +; $Id: bs3-first-init-all-pp32.asm $ +;; @file +; BS3Kit - First Object, calling 32-bit paged protected mode main() after full init. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +; +; Segment defs, grouping and related variables. +; Defines the entry point 'start' as well, leaving us in BS3TEXT16. +; +%include "bs3-first-common.mac" + +extern NAME(Bs3InitAll_rm) +extern NAME(Bs3SwitchToPP32_rm) + +;; Entry point. + push word 0 ; zero return address. + push word 0 ; zero caller BP + mov bp, sp + + ; + ; Init all while we're in real mode. + ; + mov ax, BS3_SEL_DATA16 + mov es, ax + mov ds, ax + call NAME(Bs3InitAll_rm) + + ; + ; Switch to 32-bit protected mode and call main. + ; + call NAME(Bs3SwitchToPP32_rm) + BS3_SET_BITS 32 + call _Main_pp32 +extern _Main_pp32 +BS3_EXTERN_CMN Bs3Shutdown + call Bs3Shutdown + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-pe16.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-pe16.asm new file mode 100644 index 00000000..cad3787e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-pe16.asm @@ -0,0 +1,105 @@ +; $Id: bs3-first-pe16.asm $ +;; @file +; BS3Kit - First Object, calling 16-bit protected-mode main(). +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* + +; +; Segment defs, grouping and related variables. +; Defines the entry point 'start' as well, leaving us in BS3TEXT16. +; +%include "bs3-first-common.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_BEGIN_DATA16 + +BS3_BEGIN_RMTEXT16 +extern _Bs3CpuDetect_rm_far +extern _Bs3InitMemory_rm_far + +BS3_BEGIN_TEXT16 +BS3_EXTERN_CMN Bs3PicMaskAll +BS3_EXTERN_CMN Bs3Trap16Init +extern _Bs3SwitchToPE16_rm +extern _Main_pe16 +BS3_EXTERN_CMN Bs3Shutdown + + +BS3_BEGIN_TEXT16 + ; + ; Zero return address and zero caller BP. + ; + xor ax, ax + push ax + push ax + mov bp, sp + + ; + ; Load DS and ES with data selectors. + ; + mov ax, BS3KIT_GRPNM_DATA16 + mov ds, ax + mov es, ax + + + ; + ; Make sure interrupts are disabled as we cannot (don't want to) service + ; BIOS interrupts once we switch mode. + ; + cli + call Bs3PicMaskAll + + ; + ; Initialize 16-bit protected mode. + ; + call far _Bs3CpuDetect_rm_far + call far _Bs3InitMemory_rm_far + call Bs3Trap16Init + + ; + ; Switch to PE16 and call main. + ; + call _Bs3SwitchToPE16_rm + call _Main_pe16 + + ; Try shutdown if it returns. + call Bs3Shutdown + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-rm.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-rm.asm new file mode 100644 index 00000000..ab6b426e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-rm.asm @@ -0,0 +1,59 @@ +; $Id: bs3-first-rm.asm $ +;; @file +; BS3Kit - First Object, calling real-mode main(). +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +; +; Segment defs, grouping and related variables. +; Defines the entry point 'start' as well, leaving us in BS3TEXT16. +; +%include "bs3-first-common.mac" + + +EXTERN Main_rm +BS3_EXTERN_CMN Bs3Shutdown + push word 0 ; zero return address. + push word 0 ; zero caller BP + mov bp, sp + + ; + ; Nothing to init here, just call main and shutdown if it returns. + ; + mov ax, BS3_SEL_DATA16 + mov es, ax + mov ds, ax + call NAME(Main_rm) + call Bs3Shutdown + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-BiosInt15hE820.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-BiosInt15hE820.asm new file mode 100644 index 00000000..6b3c66e4 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-BiosInt15hE820.asm @@ -0,0 +1,245 @@ +; $Id: bs3-mode-BiosInt15hE820.asm $ +;; @file +; BS3Kit - Bs3BiosInt15hE820 +; + +; +; Copyright (C) 2021-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* Defined Constants And Macros * +;********************************************************************************************************************************* +;; Signature: 'SMAP' +%define INT15_E820_SIGNATURE 0534d4150h + + +;********************************************************************************************************************************* +;* External symbols * +;********************************************************************************************************************************* +TMPL_BEGIN_TEXT +extern TMPL_NM(Bs3SwitchToRM) +BS3_BEGIN_TEXT16 +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_rm) + + +;; +; Performs a int 15h function 0xe820 call. +; +; @cproto BS3_MODE_PROTO_STUB(bool, Bs3BiosInt15hE820,(INT15E820ENTRY BS3_FAR *pEntry, uint32_t BS3_FAR *pcbEntry, +; uint32_t BS3_FAR *puContinuationValue)); +; +; @returns Success indicator. +; @param pEntry The return buffer. +; @param pcbEntry Input: The size of the buffer (min 20 bytes); +; Output: The size of the returned data. +; @param puContinuationValue Where to get and return the continuation value (EBX) +; Set to zero the for the first call. Returned as zero +; after the last entry. +; +; @remarks ASSUMES we're in ring-0 when not in some kind of real mode. +; @remarks ASSUMES we're on a 16-bit suitable stack. +; +; @uses rax +; +TMPL_BEGIN_TEXT +BS3_PROC_BEGIN_MODE Bs3BiosInt15hE820, BS3_PBC_HYBRID + push xBP + mov xBP, xSP + sPUSHF + cli + push sBX + push sCX + push sDX + push sSI + push sDI +%ifdef TMPL_16BIT + push ds + push es +%endif + ; Load/Save parameters. +%define a_pEntry [xBP + xCB + cbCurRetAddr + sCB*0] +%define a_pcbEntry [xBP + xCB + cbCurRetAddr + sCB*1] +%define a_puContinuationValue [xBP + xCB + cbCurRetAddr + sCB*2] +%ifdef TMPL_64BIT + mov a_pEntry, rcx ; save pEntry + mov a_pcbEntry, rdx ; save pcbEntry + mov a_puContinuationValue, r8 ; save a_puContinuationValue + mov ebx, [r8] ; uContinuationValue for int15 + mov ecx, [rdx] ; Buffer size for int15. +%elifdef TMPL_16BIT + les bx, a_pcbEntry + mov ecx, [es:bx] ; Buffer size for int15. + les bx, a_puContinuationValue + mov ebx, [es:bx] ; Buffer size for int15. +%else + mov ecx, a_pcbEntry + mov ecx, [ecx] ; Buffer size for int15. + mov ebx, a_puContinuationValue + mov ebx, [ebx] ; uContinuationValue for int15 +%endif + ; + ; Check that the cbEntry isn't too big or too small before doing + ; the stack allocation. (Our BIOS doesn't check if too small.) + ; + cmp ecx, 100h + jae .failed + cmp cl, 14h + jb .failed + +%if TMPL_MODE != BS3_MODE_RM + sub xSP, xCX ; allocate a temporary buffer on the stack. + and xSP, ~0fh +%endif + + ; + ; Switch to real mode, first we just ot the 16-bit text segment. + ; This preserve all 32-bit register values. + ; +%if TMPL_MODE != BS3_MODE_RM + %ifndef TMPL_16BIT + jmp .to_text16 +BS3_BEGIN_TEXT16 +.to_text16: + BS3_SET_BITS TMPL_BITS + %endif + call TMPL_NM(Bs3SwitchToRM) + BS3_SET_BITS 16 +%endif + + ; + ; Make the call. + ; +%if TMPL_MODE == BS3_MODE_RM + les di, a_pEntry +%else + push ss ; es:di -> ss:sp + pop es + mov di, sp +%endif + mov edx, INT15_E820_SIGNATURE + mov eax, 0e820h ; BIOS function number + int 15h + + ; + ; Switch back. + ; +%if TMPL_MODE != BS3_MODE_RM + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_rm) + BS3_SET_BITS TMPL_BITS + %ifndef TMPL_16BIT + jmp .from_text16 +TMPL_BEGIN_TEXT +.from_text16: + %endif +%endif + ; + ; Check that we didn't failed. + ; + jc .failed + cmp eax, INT15_E820_SIGNATURE + jc .failed + cmp ecx, 20 + jb .failed + + ; + ; Save the continuation value. + ; +%ifdef TMPL_16BIT + mov eax, ebx + lds bx, a_puContinuationValue + mov [bx], eax +%else + mov xAX, a_puContinuationValue + mov [xAX], ebx +%endif + + ; + ; Save the entry size. + ; +%ifdef TMPL_16BIT + lds bx, a_pcbEntry +%else + mov xBX, a_pcbEntry +%endif + mov [xBX], ecx + +%if TMPL_MODE != BS3_MODE_RM + ; + ; Copy the returned stuff into the caller's buffer. + ; + mov xSI, xSP + %ifdef TMPL_16BIT + push ss + pop es + lds di, a_pEntry + %else + mov xDI, a_pEntry + %endif + cld + rep movsb +%endif + + ; + ; Return success + ; + mov al, 1 + +.return: +%ifdef TMPL_16BIT + lea xSP, [xBP - sCB * 6 - xCB*2] + pop es + pop ds +%else + lea xSP, [xBP - sCB * 6] +%endif + pop sDI + pop sSI + pop sDX + pop sCX + pop sBX + sPOPF + leave + BS3_HYBRID_RET + + ; + ; Failed. + ; +.failed: + xor al, al + jmp .return +BS3_PROC_END_MODE Bs3BiosInt15hE820 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-CpuDetect.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-CpuDetect.asm new file mode 100644 index 00000000..b54cba28 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-CpuDetect.asm @@ -0,0 +1,347 @@ +; $Id: bs3-mode-CpuDetect.asm $ +;; @file +; BS3Kit - Bs3CpuDetect +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +BS3_EXTERN_DATA16 g_uBs3CpuDetected + + +;; +; Rough CPU detection, mainly for detecting really old CPUs. +; +; A Bs3CpuDetectEx can be added if this is insufficient. +; +; @returns BS3CPU_xxx in xAX. +; @cproto BS3_DECL(BS3CPU) Bs3CpuDetect(void); +; +; @uses xAX. +; +; @remarks ASSUMES we're in ring-0 when not in some kind of real mode. +; +; @note We put the real mode version of this code in the RMTEXT16 segment +; to save space elsewhere. We generate a far call stub that goes +; to the right segment. +; +%if TMPL_MODE == BS3_MODE_RM +BS3_BEGIN_RMTEXT16 +BS3_PROC_BEGIN_MODE Bs3CpuDetect, BS3_PBC_FAR +%else +TMPL_BEGIN_TEXT +BS3_PROC_BEGIN_MODE Bs3CpuDetect, BS3_PBC_HYBRID +%endif +CPU 8086 + push xBP + mov xBP, xSP + pushf ; xBP - xCB*1 + push xCX ; xBP - xCB*2 + push xDX ; xBP - xCB*3 + push xBX ; xBP - xCB*4 + sub xSP, 20h ; xBP - xCB*4 - 20h + +%ifndef TMPL_CMN_PAGING + %ifdef TMPL_RM + %if 1 ; this is simpler + ; + ; FLAGS bits 15:12 are always set on 8086, 8088, V20, V30, 80186, and + ; 80188. FLAGS bit 15 is always zero on 286+, whereas bit 14 is NT and + ; bits 13:12 are IOPL. + ; + test byte [xBP - xCB + 1], 80h ; Top byte of saved flags. + jz .286plus + %else + ; + ; When executing 'PUSH SP' the 8086, 8088, V20, V30, 80186, and 80188 + ; should be pushing the updated SP value instead of the initial one. + ; + push xSP + pop xAX + cmp xAX, xSP + je .286plus + %endif + + ; + ; Older than 286. + ; + ; Detect 8086/8088/V20/V30 vs. 80186/80188 by checking for pre 80186 + ; shift behavior. the 80186/188 and later will mask the CL value according + ; to the width of the destination register, whereas 8086/88 and V20/30 will + ; perform the exact number of shifts specified. + ; + mov cl, 20h ; Shift count; 80186/88 and later will mask this by 0x1f (or 0xf)? + mov dx, 7fh + shl dx, cl + cmp dx, 7fh ; If no change, this is a 80186/88. + mov xAX, BS3CPU_80186 + je .return + + ; + ; Detect 8086/88 vs V20/30 by exploiting undocumented POP CS encoding + ; that was redefined on V20/30 to SET1. + ; + xor ax, ax ; clear + push cs + db 0fh ; 8086/88: pop cs V20/30: set1 bl,cl + db 14h, 3ch ; 8086/88: add al, 3ch + ; 8086/88: al = 3ch V20/30: al = 0, cs on stack, bl modified. + cmp al, 3ch + jne .is_v20_or_v30 + mov xAX, BS3CPU_8086 + jmp .return + +.is_v20_or_v30: + pop xCX ; unclaimed CS + mov xAX, BS3CPU_V20 + jmp .return + + %endif ; TMPL_RM + +CPU 286 +.286plus: + ; + ; The 4th bit of the machine status word / CR0 indicates the precense + ; of a 80387 or later co-processor (a 80287+80386 => ET=0). 486 and + ; later should be hardcoding this to 1, according to the documentation + ; (need to test on 486SX). The initial idea here then would be to + ; assume 386+ if ET=1. + ; + ; The second idea was to check whether any reserved bits are set, + ; because the 286 here has bits 4 thru 15 all set. Unfortunately, it + ; turned out the 386SX and AMD 486DX-40 also sets bits 4 thru 15 when + ; using SMSW. So, nothing conclusive to distinguish 386 from 286, but + ; we've probably got a safe 486+ detection here. + ; + ;; @todo check if LOADALL can set any of the reserved bits on a 286 or 386. + smsw ax + test ax, ~(X86_CR0_PE | X86_CR0_MP | X86_CR0_EM | X86_CR0_TS | X86_CR0_ET | X86_CR0_NE) + jz .486plus + + ; + ; The 286 stores 0xff in the high byte of the SIDT and SGDT base + ; address (since it only did 24-bit addressing and the top 8-bit was + ; reserved for the 386). ASSUMES low IDT (which is the case for BS3Kit). + ; + sidt [xBP - xCB*4 - 20h] + cmp byte [xBP - xCB*4 - 20h + 2 + 3], 0ffh + jne .386plus + + %if 0 + ; + ; Detect 80286 by checking whether the IOPL and NT bits of EFLAGS can be + ; modified or not. There are different accounts of these bits. Dr.Dobb's + ; (http://www.drdobbs.com/embedded-systems/processor-detection-schemes/184409011) + ; say they are undefined on 286es and will always be zero. Whereas Intel + ; iAPX 286 Programmer's Reference Manual (both order #210498-001 and + ; #210498-003) documents both IOPL and NT, but with comment 4 on page + ; C-43 stating that they cannot be POPFed in real mode and will both + ; remain 0. This is different from the 386+, where the NT flag isn't + ; privileged according to page 3-37 in #230985-003. Later Intel docs + ; (#235383-052US, page 4-192) documents real mode as taking both NT and + ; IOPL from what POPF reads off the stack - which is the behavior + ; observed a 386SX here. + ; + test al, X86_CR0_PE ; This flag test doesn't work in protected mode, ... + jnz .386plus ; ... so ASSUME 386plus if in PE for now. + + pushf ; Save a copy of the original flags for restoring IF. + pushf + pop ax + xor ax, X86_EFL_IOPL | X86_EFL_NT ; Try modify IOPL and NT. + and ax, ~X86_EFL_IF ; Try clear IF. + push ax ; Load modified flags. + popf + pushf ; Get actual flags. + pop dx + popf ; Restore IF, IOPL and NT. + cmp ax, dx + je .386plus ; If any of the flags are set, we're on 386+. + + ; While we could in theory be in v8086 mode at this point and be fooled + ; by a flaky POPF implementation, we assume this isn't the case in our + ; execution environment. + %endif +.is_286: + mov ax, BS3CPU_80286 + jmp .return +%endif ; !TMPL_CMN_PAGING + +CPU 386 +.386plus: +.486plus: + ; + ; Check for CPUID and AC. The former flag indicates CPUID support, the + ; latter was introduced with the 486. + ; + mov ebx, esp ; Save esp. + and esp, 0fffch ; Clear high word and don't trigger ACs. + pushfd + mov eax, [esp] ; eax = original EFLAGS. + xor dword [esp], X86_EFL_ID | X86_EFL_AC ; Flip the ID and AC flags. + popfd ; Load modified flags. + pushfd ; Save actual flags. + xchg eax, [esp] ; Switch, so the stack has the original flags. + xor eax, [esp] ; Calc changed flags. + popf ; Restore EFLAGS. + mov esp, ebx ; Restore possibly unaligned ESP. + test eax, X86_EFL_ID + jnz .have_cpuid ; If ID changed, we've got CPUID. + test eax, X86_EFL_AC + mov xAX, BS3CPU_80486 + jnz .return ; If AC changed, we've got a 486 without CPUID (or similar). + mov xAX, BS3CPU_80386 + jmp .return + +CPU 586 +.have_cpuid: + ; + ; Do a very simple minded check here using the (standard) family field. + ; While here, we also check for PAE. + ; + mov eax, 1 + cpuid + + ; Calc the extended family and model values before we mess up EAX. + mov cl, ah + and cl, 0fh + cmp cl, 0fh + jnz .not_extended_family + mov ecx, eax + shr ecx, 20 + and cl, 7fh + add cl, 0fh +.not_extended_family: ; cl = family + mov ch, al + shr ch, 4 + cmp cl, 0fh + jae .extended_model + cmp cl, 06h ; actually only intel, but we'll let this slip for now. + jne .done_model +.extended_model: + shr eax, 12 + and al, 0f0h + or ch, al +.done_model: ; ch = model + + ; Start assembling return flags, checking for PSE + PAE. + mov eax, X86_CPUID_FEATURE_EDX_PSE | X86_CPUID_FEATURE_EDX_PAE + and eax, edx + mov ah, al + AssertCompile(X86_CPUID_FEATURE_EDX_PAE_BIT > BS3CPU_F_PAE_BIT - 8) ; 6 vs 10-8=2 + and al, X86_CPUID_FEATURE_EDX_PAE + shr al, X86_CPUID_FEATURE_EDX_PAE_BIT - (BS3CPU_F_PAE_BIT - 8) + AssertCompile(X86_CPUID_FEATURE_EDX_PSE_BIT == BS3CPU_F_PSE_BIT - 8) ; 3 vs 11-8=3 + and ah, X86_CPUID_FEATURE_EDX_PSE + or ah, al + or ah, (BS3CPU_F_CPUID >> 8) + + ; Add the CPU type based on the family and model values. + cmp cl, 6 + jne .not_family_06h + mov al, BS3CPU_PPro + cmp ch, 1 + jbe .return + mov al, BS3CPU_PProOrNewer + jmp .NewerThanPPro + +.not_family_06h: + mov al, BS3CPU_PProOrNewer + ja .NewerThanPPro + cmp cl, 5 + mov al, BS3CPU_Pentium + je .return + cmp cl, 4 + mov al, BS3CPU_80486 + je .return + cmp cl, 3 + mov al, BS3CPU_80386 + je .return + +.NewerThanPPro: + + ; Check for extended leaves and long mode. + push xAX ; save PAE+PProOrNewer + mov eax, 0x80000000 + cpuid + sub eax, 0x80000001 ; Minimum leaf 0x80000001 + cmp eax, 0x00010000 ; At most 0x10000 leaves. + ja .no_ext_leaves + + mov eax, 0x80000001 + cpuid + pop xAX ; restore PAE+PProOrNewer + test edx, X86_CPUID_EXT_FEATURE_EDX_LONG_MODE + jz .no_long_mode + or ah, ((BS3CPU_F_CPUID_EXT_LEAVES | BS3CPU_F_LONG_MODE) >> 8) + jmp .no_check_for_nx +.no_long_mode: + or ah, (BS3CPU_F_CPUID_EXT_LEAVES >> 8) +.no_check_for_nx: + test edx, X86_CPUID_EXT_FEATURE_EDX_NX + jz .return + or ax, BS3CPU_F_NX + jmp .return + +.no_ext_leaves: + pop xAX ; restore PAE+PProOrNewer + +CPU 8086 +.return: + ; + ; Save the return value. + ; + mov [BS3_DATA16_WRT(g_uBs3CpuDetected)], ax + + ; + ; Epilogue. + ; + add xSP, 20h + pop xBX + pop xDX + pop xCX + popf + pop xBP + BS3_HYBRID_RET + +BS3_PROC_END_MODE Bs3CpuDetect + + +%if TMPL_MODE == BS3_MODE_RM +BS3_BEGIN_TEXT16_NEARSTUBS +BS3_PROC_BEGIN_MODE Bs3CpuDetect, BS3_PBC_NEAR + call far TMPL_FAR_NM(Bs3CpuDetect) + ret +BS3_PROC_END_MODE Bs3CpuDetect +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-EnteredMode.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-EnteredMode.asm new file mode 100644 index 00000000..4cc2c11e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-EnteredMode.asm @@ -0,0 +1,279 @@ +; $Id: bs3-mode-EnteredMode.asm $ +;; @file +; BS3Kit - Bs3EnteredMode +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_uBs3CpuDetected +%endif +BS3_EXTERN_DATA16 g_bBs3CurrentMode +TMPL_BEGIN_TEXT + +;; +; @cproto BS3_DECL(void) Bs3EnteredMode(void); +; +; @uses Nothing. +; +; @remarks ASSUMES we're in ring-0 when not in some kind of real mode. +; +BS3_PROC_BEGIN_MODE Bs3EnteredMode, BS3_PBC_NEAR ; won't need this outside the switchers, so always near. + push xBP + mov xBP, xSP + push xAX + push xCX + push xDX +TONLY16 push xBX +%if BS3_MODE_IS_64BIT_CODE(TMPL_MODE) + push r8 + push r9 +%endif + + ; + ; Load stack selector (not always necessary) and sometimes CS too. + ; +%if BS3_MODE_IS_RM_SYS(TMPL_MODE) + xor ax, ax +%elif BS3_MODE_IS_V86(TMPL_MODE) + extern v86_versions_of_Bs3EnteredMode_should_not_be_dragged_into_the_link + call v86_versions_of_Bs3EnteredMode_should_not_be_dragged_into_the_link +%elif BS3_MODE_IS_16BIT_CODE(TMPL_MODE) + jmp BS3_SEL_R0_CS16:.reloaded_cs +.reloaded_cs: + mov ax, BS3_SEL_R0_SS16 +%elif BS3_MODE_IS_32BIT_CODE(TMPL_MODE) + mov ax, BS3_SEL_R0_SS32 +%elif BS3_MODE_IS_64BIT_CODE(TMPL_MODE) + mov ax, BS3_SEL_R0_DS64 +%else + %error "TMPL_MODE" +%endif + mov ss, ax + + ; + ; Load selector appropriate for accessing BS3SYSTEM16 data. + ; +%if BS3_MODE_IS_16BIT_CODE(TMPL_MODE) + mov ax, BS3_SEL_SYSTEM16 +%else + mov ax, RT_CONCAT(BS3_SEL_R0_DS,TMPL_BITS) +%endif + mov ds, ax + + ; + ; Load the appropritate IDT or IVT. + ; Always 64-bit in long mode, otherwise according to TMPL_BITS. + ; +%if BS3_MODE_IS_RM_SYS(TMPL_MODE) + BS3_EXTERN_SYSTEM16 Bs3Lidt_Ivt + TMPL_BEGIN_TEXT + lidt [Bs3Lidt_Ivt] + +%elif BS3_MODE_IS_16BIT_SYS(TMPL_MODE) + BS3_EXTERN_SYSTEM16 Bs3Lidt_Idt16 + TMPL_BEGIN_TEXT + lidt [Bs3Lidt_Idt16 TMPL_WRT_SYSTEM16_OR_FLAT] + +%elif BS3_MODE_IS_32BIT_SYS(TMPL_MODE) + BS3_EXTERN_SYSTEM16 Bs3Lidt_Idt32 + TMPL_BEGIN_TEXT + lidt [Bs3Lidt_Idt32 TMPL_WRT_SYSTEM16_OR_FLAT] + +%elif BS3_MODE_IS_64BIT_SYS(TMPL_MODE) + BS3_EXTERN_SYSTEM16 Bs3Lidt_Idt64 + TMPL_BEGIN_TEXT + lidt [Bs3Lidt_Idt64 TMPL_WRT_SYSTEM16_OR_FLAT] +%else + %error "TMPL_MODE" +%endif + +%if !BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + ; + ; Load the appropriate task selector. + ; Always 64-bit in long mode, otherwise according to TMPL_BITS. + ; + %if BS3_MODE_IS_64BIT_SYS(TMPL_MODE) + BS3_EXTERN_SYSTEM16 Bs3Gdte_Tss64 + TMPL_BEGIN_TEXT + and byte [5 + Bs3Gdte_Tss64 TMPL_WRT_SYSTEM16_OR_FLAT], ~X86_SEL_TYPE_SYS_TSS_BUSY_MASK + mov ax, BS3_SEL_TSS64 + + %elif BS3_MODE_IS_16BIT_SYS(TMPL_MODE) + BS3_EXTERN_SYSTEM16 Bs3Gdte_Tss16 + BS3_EXTERN_SYSTEM16 Bs3Gdte_Tss16DoubleFault + TMPL_BEGIN_TEXT + and byte [5 + Bs3Gdte_Tss16 TMPL_WRT_SYSTEM16_OR_FLAT], ~X86_SEL_TYPE_SYS_TSS_BUSY_MASK + and byte [5 + Bs3Gdte_Tss16DoubleFault TMPL_WRT_SYSTEM16_OR_FLAT], ~X86_SEL_TYPE_SYS_TSS_BUSY_MASK + mov ax, BS3_SEL_TSS16 + + %elif BS3_MODE_IS_32BIT_SYS(TMPL_MODE) + BS3_EXTERN_SYSTEM16 Bs3Gdte_Tss32 + BS3_EXTERN_SYSTEM16 Bs3Gdte_Tss32DoubleFault + BS3_EXTERN_SYSTEM16 Bs3Tss32 + BS3_EXTERN_SYSTEM16 Bs3Tss32DoubleFault + TMPL_BEGIN_TEXT + and byte [5 + Bs3Gdte_Tss32 TMPL_WRT_SYSTEM16_OR_FLAT], ~X86_SEL_TYPE_SYS_TSS_BUSY_MASK + and byte [5 + Bs3Gdte_Tss32DoubleFault TMPL_WRT_SYSTEM16_OR_FLAT], ~X86_SEL_TYPE_SYS_TSS_BUSY_MASK + mov eax, cr3 + mov [X86TSS32.cr3 + Bs3Tss32 TMPL_WRT_SYSTEM16_OR_FLAT], eax + mov [X86TSS32.cr3 + Bs3Tss32DoubleFault TMPL_WRT_SYSTEM16_OR_FLAT], eax + mov ax, BS3_SEL_TSS32 + %else + %error "TMPL_BITS" + %endif + ltr ax +%endif ; !TMPL_CMN_R86 + +%if !BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + ; + ; Load the LDT. + ; + mov ax, BS3_SEL_LDT + lldt ax +%endif + + ; + ; Load ds and es; clear fs and gs. + ; +%if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + mov ax, BS3_SEL_DATA16 +%else + mov ax, RT_CONCAT(BS3_SEL_R0_DS,TMPL_BITS) +%endif + mov ds, ax + mov es, ax + +%if TMPL_BITS == 16 + ; For restoring after Bs3Trap* calls below. + push ax + push ax + + cmp byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80286 + jbe .skip_fs_gs +%endif + xor ax, ax + mov fs, ax + mov gs, ax +.skip_fs_gs: + + ; + ; Set global indicating CPU mode. + ; + mov byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], TMPL_MODE + + ; + ; Install system call handler. + ; Always 64-bit in long mode, otherwise according to TMPL_BITS. + ; +%if BS3_MODE_IS_RM_SYS(TMPL_MODE) + extern _Bs3TrapSystemCallHandler_rm + mov word [ss: BS3_TRAP_SYSCALL*4], _Bs3TrapSystemCallHandler_rm wrt CGROUP16 + mov word [ss: BS3_TRAP_SYSCALL*4 + 2], CGROUP16 + +%elif BS3_MODE_IS_16BIT_SYS(TMPL_MODE) + BS3_EXTERN_CMN Bs3Trap16SetGate + extern TMPL_NM(Bs3TrapSystemCallHandler) + BS3_BEGIN_TEXT16 + TMPL_BEGIN_TEXT + push 0 ; cParams + push TMPL_NM(Bs3TrapSystemCallHandler) wrt CGROUP16 + push BS3_SEL_R0_CS16 + push 3 ; DPL + push X86_SEL_TYPE_SYS_286_INT_GATE + push BS3_TRAP_SYSCALL + BS3_CALL Bs3Trap16SetGate,6 + add xSP, xCB * 6 + +%elif BS3_MODE_IS_32BIT_SYS(TMPL_MODE) + BS3_EXTERN_CMN Bs3Trap32SetGate + extern TMPL_NM(Bs3TrapSystemCallHandler) + TMPL_BEGIN_TEXT + push 0 ; cParams + push dword TMPL_NM(Bs3TrapSystemCallHandler) wrt FLAT + push BS3_SEL_R0_CS32 + push 3 ; DPL + push X86_SEL_TYPE_SYS_386_INT_GATE + push BS3_TRAP_SYSCALL + BS3_CALL Bs3Trap32SetGate,6 + add xSP, xCB * 6 + +%elif BS3_MODE_IS_64BIT_SYS(TMPL_MODE) + BS3_EXTERN_CMN Bs3Trap64SetGate + extern _Bs3TrapSystemCallHandler_lm64 + TMPL_BEGIN_TEXT + push 0 ; bIst + %if BS3_MODE_IS_64BIT_CODE(TMPL_MODE) + push _Bs3TrapSystemCallHandler_lm64 wrt FLAT + %else + push dword 0 ; upper offset + push dword _Bs3TrapSystemCallHandler_lm64 wrt FLAT + %endif + push BS3_SEL_R0_CS64 + push 3 ; DPL + push AMD64_SEL_TYPE_SYS_INT_GATE + push BS3_TRAP_SYSCALL + BS3_CALL Bs3Trap64SetGate,6 + add xSP, xCB * 5 + 8 +%else + %error "TMPL_BITS" +%endif + +%if TMPL_BITS == 16 + ; Restoring ds and es after the above calls. + pop es + pop ds +%endif + + ; + ; Epilogue. + ; +%if TMPL_BITS == 64 + pop r9 + pop r8 +%endif +TONLY16 pop xBX + pop xDX + pop xCX + pop xAX +%ifdef BS3_STRICT + cmp xBP, xSP + je .return_stack_ok + int3 +.return_stack_ok: +%endif + pop xBP + ret +BS3_PROC_END_MODE Bs3EnteredMode + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-Name.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-Name.asm new file mode 100644 index 00000000..0cad7a2b --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-Name.asm @@ -0,0 +1,44 @@ +; $Id: bs3-mode-Name.asm $ +;; @file +; BS3Kit - g_szBs3ModeName_xxx +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_BEGIN_DATA16 +BS3_GLOBAL_NAME_EX RT_CONCAT3(g_szBs3ModeName, _, TMPL_MODE_LNAME), , %strlen(TMPL_MODE_STR) +BS3_GLOBAL_NAME_EX RT_CONCAT3(_g_szBs3ModeName, _, TMPL_MODE_LNAME), , %strlen(TMPL_MODE_STR) + db TMPL_MODE_STR, 0 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-NameShortLower.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-NameShortLower.asm new file mode 100644 index 00000000..08d679c7 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-NameShortLower.asm @@ -0,0 +1,46 @@ +; $Id: bs3-mode-NameShortLower.asm $ +;; @file +; BS3Kit - g_szBs3ModeName_xxx +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +BS3_BEGIN_DATA16 +%undef MY_MODE_NAME_STR +%defstr MY_MODE_NAME_STR TMPL_MODE_LNAME +BS3_GLOBAL_NAME_EX RT_CONCAT3(g_szBs3ModeNameShortLower, _, TMPL_MODE_LNAME), , %strlen(MY_MODE_NAME_STR) +BS3_GLOBAL_NAME_EX RT_CONCAT3(_g_szBs3ModeNameShortLower, _, TMPL_MODE_LNAME), , %strlen(MY_MODE_NAME_STR) + db MY_MODE_NAME_STR, 0 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForLM64.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForLM64.asm new file mode 100644 index 00000000..9fea5e53 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForLM64.asm @@ -0,0 +1,141 @@ +; $Id: bs3-mode-PagingGetRootForLM64.asm $ +;; @file +; BS3Kit - Bs3PagingGetRootForLM64 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +%ifdef TMPL_RM +extern TMPL_NM(Bs3SwitchToPE16) +extern NAME(Bs3SwitchToRM_pe16) +%elifdef TMPL_CMN_V86 +extern TMPL_NM(Bs3SwitchToRing0) +extern TMPL_NM(Bs3SwitchTo16BitV86) +%endif + +BS3_EXTERN_CMN Bs3PagingInitRootForLM + +BS3_EXTERN_DATA16 g_PhysPagingRootLM +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_DECL(uint32_t) Bs3PagingGetRootForLM64(void) +; +; @returns eax +; +; @uses ax +; +; @remarks returns value in EAX, not dx:ax! +; +BS3_PROC_BEGIN_MODE Bs3PagingGetRootForLM64, BS3_PBC_NEAR ; Internal function, no far variant necessary. + mov eax, [BS3_DATA16_WRT(g_PhysPagingRootLM)] + cmp eax, 0ffffffffh + je .init_root +%ifdef BS3_STRICT +.return: + cmp eax, 1000h + jnb .cr3_ok_low + hlt +.cr3_ok_low: + cmp eax, 16*_1M + jb .cr3_ok_high + hlt +.cr3_ok_high: +%endif + ret + +.init_root: + push xBP + mov xBP, xSP +BONLY16 push es + push sDX + push sCX + push sBX +%if TMPL_BITS == 64 + push r8 + push r9 + push r10 + push r11 +%endif + +%ifdef TMPL_RM + ; + ; We don't want to be restricted to real mode addressing, so + ; temporarily switch to 16-bit protected mode. + ; + call TMPL_NM(Bs3SwitchToPE16) + call Bs3PagingInitRootForLM + call NAME(Bs3SwitchToRM_pe16) +%elifdef TMPL_CMN_V86 + ; + ; V8086 mode uses real mode addressing too. Unlikly that we'll + ; ever end up here though. + ; + call TMPL_NM(Bs3SwitchToRing0) + call Bs3PagingInitRootForLM + call TMPL_NM(Bs3SwitchTo16BitV86) +%else + ; + ; Not a problematic addressing mode. + ; +BONLY64 sub rsp, 20h + BS3_CALL Bs3PagingInitRootForLM, 0 +BONLY64 add rsp, 20h +%endif + + ; + ; Load the value and return. + ; + mov eax, [BS3_DATA16_WRT(g_PhysPagingRootLM)] + +%if TMPL_BITS == 64 + pop r11 + pop r10 + pop r9 + pop r8 +%endif + pop sBX + pop sCX + pop sDX +BONLY16 pop es + leave +%ifdef BS3_STRICT + jmp .return +%else + ret +%endif +BS3_PROC_END_MODE Bs3PagingGetRootForLM64 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForPAE16.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForPAE16.asm new file mode 100644 index 00000000..db5c700d --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForPAE16.asm @@ -0,0 +1,55 @@ +; $Id: bs3-mode-PagingGetRootForPAE16.asm $ +;; @file +; BS3Kit - Bs3PagingGetRootForPAE16 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +extern TMPL_NM(Bs3PagingGetRootForPAE32) + + +;; +; @cproto BS3_DECL(uint32_t) Bs3PagingGetRootForPAE16(void) +; +; @returns eax +; +; @uses ax +; +; @remarks returns value in EAX, not dx:ax! +; +BS3_PROC_BEGIN_MODE Bs3PagingGetRootForPAE16, BS3_PBC_NEAR ; Internal function, no far variant necessary. + jmp TMPL_NM(Bs3PagingGetRootForPAE32) +BS3_PROC_END_MODE Bs3PagingGetRootForPAE16 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForPAE32.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForPAE32.asm new file mode 100644 index 00000000..9f48d3bd --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForPAE32.asm @@ -0,0 +1,127 @@ +; $Id: bs3-mode-PagingGetRootForPAE32.asm $ +;; @file +; BS3Kit - Bs3PagingGetRootForPAE32 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +%ifdef TMPL_RM +extern TMPL_NM(Bs3SwitchToPE16) +extern NAME(Bs3SwitchToRM_pe16) +%elifdef TMPL_CMN_V86 +extern TMPL_NM(Bs3SwitchToRing0) +extern TMPL_NM(Bs3SwitchTo16BitV86) +%endif + +BS3_EXTERN_CMN Bs3PagingInitRootForPAE + +BS3_EXTERN_DATA16 g_PhysPagingRootPAE +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_DECL(uint32_t) Bs3PagingGetRootForPAE32(void) +; +; @returns eax +; +; @uses ax +; +; @remarks returns value in EAX, not dx:ax! +; +BS3_PROC_BEGIN_MODE Bs3PagingGetRootForPAE32, BS3_PBC_NEAR ; Internal function, no far variant necessary. + mov eax, [BS3_DATA16_WRT(g_PhysPagingRootPAE)] + cmp eax, 0ffffffffh + je .init_root + ret + +.init_root: + push xBP + mov xBP, xSP +BONLY16 push es + push sDX + push sCX + push sBX +%if TMPL_BITS == 64 + push r8 + push r9 + push r10 + push r11 +%endif + +%ifdef TMPL_RM + ; + ; We don't want to be restricted to real mode addressing, so + ; temporarily switch to 16-bit protected mode. + ; + call TMPL_NM(Bs3SwitchToPE16) + call Bs3PagingInitRootForPAE + call NAME(Bs3SwitchToRM_pe16) + +%elifdef TMPL_CMN_V86 + ; + ; V8086 mode uses real mode addressing too. Unlikly that we'll + ; ever end up here though. + ; + call TMPL_NM(Bs3SwitchToRing0) + call Bs3PagingInitRootForPAE + call TMPL_NM(Bs3SwitchTo16BitV86) +%else + ; + ; Not a problematic addressing mode. + ; +BONLY64 sub rsp, 20h + BS3_CALL Bs3PagingInitRootForPAE, 0 +BONLY64 add rsp, 20h +%endif + + ; + ; Load the value and return. + ; + mov eax, [BS3_DATA16_WRT(g_PhysPagingRootPAE)] + +%if TMPL_BITS == 64 + pop r11 + pop r10 + pop r9 + pop r8 +%endif + pop sBX + pop sCX + pop sDX +BONLY16 pop es + leave + ret +BS3_PROC_END_MODE Bs3PagingGetRootForPAE32 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForPP16.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForPP16.asm new file mode 100644 index 00000000..88c22bd3 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForPP16.asm @@ -0,0 +1,55 @@ +; $Id: bs3-mode-PagingGetRootForPP16.asm $ +;; @file +; BS3Kit - Bs3PagingGetRootForPP16 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +extern TMPL_NM(Bs3PagingGetRootForPP32) + + +;; +; @cproto BS3_DECL(uint32_t) Bs3PagingGetRootForPP16(void) +; +; @returns eax +; +; @uses ax +; +; @remarks returns value in EAX, not dx:ax! +; +BS3_PROC_BEGIN_MODE Bs3PagingGetRootForPP16, BS3_PBC_NEAR ; Internal function, no far variant necessary. + jmp TMPL_NM(Bs3PagingGetRootForPP32) +BS3_PROC_END_MODE Bs3PagingGetRootForPP16 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForPP32.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForPP32.asm new file mode 100644 index 00000000..865fac3e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForPP32.asm @@ -0,0 +1,142 @@ +; $Id: bs3-mode-PagingGetRootForPP32.asm $ +;; @file +; BS3Kit - Bs3PagingGetRootForPP32 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +%ifdef TMPL_RM +extern TMPL_NM(Bs3SwitchToPE16) +extern NAME(Bs3SwitchToRM_pe16) +%elifdef TMPL_CMN_V86 +extern TMPL_NM(Bs3SwitchToRing0) +extern TMPL_NM(Bs3SwitchTo16BitV86) +%endif + +BS3_EXTERN_CMN Bs3PagingInitRootForPP + +BS3_EXTERN_DATA16 g_PhysPagingRootPP +TMPL_BEGIN_TEXT + + +;; +; @cproto BS3_DECL(uint32_t) Bs3PagingGetRootForPP32(void) +; +; @returns eax +; +; @uses ax +; +; @remarks returns value in EAX, not dx:ax! +; +BS3_PROC_BEGIN_MODE Bs3PagingGetRootForPP32, BS3_PBC_NEAR ; Internal function, no far variant necessary. + mov eax, [BS3_DATA16_WRT(g_PhysPagingRootPP)] + cmp eax, 0ffffffffh + je .init_root +%ifdef BS3_STRICT +.return: + cmp eax, 1000h + jnb .cr3_ok_low + hlt +.cr3_ok_low: + cmp eax, 16*_1M + jb .cr3_ok_high + hlt +.cr3_ok_high: +%endif + ret + +.init_root: + push xBP + mov xBP, xSP +BONLY16 push es + push sDX + push sCX + push sBX +%if TMPL_BITS == 64 + push r8 + push r9 + push r10 + push r11 +%endif + +%ifdef TMPL_RM + ; + ; We don't want to be restricted to real mode addressing, so + ; temporarily switch to 16-bit protected mode. + ; + call TMPL_NM(Bs3SwitchToPE16) + call Bs3PagingInitRootForPP + call NAME(Bs3SwitchToRM_pe16) + +%elifdef TMPL_CMN_V86 + ; + ; V8086 mode uses real mode addressing too. Unlikly that we'll + ; ever end up here though. + ; + call TMPL_NM(Bs3SwitchToRing0) + call Bs3PagingInitRootForPP + call TMPL_NM(Bs3SwitchTo16BitV86) +%else + ; + ; Not a problematic addressing mode. + ; +BONLY64 sub rsp, 20h + BS3_CALL Bs3PagingInitRootForPP, 0 +BONLY64 add rsp, 20h +%endif + + ; + ; Load the value and return. + ; + mov eax, [BS3_DATA16_WRT(g_PhysPagingRootPP)] + +%if TMPL_BITS == 64 + pop r11 + pop r10 + pop r9 + pop r8 +%endif + pop sBX + pop sCX + pop sDX +BONLY16 pop es + leave +%ifdef BS3_STRICT + jmp .return +%else + ret +%endif +BS3_PROC_END_MODE Bs3PagingGetRootForPP32 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchTo32BitAndCallC.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchTo32BitAndCallC.asm new file mode 100644 index 00000000..23c18cd7 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchTo32BitAndCallC.asm @@ -0,0 +1,164 @@ +; $Id: bs3-mode-SwitchTo32BitAndCallC.asm $ +;; @file +; BS3Kit - bs3SwitchTo32BitAndCallC +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_EXTERN_DATA16 g_bBs3CurrentMode +TMPL_BEGIN_TEXT + +%ifdef BS3_STRICT +BS3_EXTERN_CMN Bs3Panic +%endif + +%if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) +BS3_EXTERN_CMN Bs3SelRealModeCodeToFlat +%endif + +%if TMPL_MODE == BS3_MODE_RM +extern NAME(Bs3SwitchToPE32_rm) +extern NAME(Bs3SwitchToRM_pe32) +%elif !BS3_MODE_IS_32BIT_CODE(TMPL_MODE) +BS3_EXTERN_CMN Bs3SwitchTo32Bit + %if BS3_MODE_IS_16BIT_CODE_NO_V86(TMPL_MODE) +extern _Bs3SwitchTo16Bit_c32 + %elif BS3_MODE_IS_V86(TMPL_MODE) +extern _Bs3SwitchTo16BitV86_c32 + %elif !BS3_MODE_IS_32BIT_CODE(TMPL_MODE) +extern _Bs3SwitchTo64_c32 + %endif +%endif + + + +;; +; @cproto BS3_MODE_PROTO_STUB(int, Bs3SwitchTo32BitAndCallC,(PFNBS3FARADDRCONV fpfnCall, unsigned cbParams, ...)); +; +BS3_PROC_BEGIN_MODE Bs3SwitchTo32BitAndCallC, BS3_PBC_HYBRID + BS3_CALL_CONV_PROLOG 4 +TONLY16 inc xBP + push xBP + mov xBP, xSP + push xSI + + ; + ; Push the arguments first. + ; +TONLY16 mov si, [xBP + xCB + cbCurRetAddr + sCB] +TNOT16 mov esi, [xBP + xCB + cbCurRetAddr + sCB] +%ifdef BS3_STRICT + test xSI, 3 + jz .cbParams_ok + call Bs3Panic +.cbParams_ok: + cmp byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], TMPL_MODE + je .mode_ok + call Bs3Panic +.mode_ok: +%endif + add xSI, sCB - 1 ; round it up to nearest push size / dword. + and xSI, ~(sCB - 1) + jz .done_pushing ; skip if zero +.push_more: + push xPRE [xBP + xCB + cbCurRetAddr + sCB + xCB + xSI - xCB] + sub xSI, xCB + jnz .push_more + mov xSI, xAX ; restore xSI +.done_pushing: + + ; + ; Load fpfnCall into eax. + ; +%if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + push sPRE [xBP + xCB + cbCurRetAddr] + BS3_CALL Bs3SelRealModeCodeToFlat, 1 + add xSP, sCB + rol eax, 16 + mov ax, dx + rol eax, 16 +%else + mov eax, [xBP + xCB + cbCurRetAddr] +%endif + + ; + ; Switch to 32-bit mode, if this is real mode pick PE32. + ; +%if TMPL_MODE == BS3_MODE_RM + call NAME(Bs3SwitchToPE32_rm) + BS3_SET_BITS 32 +%elif !BS3_MODE_IS_32BIT_CODE(TMPL_MODE) + call Bs3SwitchTo32Bit + BS3_SET_BITS 32 +%endif + + ; + ; Make the call. + ; + call eax + + ; + ; Return, preserving xAX. + ; +%if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + mov edx, eax + shr edx, 16 +%endif +%if TMPL_MODE == BS3_MODE_RM + call NAME(Bs3SwitchToRM_pe32) +%elif BS3_MODE_IS_16BIT_CODE_NO_V86(TMPL_MODE) + call _Bs3SwitchTo16Bit_c32 +%elif BS3_MODE_IS_V86(TMPL_MODE) + call _Bs3SwitchTo16BitV86_c32 +%elif !BS3_MODE_IS_32BIT_CODE(TMPL_MODE) + call _Bs3SwitchTo64_c32 +%endif + BS3_SET_BITS TMPL_BITS + + ; Epilog. + lea xSP, [xBP - xCB] + pop xSI + pop xBP +TONLY16 dec xBP + BS3_CALL_CONV_EPILOG 4 + BS3_HYBRID_RET +BS3_PROC_END_MODE Bs3SwitchTo32BitAndCallC + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToLM16.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToLM16.asm new file mode 100644 index 00000000..f8210fcc --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToLM16.asm @@ -0,0 +1,136 @@ +; $Id: bs3-mode-SwitchToLM16.asm $ +;; @file +; BS3Kit - Bs3SwitchToLM16 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to 16-bit long mode from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToLM16(void); +; +; @uses Nothing (except possibly high 32-bit and/or upper 64-bit register parts). +; +; @remarks Obviously returns to 16-bit mode, even if the caller was in 32-bit +; or 64-bit mode. It doesn't not preserve the callers ring, but +; instead changes to ring-0. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +%if TMPL_BITS == 16 +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToLM16_Safe), function , 0 +%endif +BS3_PROC_BEGIN_MODE Bs3SwitchToLM16, BS3_PBC_NEAR +%ifdef TMPL_LM16 + extern BS3_CMN_NM(Bs3SwitchToRing0) + call BS3_CMN_NM(Bs3SwitchToRing0) + push ax + mov ax, BS3_SEL_R0_DS16 + mov ds, ax + mov es, ax + pop ax + ret + +%elifdef TMPL_CMN_LM + ; + ; Already in long mode, just switch to 16-bit. + ; + extern BS3_CMN_NM(Bs3SwitchTo16Bit) + jmp BS3_CMN_NM(Bs3SwitchTo16Bit) + +%else + ; + ; Switch to LM32 and then switch to 64-bits (IDT & TSS are the same for + ; LM16, LM32 and LM64, unlike the rest). + ; + ; (The long mode switching code is going via 32-bit protected mode, so + ; Bs3SwitchToLM32 contains the actual code for switching to avoid + ; unnecessary 32-bit -> 64-bit -> 32-bit trips.) + ; + extern TMPL_NM(Bs3SwitchToLM32) + call TMPL_NM(Bs3SwitchToLM32) + BS3_SET_BITS 32 + + extern _Bs3SwitchTo16Bit_c32 + %if TMPL_BITS == 16 + sub esp, 2 + shr dword [esp], 16 + %elif TMPL_BITS == 64 + pop dword [esp + 4] + %endif + jmp _Bs3SwitchTo16Bit_c32 +%endif +BS3_PROC_END_MODE Bs3SwitchToLM16 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToLM16, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToLM16) + + %if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + ; Jmp to common code for the tedious conversion. + BS3_EXTERN_CMN Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn + jmp Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn + %else + pop bp + dec bp + retf + %endif +BS3_PROC_END_MODE Bs3SwitchToLM16 + +%else +;; +; Safe far return to non-BS3TEXT16 code. +BS3_EXTERN_CMN Bs3SwitchHlpConvFlatRetToRetfProtMode +BS3_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_PROC_BEGIN_MODE Bs3SwitchToLM16_Safe, BS3_PBC_NEAR + call Bs3SwitchHlpConvFlatRetToRetfProtMode ; Special internal function. Uses nothing, but modifies the stack. + call TMPL_NM(Bs3SwitchToLM16) + BS3_SET_BITS 16 + retf +BS3_PROC_END_MODE Bs3SwitchToLM16_Safe + +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToLM32.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToLM32.asm new file mode 100644 index 00000000..5ac49b74 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToLM32.asm @@ -0,0 +1,203 @@ +; $Id: bs3-mode-SwitchToLM32.asm $ +;; @file +; BS3Kit - Bs3SwitchToLM32 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to 32-bit long mode from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToLM32(void); +; +; @uses Nothing (except possibly high 32-bit and/or upper 64-bit register parts). +; +; @remarks There are no IDT or TSS differences between LM16, LM32 and LM64 (unlike +; PE16 & PE32, PP16 & PP32, and PAE16 & PAE32). +; +; @remarks Obviously returns to 32-bit mode, even if the caller was in 16-bit +; or 64-bit mode. It doesn't not preserve the callers ring, but +; instead changes to ring-0. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToLM32_Safe), function, 0 +BS3_PROC_BEGIN_MODE Bs3SwitchToLM32, BS3_PBC_NEAR +%ifdef TMPL_LM32 + ret + +%elifdef TMPL_CMN_LM + ; + ; Already in long mode, just switch to 32-bit. + ; + extern BS3_CMN_NM(Bs3SwitchTo32Bit) + jmp BS3_CMN_NM(Bs3SwitchTo32Bit) + +%elif BS3_MODE_IS_V86(TMPL_MODE) + ; + ; V8086 - Switch to 16-bit ring-0 and call worker for that mode. + ; + extern BS3_CMN_NM(Bs3SwitchToRing0) + call BS3_CMN_NM(Bs3SwitchToRing0) + extern %[BS3_MODE_R0_NM_ %+ TMPL_MODE](Bs3SwitchToLM32) + jmp %[BS3_MODE_R0_NM_ %+ TMPL_MODE](Bs3SwitchToLM32) + +%else + %if TMPL_BITS == 16 + push word 0 ; save space for extending the return value. + %endif + + ; + ; Switch to 32-bit protected mode (for identify mapped pages). + ; + extern TMPL_NM(Bs3SwitchToPE32) + call TMPL_NM(Bs3SwitchToPE32) + BS3_SET_BITS 32 + %if TMPL_BITS == 16 + jmp .thirty_two_bit_segment +BS3_BEGIN_TEXT32 +BS3_GLOBAL_LOCAL_LABEL .thirty_two_bit_segment + %endif + + push eax + push ecx + push edx + pushfd + + ; + ; Make sure both PAE and PSE are enabled (requires pentium pro). + ; + mov eax, cr4 + mov ecx, eax + or eax, X86_CR4_PAE | X86_CR4_PSE + cmp eax, ecx + je .cr4_is_fine + mov cr4, eax +.cr4_is_fine: + + ; + ; Get the page directory (returned in eax). + ; Will lazy init page tables. + ; + extern NAME(Bs3PagingGetRootForLM64_pe32) + call NAME(Bs3PagingGetRootForLM64_pe32) + + cli + mov cr3, eax + + ; + ; Enable long mode in EFER. + ; + mov ecx, MSR_K6_EFER + rdmsr + or eax, MSR_K6_EFER_LME + wrmsr + + ; + ; Enable paging and thereby activating LM64. + ; +BS3_EXTERN_SYSTEM16 Bs3Lgdt_Gdt +BS3_BEGIN_TEXT32 + mov eax, cr0 + or eax, X86_CR0_PG + mov cr0, eax + jmp .in_lm32 +.in_lm32: + + ; + ; Call rountine for doing mode specific setups. + ; + extern NAME(Bs3EnteredMode_lm32) + call NAME(Bs3EnteredMode_lm32) + + ; + ; Load full 64-bit GDT base address from 64-bit segment. + ; + jmp dword BS3_SEL_R0_CS64:.load_full_gdt_base wrt FLAT +.load_full_gdt_base: + BS3_SET_BITS 64 + lgdt [Bs3Lgdt_Gdt wrt FLAT] + push BS3_SEL_R0_CS32 + push .back_to_32bit wrt FLAT + o64 retf +.back_to_32bit: + BS3_SET_BITS 32 + + ; + ; Restore ecx, eax and flags (IF). + ; + %if TMPL_BITS == 16 + movzx eax, word [esp + 16 + 2] ; Load return address. + add eax, BS3_ADDR_BS3TEXT16 ; Convert it to a flat address. + mov [esp + 16], eax ; Store it in the place right for 32-bit returns. + %endif + popfd + pop edx + pop ecx + pop eax + ret + + %if TMPL_BITS != 32 +TMPL_BEGIN_TEXT + %endif +%endif +BS3_PROC_END_MODE Bs3SwitchToLM32 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToLM32, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToLM32) + BS3_SET_BITS 32 + + ; Jmp to common code for the tedious conversion. + %if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + extern _Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn_c32 + jmp _Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn_c32 + %else + extern _Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn_c32 + jmp _Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn_c32 + %endif + BS3_SET_BITS 16 +BS3_PROC_END_MODE Bs3SwitchToLM32 +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToLM64.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToLM64.asm new file mode 100644 index 00000000..f906044c --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToLM64.asm @@ -0,0 +1,114 @@ +; $Id: bs3-mode-SwitchToLM64.asm $ +;; @file +; BS3Kit - Bs3SwitchToLM64 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to 64-bit long mode from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToLM64(void); +; +; @uses Nothing (except possibly high 32-bit and/or upper 64-bit register parts). +; +; @remarks Obviously returns to 64-bit mode, even if the caller was in 16-bit +; or 32-bit mode. It doesn't not preserve the callers ring, but +; instead changes to ring-0. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToLM64_Safe), function, 0 +BS3_PROC_BEGIN_MODE Bs3SwitchToLM64, BS3_PBC_NEAR +%ifdef TMPL_LM64 + ret + +%elifdef TMPL_CMN_LM + ; + ; Already in long mode, just switch to 64-bit. + ; + extern BS3_CMN_NM(Bs3SwitchTo64Bit) + jmp BS3_CMN_NM(Bs3SwitchTo64Bit) + +%else + ; + ; Switch to LM32 and then switch to 64-bits (IDT & TSS are the same for + ; LM16, LM32 and LM64, unlike the rest). + ; + ; (The long mode switching code is going via 32-bit protected mode, so + ; Bs3SwitchToLM32 contains the actual code for switching to avoid + ; unnecessary 32-bit -> 64-bit -> 32-bit trips.) + ; + %ifdef TMPL_16BIT + and esp, 0ffffh + push word [esp] ; copy return address. + and word [esp + 2], 0 ; clear upper return address + add dword [esp], BS3_ADDR_BS3TEXT16 ; Add base of return segment, completing 32-bit conversion. + %endif + extern TMPL_NM(Bs3SwitchToLM32) + call TMPL_NM(Bs3SwitchToLM32) + BS3_SET_BITS 32 + + extern _Bs3SwitchTo64Bit_c32 + jmp _Bs3SwitchTo64Bit_c32 +%endif +BS3_PROC_END_MODE Bs3SwitchToLM64 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToLM64, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToLM64) + BS3_SET_BITS 64 + + ; Jmp to common code for the tedious conversion. + %if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + extern _Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn_c64 + jmp _Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn_c64 + %else + extern _Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn_c64 + jmp _Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn_c64 + %endif + BS3_SET_BITS 16 +BS3_PROC_END_MODE Bs3SwitchToLM64 +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE16.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE16.asm new file mode 100644 index 00000000..15ced7ab --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE16.asm @@ -0,0 +1,243 @@ +; $Id: bs3-mode-SwitchToPAE16.asm $ +;; @file +; BS3Kit - Bs3SwitchToPAE16 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +%ifndef TMPL_PAE16 +BS3_BEGIN_TEXT16 +extern NAME(Bs3EnteredMode_pae16) + %ifdef TMPL_PAE32 + BS3_EXTERN_CMN Bs3SwitchTo16Bit + %endif +TMPL_BEGIN_TEXT +%endif + + +;; +; Switch to 16-bit paged protected mode from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToPAE16(void); +; +; @uses Nothing (except high 32-bit register parts). +; +; @remarks Obviously returns to 16-bit mode, even if the caller was +; in 32-bit or 64-bit mode. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +%if TMPL_BITS == 16 +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToPAE16_Safe), function , 0 +%endif +BS3_PROC_BEGIN_MODE Bs3SwitchToPAE16, BS3_PBC_NEAR +%ifdef TMPL_PAE16 + extern BS3_CMN_NM(Bs3SwitchToRing0) + call BS3_CMN_NM(Bs3SwitchToRing0) + push ax + mov ax, BS3_SEL_R0_DS16 + mov ds, ax + mov es, ax + pop ax + ret + +%elif BS3_MODE_IS_V86(TMPL_MODE) + ; + ; V8086 - Switch to 16-bit ring-0 and call worker for that mode. + ; + extern BS3_CMN_NM(Bs3SwitchToRing0) + call BS3_CMN_NM(Bs3SwitchToRing0) + extern %[BS3_MODE_R0_NM_ %+ TMPL_MODE](Bs3SwitchToPAE16) + jmp %[BS3_MODE_R0_NM_ %+ TMPL_MODE](Bs3SwitchToPAE16) + +%else + ; + ; Switch to 16-bit text segment and prepare for returning in 16-bit mode. + ; + %if TMPL_BITS != 16 + shl xPRE [xSP], TMPL_BITS - 16 ; Adjust the return address. + add xSP, xCB - 2 + + ; Must be in 16-bit segment when calling Bs3SwitchToRM and Bs3SwitchTo16Bit. + jmp .sixteen_bit_segment +BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .sixteen_bit_segment + %endif + + %ifdef TMPL_PAE32 + ; + ; No need to go to real-mode here, we use the same CR3 and stuff. + ; Just switch to 32-bit mode and call the Bs3EnteredMode routine to + ; load the right descriptor tables. + ; + call Bs3SwitchTo16Bit + BS3_SET_BITS 16 + call NAME(Bs3EnteredMode_pae16) + ret + %else + + ; + ; Switch to real mode. + ; + extern TMPL_NM(Bs3SwitchToRM) + call TMPL_NM(Bs3SwitchToRM) + BS3_SET_BITS 16 + + push eax + push ecx + pushfd + + ; + ; Get the page directory (returned in eax). + ; Will lazy init page tables (in 16-bit prot mode). + ; + extern NAME(Bs3PagingGetRootForPAE16_rm) + call NAME(Bs3PagingGetRootForPAE16_rm) + + cli + mov cr3, eax + + ; + ; Make sure PAE, PSE, and VME are enabled (former two require pentium pro, latter 486). + ; + mov eax, cr4 + mov ecx, eax + or eax, X86_CR4_PAE | X86_CR4_PSE | X86_CR4_VME + cmp eax, ecx + je .cr4_is_fine + mov cr4, eax +.cr4_is_fine: + + ; + ; Load the GDT and enable PP16. + ; +BS3_EXTERN_SYSTEM16 Bs3LgdtDef_Gdt +BS3_EXTERN_SYSTEM16 Bs3Lgdt_Gdt +BS3_BEGIN_TEXT16 + mov ax, BS3SYSTEM16 + mov ds, ax + lgdt [Bs3LgdtDef_Gdt] ; Will only load 24-bit base! + + mov eax, cr0 + or eax, X86_CR0_PE | X86_CR0_PG + mov cr0, eax + jmp BS3_SEL_R0_CS16:.reload_cs_and_stuff +.reload_cs_and_stuff: + + ; + ; Convert the (now) real mode stack to 16-bit. + ; + mov ax, .stack_fix_return + extern NAME(Bs3ConvertRMStackToP16UsingCxReturnToAx_c16) + jmp NAME(Bs3ConvertRMStackToP16UsingCxReturnToAx_c16) +.stack_fix_return: + + ; + ; Call rountine for doing mode specific setups. + ; + call NAME(Bs3EnteredMode_pae16) + + ; + ; Load full 32-bit GDT base address from 32-bit segment. + ; + push ds + mov ax, BS3_SEL_SYSTEM16 + mov ds, ax + jmp dword BS3_SEL_R0_CS32:.load_full_gdt_base wrt FLAT +.load_full_gdt_base: + BS3_SET_BITS 32 + lgdt [Bs3Lgdt_Gdt wrt BS3SYSTEM16] + jmp BS3_SEL_R0_CS16:.back_to_16bit +.back_to_16bit: + BS3_SET_BITS 16 + pop ds + + popfd + pop ecx + pop eax + ret + + %endif ; !TMPL_PP32 + %if TMPL_BITS != 16 +TMPL_BEGIN_TEXT + %endif +%endif +BS3_PROC_END_MODE Bs3SwitchToPAE16 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToPAE16, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToPAE16) + + %if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + ; Jmp to common code for the tedious conversion. + BS3_EXTERN_CMN Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn + jmp Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn + %else + pop bp + dec bp + retf + %endif +BS3_PROC_END_MODE Bs3SwitchToPAE16 + +%else +;; +; Safe far return to non-BS3TEXT16 code. +BS3_EXTERN_CMN Bs3SwitchHlpConvFlatRetToRetfProtMode +BS3_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_PROC_BEGIN_MODE Bs3SwitchToPAE16_Safe, BS3_PBC_NEAR + call Bs3SwitchHlpConvFlatRetToRetfProtMode ; Special internal function. Uses nothing, but modifies the stack. + call TMPL_NM(Bs3SwitchToPAE16) + BS3_SET_BITS 16 + retf +BS3_PROC_END_MODE Bs3SwitchToPAE16_Safe +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE16_32.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE16_32.asm new file mode 100644 index 00000000..130a239a --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE16_32.asm @@ -0,0 +1,114 @@ +; $Id: bs3-mode-SwitchToPAE16_32.asm $ +;; @file +; BS3Kit - Bs3SwitchToPAE16_32 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to 32-bit code under 16-bit PAE paged protected mode sys/tss from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToPE16_32(void); +; +; @uses Nothing (except high 32-bit register parts). +; +; @remarks Obviously returns to 32-bit mode, even if the caller was +; in 16-bit or 64-bit mode. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToPAE16_32_Safe), function, 0 +BS3_PROC_BEGIN_MODE Bs3SwitchToPAE16_32, BS3_PBC_NEAR +%ifdef TMPL_PAE16_32 + ret + +%else + ; + ; Make sure we're in the 16-bit segment and then call Bs3SwitchToPAE16. + ; + %if TMPL_BITS != 16 + jmp .sixteen_bit_segment +BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .sixteen_bit_segment + %endif + extern TMPL_NM(Bs3SwitchToPAE16) + call TMPL_NM(Bs3SwitchToPAE16) + BS3_SET_BITS 16 + + ; + ; Switch to 32-bit mode. + ; + extern _Bs3SwitchTo32Bit_c16 + %if TMPL_BITS == 16 + jmp _Bs3SwitchTo32Bit_c16 + %else + call _Bs3SwitchTo32Bit_c16 + BS3_SET_BITS 32 + %if TMPL_BITS == 32 + ret + %else + ret 4 ; Return and pop 4 bytes of "parameters" (unused return address). + %endif + %endif +%endif +BS3_PROC_END_MODE Bs3SwitchToPAE16_32 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToPAE16_32, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToPAE16_32) + BS3_SET_BITS 32 + + ; Jmp to common code for the tedious conversion. + %if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + extern _Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn_c32 + jmp _Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn_c32 + %else + extern _Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn_c32 + jmp _Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn_c32 + %endif + BS3_SET_BITS 16 +BS3_PROC_END_MODE Bs3SwitchToPAE16_32 +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE16_V86.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE16_V86.asm new file mode 100644 index 00000000..e20ab30a --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE16_V86.asm @@ -0,0 +1,124 @@ +; $Id: bs3-mode-SwitchToPAE16_V86.asm $ +;; @file +; BS3Kit - Bs3SwitchToPAE16_V86 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to 16-bit PAE paged protected mode with 16-bit sys+tss from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToPAE16(void); +; +; @uses Nothing (except high 32-bit register parts). +; +; @remarks Obviously returns to v8086 16-bit mode, even if the caller was +; in 16-bit, 32-bit or 64-bit mode. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +%if TMPL_BITS == 16 +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToPAE16_V86_Safe), function , 0 +%endif +BS3_PROC_BEGIN_MODE Bs3SwitchToPAE16_V86, BS3_PBC_NEAR +%ifdef TMPL_PAE16_V86 + ret + +%else + ; + ; Convert the return address and jump to the 16-bit code segment. + ; + %if TMPL_BITS != 16 + shl xPRE [xSP], TMPL_BITS - 16 + add xSP, (TMPL_BITS - 16) / 8 + jmp .sixteen_bit_segment +BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .sixteen_bit_segment + %endif + + ; + ; Switch to 16-bit PAE16 and from there to V8086. + ; + extern TMPL_NM(Bs3SwitchToPAE16) + call TMPL_NM(Bs3SwitchToPAE16) + BS3_SET_BITS 16 + + ; + ; Switch to v8086 mode (return address is already 16-bit). + ; + extern _Bs3SwitchTo16BitV86_c16 + jmp _Bs3SwitchTo16BitV86_c16 +%endif +BS3_PROC_END_MODE Bs3SwitchToPAE16_V86 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToPAE16_V86, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToPAE16_V86) + + %if !BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + ; Jmp to common code for the tedious conversion. + BS3_EXTERN_CMN Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn + jmp Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn + %else + pop bp + dec bp + retf + %endif +BS3_PROC_END_MODE Bs3SwitchToPAE16_V86 + +%else +;; +; Safe far return to non-BS3TEXT16 code. +BS3_EXTERN_CMN Bs3SwitchHlpConvFlatRetToRetfProtMode +BS3_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_PROC_BEGIN_MODE Bs3SwitchToPAE16_V86_Safe, BS3_PBC_NEAR + call Bs3SwitchHlpConvFlatRetToRetfProtMode ; Special internal function. Uses nothing, but modifies the stack. + call TMPL_NM(Bs3SwitchToPAE16_V86) + BS3_SET_BITS 16 + retf +BS3_PROC_END_MODE Bs3SwitchToPAE16_V86_Safe +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE32.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE32.asm new file mode 100644 index 00000000..768bc013 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE32.asm @@ -0,0 +1,202 @@ +; $Id: bs3-mode-SwitchToPAE32.asm $ +;; @file +; BS3Kit - Bs3SwitchToPAE32 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to PAE paged protected mode from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToPAE32(void); +; +; @uses Nothing (except high 32-bit register parts), upper part of ESP is +; cleared if caller is in 16-bit mode. +; +; @remarks Obviously returns to 32-bit mode, even if the caller was +; in 16-bit or 64-bit mode. It doesn't not preserve the callers +; ring, but instead changes to ring-0. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToPAE32_Safe), function, 0 +BS3_PROC_BEGIN_MODE Bs3SwitchToPAE32, BS3_PBC_NEAR +%ifdef TMPL_PAE32 + ret + +%elif BS3_MODE_IS_V86(TMPL_MODE) + ; + ; V8086 - Switch to 16-bit ring-0 and call worker for that mode. + ; + extern BS3_CMN_NM(Bs3SwitchToRing0) + call BS3_CMN_NM(Bs3SwitchToRing0) + extern %[BS3_MODE_R0_NM_ %+ TMPL_MODE](Bs3SwitchToPAE32) + jmp %[BS3_MODE_R0_NM_ %+ TMPL_MODE](Bs3SwitchToPAE32) + +%else + ; + ; Switch to real mode. + ; + %if TMPL_BITS != 32 + %if TMPL_BITS > 32 + shl xPRE [xSP], 32 ; Adjust the return address from 64-bit to 32-bit. + add rsp, xCB - 4 + %else + push word 0 ; Reserve space to expand the return address. + %endif + %endif + %if TMPL_BITS != 16 + ; Must be in 16-bit segment when calling Bs3SwitchTo16Bit. + jmp .sixteen_bit_segment +BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .sixteen_bit_segment + %endif + + ; + ; Switch to real mode. + ; + extern TMPL_NM(Bs3SwitchToRM) + call TMPL_NM(Bs3SwitchToRM) + BS3_SET_BITS 16 + + push eax + push ecx + pushfd + + ; + ; Get the page directory (returned in eax). + ; Will lazy init page tables (in 16-bit prot mode). + ; + extern NAME(Bs3PagingGetRootForPAE32_rm) + call NAME(Bs3PagingGetRootForPAE32_rm) + + cli + mov cr3, eax + + ; + ; Make sure PAE, PSE, and VME are enabled (former two require pentium pro, latter 486). + ; + mov eax, cr4 + mov ecx, eax + or eax, X86_CR4_PAE | X86_CR4_PSE | X86_CR4_VME + cmp eax, ecx + je .cr4_is_fine + mov cr4, eax +.cr4_is_fine: + + ; + ; Load the GDT and enable PE32. + ; +BS3_EXTERN_SYSTEM16 Bs3LgdtDef_Gdt +BS3_EXTERN_SYSTEM16 Bs3Lgdt_Gdt +BS3_BEGIN_TEXT16 + mov ax, BS3SYSTEM16 + mov ds, ax + lgdt [Bs3LgdtDef_Gdt] ; Will only load 24-bit base! + + mov eax, cr0 + or eax, X86_CR0_PE | X86_CR0_PG + mov cr0, eax + jmp BS3_SEL_R0_CS32:dword .thirty_two_bit wrt FLAT +BS3_BEGIN_TEXT32 +BS3_GLOBAL_LOCAL_LABEL .thirty_two_bit + + ; + ; Convert the (now) real mode stack pointer to 32-bit flat. + ; + xor eax, eax + mov ax, ss + shl eax, 4 + and esp, 0ffffh + add esp, eax + + mov ax, BS3_SEL_R0_SS32 + mov ss, ax + + ; + ; Call rountine for doing mode specific setups. + ; + extern NAME(Bs3EnteredMode_pae32) + call NAME(Bs3EnteredMode_pae32) + + ; Load full 32-bit GDT base address. + lgdt [Bs3Lgdt_Gdt wrt FLAT] + + ; + ; Restore ecx, eax and flags (IF). + ; + %if TMPL_BITS < 32 + movzx eax, word [esp + 12 + 2] ; Load return address. + add eax, BS3_ADDR_BS3TEXT16 ; Convert it to a flat address. + mov [esp + 12], eax ; Store it in the place right for 32-bit returns. + %endif + popfd + pop ecx + pop eax + ret + + %if TMPL_BITS != 32 +TMPL_BEGIN_TEXT + %endif +%endif +BS3_PROC_END_MODE Bs3SwitchToPAE32 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToPAE32, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToPAE32) + BS3_SET_BITS 32 + + ; Jmp to common code for the tedious conversion. + %if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + extern _Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn_c32 + jmp _Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn_c32 + %else + extern _Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn_c32 + jmp _Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn_c32 + %endif + BS3_SET_BITS 16 +BS3_PROC_END_MODE Bs3SwitchToPAE32 +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE32_16.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE32_16.asm new file mode 100644 index 00000000..6a69d35e --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE32_16.asm @@ -0,0 +1,132 @@ +; $Id: bs3-mode-SwitchToPAE32_16.asm $ +;; @file +; BS3Kit - Bs3SwitchToPAE32_16 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to 16-bit code under 32-bit PAE paged protected mode sys/tss from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToPAE32_16(void); +; +; @uses Nothing (except high 32-bit register parts). +; +; @remarks Obviously returns to 16-bit mode, even if the caller was +; in 32-bit or 64-bit mode. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +%if TMPL_BITS == 16 +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToPAE32_16_Safe), function , 0 +%endif +BS3_PROC_BEGIN_MODE Bs3SwitchToPAE32_16, BS3_PBC_NEAR +%if TMPL_MODE == BS3_MODE_PAE32_16 + ret + +%elif TMPL_MODE == BS3_MODE_PAE32 + extern BS3_CMN_NM(Bs3SwitchTo16Bit) + jmp BS3_CMN_NM(Bs3SwitchTo16Bit) + +%else + ; + ; Switch to PAE32. + ; + extern TMPL_NM(Bs3SwitchToPAE32) + call TMPL_NM(Bs3SwitchToPAE32) + BS3_SET_BITS 32 + + ; + ; Make sure we're in the 16-bit segment and then do the switch to 16-bit. + ; + %if TMPL_BITS != 16 + jmp .sixteen_bit_segment +BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .sixteen_bit_segment + %endif + extern _Bs3SwitchTo16Bit_c32 + %if TMPL_BITS == 32 + jmp _Bs3SwitchTo16Bit_c32 + %else + call _Bs3SwitchTo16Bit_c32 + BS3_SET_BITS 16 + %if TMPL_BITS == 16 + ret + %else + ret 6 ; Return and pop 6 bytes of "parameters" (unused return address). + %endif + %endif +%endif +BS3_PROC_END_MODE Bs3SwitchToPAE32_16 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToPAE32_16, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToPAE32_16) + + %if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + ; Jmp to common code for the tedious conversion. + BS3_EXTERN_CMN Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn + jmp Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn + %else + pop bp + dec bp + retf + %endif +BS3_PROC_END_MODE Bs3SwitchToPAE32_16 + +%else +;; +; Safe far return to non-BS3TEXT16 code. +BS3_EXTERN_CMN Bs3SwitchHlpConvFlatRetToRetfProtMode +BS3_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_PROC_BEGIN_MODE Bs3SwitchToPAE32_16_Safe, BS3_PBC_NEAR + call Bs3SwitchHlpConvFlatRetToRetfProtMode ; Special internal function. Uses nothing, but modifies the stack. + call TMPL_NM(Bs3SwitchToPAE32_16) + BS3_SET_BITS 16 + retf +BS3_PROC_END_MODE Bs3SwitchToPAE32_16_Safe +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAEV86.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAEV86.asm new file mode 100644 index 00000000..288d0823 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAEV86.asm @@ -0,0 +1,118 @@ +; $Id: bs3-mode-SwitchToPAEV86.asm $ +;; @file +; BS3Kit - Bs3SwitchToPAEV86 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to 16-bit v8086 PAE paged protected mode with 32-bit sys+tss from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToPAEV86(void); +; +; @uses Nothing (except high 32-bit register parts). +; +; @remarks Obviously returns to 16-bit v8086 mode, even if the caller was +; in 32-bit or 64-bit mode. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +%if TMPL_BITS == 16 +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToPAEV86_Safe), function , 0 +%endif +BS3_PROC_BEGIN_MODE Bs3SwitchToPAEV86, BS3_PBC_NEAR +%if TMPL_MODE == BS3_MODE_PAEV86 + ret + +%else + ; + ; Switch to 32-bit PAE32 and from there to V8086. + ; + extern TMPL_NM(Bs3SwitchToPAE32) + call TMPL_NM(Bs3SwitchToPAE32) + BS3_SET_BITS 32 + + ; + ; Switch to v8086 mode after adjusting the return address. + ; + %if TMPL_BITS == 16 + push word [esp] + mov word [esp + 2], 0 + %elif TMPL_BITS == 64 + pop dword [esp + 4] + %endif + extern _Bs3SwitchTo16BitV86_c32 + jmp _Bs3SwitchTo16BitV86_c32 +%endif +BS3_PROC_END_MODE Bs3SwitchToPAEV86 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToPAEV86, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToPAEV86) + + %if !BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + ; Jmp to common code for the tedious conversion. + BS3_EXTERN_CMN Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn + jmp Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn + %else + pop bp + dec bp + retf + %endif +BS3_PROC_END_MODE Bs3SwitchToPAEV86 + +%else +;; +; Safe far return to non-BS3TEXT16 code. +BS3_EXTERN_CMN Bs3SwitchHlpConvFlatRetToRetfProtMode +BS3_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_PROC_BEGIN_MODE Bs3SwitchToPAEV86_Safe, BS3_PBC_NEAR + call Bs3SwitchHlpConvFlatRetToRetfProtMode ; Special internal function. Uses nothing, but modifies the stack. + call TMPL_NM(Bs3SwitchToPAEV86) + BS3_SET_BITS 16 + retf +BS3_PROC_END_MODE Bs3SwitchToPAEV86_Safe +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE16.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE16.asm new file mode 100644 index 00000000..058642be --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE16.asm @@ -0,0 +1,198 @@ +; $Id: bs3-mode-SwitchToPE16.asm $ +;; @file +; BS3Kit - Bs3SwitchToPE16 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to 16-bit unpaged protected mode from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToPE16(void); +; +; @uses Nothing (except high 32-bit register parts). +; +; @remarks Obviously returns to 16-bit mode, even if the caller was +; in 32-bit or 64-bit mode. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +%if TMPL_BITS == 16 +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToPE16_Safe), function , 0 +%endif +BS3_PROC_BEGIN_MODE Bs3SwitchToPE16, BS3_PBC_NEAR +%ifdef TMPL_PE16 + extern BS3_CMN_NM(Bs3SwitchToRing0) + call BS3_CMN_NM(Bs3SwitchToRing0) + push ax + mov ax, BS3_SEL_R0_DS16 + mov ds, ax + mov es, ax + pop ax + ret + +%elif BS3_MODE_IS_V86(TMPL_MODE) + ; + ; V8086 - Switch to 16-bit ring-0 and call worker for that mode. + ; + extern BS3_CMN_NM(Bs3SwitchToRing0) + call BS3_CMN_NM(Bs3SwitchToRing0) + extern %[BS3_MODE_R0_NM_ %+ TMPL_MODE](Bs3SwitchToPE16) + jmp %[BS3_MODE_R0_NM_ %+ TMPL_MODE](Bs3SwitchToPE16) + +%else + ; + ; Switch to 16-bit mode and prepare for returning in 16-bit mode. + ; + %if TMPL_BITS != 16 + shl xPRE [xSP], TMPL_BITS - 16 ; Adjust the return address. + add xSP, xCB - 2 + + ; Must be in 16-bit segment when calling Bs3SwitchTo16Bit. + jmp .sixteen_bit_segment +BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .sixteen_bit_segment + %endif + + ; + ; Switch to real mode. + ; + extern TMPL_NM(Bs3SwitchToRM) + call TMPL_NM(Bs3SwitchToRM) + BS3_SET_BITS 16 + + push ax + push cx + pushf + cli + + ; + ; Load the GDT and enable PE16. + ; +BS3_EXTERN_SYSTEM16 Bs3Lgdt_Gdt +BS3_EXTERN_SYSTEM16 Bs3LgdtDef_Gdt +BS3_BEGIN_TEXT16 + mov ax, BS3SYSTEM16 + mov ds, ax + lgdt [Bs3LgdtDef_Gdt] ; Will only load 24-bit base! + + smsw ax + or ax, X86_CR0_PE + lmsw ax + + ; + ; Convert from real mode stack to protected mode stack. + ; + mov ax, .p16_stack + extern NAME(Bs3ConvertRMStackToP16UsingCxReturnToAx_c16) + jmp NAME(Bs3ConvertRMStackToP16UsingCxReturnToAx_c16) +.p16_stack: + + ; + ; Call routine for doing mode specific setups. + ; + extern NAME(Bs3EnteredMode_pe16) + call NAME(Bs3EnteredMode_pe16) + + ; + ; Load full 32-bit GDT base address from 32-bit segment, if 386+ CPU. + ; + BS3_EXTERN_DATA16 g_uBs3CpuDetected + BS3_BEGIN_TEXT16 + cmp byte [g_uBs3CpuDetected], BS3CPU_80386 + jb .old_cpu_skip_32bit_lgdt + push ds + mov ax, BS3_SEL_SYSTEM16 + mov ds, ax + jmp dword BS3_SEL_R0_CS32:.load_full_gdt_base wrt FLAT +.load_full_gdt_base: + BS3_SET_BITS 32 + lgdt [Bs3Lgdt_Gdt wrt BS3SYSTEM16] + jmp BS3_SEL_R0_CS16:.back_to_16bit +.back_to_16bit: + BS3_SET_BITS 16 + pop ds +.old_cpu_skip_32bit_lgdt: + + popf + pop cx + pop ax + ret + + %if TMPL_BITS != 16 +TMPL_BEGIN_TEXT + %endif +%endif +BS3_PROC_END_MODE Bs3SwitchToPE16 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToPE16, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToPE16) + + %if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + ; Jmp to common code for the tedious conversion. + BS3_EXTERN_CMN Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn + jmp Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn + %else + pop bp + dec bp + retf + %endif +BS3_PROC_END_MODE Bs3SwitchToPE16 + +%else +;; +; Safe far return to non-BS3TEXT16 code. +BS3_EXTERN_CMN Bs3SwitchHlpConvFlatRetToRetfProtMode +BS3_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_PROC_BEGIN_MODE Bs3SwitchToPE16_Safe, BS3_PBC_NEAR + call Bs3SwitchHlpConvFlatRetToRetfProtMode ; Special internal function. Uses nothing, but modifies the stack. + call TMPL_NM(Bs3SwitchToPE16) + BS3_SET_BITS 16 + retf +BS3_PROC_END_MODE Bs3SwitchToPE16_Safe +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE16_32.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE16_32.asm new file mode 100644 index 00000000..587e6446 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE16_32.asm @@ -0,0 +1,114 @@ +; $Id: bs3-mode-SwitchToPE16_32.asm $ +;; @file +; BS3Kit - Bs3SwitchToPE16_32 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to 32-bit code under 16-bit unpaged protected mode sys/tss from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToPE16_32(void); +; +; @uses Nothing (except high 32-bit register parts). +; +; @remarks Obviously returns to 32-bit mode, even if the caller was +; in 16-bit or 64-bit mode. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToPE16_32_Safe), function, 0 +BS3_PROC_BEGIN_MODE Bs3SwitchToPE16_32, BS3_PBC_NEAR +%ifdef TMPL_PE16_32 + ret + +%else + ; + ; Make sure we're in the 16-bit segment and then call Bs3SwitchToPE16. + ; + %if TMPL_BITS != 16 + jmp .sixteen_bit_segment +BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .sixteen_bit_segment + %endif + extern TMPL_NM(Bs3SwitchToPE16) + call TMPL_NM(Bs3SwitchToPE16) + BS3_SET_BITS 16 + + ; + ; Switch to 32-bit mode. + ; + extern _Bs3SwitchTo32Bit_c16 + %if TMPL_BITS == 16 + jmp _Bs3SwitchTo32Bit_c16 + %else + call _Bs3SwitchTo32Bit_c16 + BS3_SET_BITS 32 + %if TMPL_BITS == 32 + ret + %else + ret 4 ; Return and pop 4 bytes of "parameters" (unused return address). + %endif + %endif +%endif +BS3_PROC_END_MODE Bs3SwitchToPE16_32 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToPE16_32, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToPE16_32) + BS3_SET_BITS 32 + + ; Jmp to common code for the tedious conversion. + %if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + extern _Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn_c32 + jmp _Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn_c32 + %else + extern _Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn_c32 + jmp _Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn_c32 + %endif + BS3_SET_BITS 16 +BS3_PROC_END_MODE Bs3SwitchToPE16_32 +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE16_V86.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE16_V86.asm new file mode 100644 index 00000000..84fb26d9 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE16_V86.asm @@ -0,0 +1,124 @@ +; $Id: bs3-mode-SwitchToPE16_V86.asm $ +;; @file +; BS3Kit - Bs3SwitchToPE16_V86 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to 16-bit unpaged protected mode with 16-bit sys+tss from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToPE16(void); +; +; @uses Nothing (except high 32-bit register parts). +; +; @remarks Obviously returns to 16-bit v8086 mode, even if the caller was +; in 16-bit, 32-bit or 64-bit mode. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +%if TMPL_BITS == 16 +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToPE16_V86_Safe), function , 0 +%endif +BS3_PROC_BEGIN_MODE Bs3SwitchToPE16_V86, BS3_PBC_NEAR +%ifdef TMPL_PE16_V86 + ret + +%else + ; + ; Convert the return address and jump to the 16-bit code segment. + ; + %if TMPL_BITS != 16 + shl xPRE [xSP], TMPL_BITS - 16 + add xSP, (TMPL_BITS - 16) / 8 + jmp .sixteen_bit_segment +BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .sixteen_bit_segment + %endif + + ; + ; Switch to 16-bit PE16 and from there to V8086. + ; + extern TMPL_NM(Bs3SwitchToPE16) + call TMPL_NM(Bs3SwitchToPE16) + BS3_SET_BITS 16 + + ; + ; Switch to v8086 mode (return address is already 16-bit). + ; + extern _Bs3SwitchTo16BitV86_c16 + jmp _Bs3SwitchTo16BitV86_c16 +%endif +BS3_PROC_END_MODE Bs3SwitchToPE16_V86 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToPE16_V86, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToPE16_V86) + + %if !BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + ; Jmp to common code for the tedious conversion. + BS3_EXTERN_CMN Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn + jmp Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn + %else + pop bp + dec bp + retf + %endif +BS3_PROC_END_MODE Bs3SwitchToPE16_V86 + +%else +;; +; Safe far return to non-BS3TEXT16 code. +BS3_EXTERN_CMN Bs3SwitchHlpConvFlatRetToRetfProtMode +BS3_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_PROC_BEGIN_MODE Bs3SwitchToPE16_V86_Safe, BS3_PBC_NEAR + call Bs3SwitchHlpConvFlatRetToRetfProtMode ; Special internal function. Uses nothing, but modifies the stack. + call TMPL_NM(Bs3SwitchToPE16_V86) + BS3_SET_BITS 16 + retf +BS3_PROC_END_MODE Bs3SwitchToPE16_V86_Safe +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE32.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE32.asm new file mode 100644 index 00000000..9030dd5b --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE32.asm @@ -0,0 +1,179 @@ +; $Id: bs3-mode-SwitchToPE32.asm $ +;; @file +; BS3Kit - Bs3SwitchToPE32 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to 32-bit unpaged protected mode from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToPE32(void); +; +; @uses Nothing (except high 32-bit register parts), upper part of ESP is +; cleared if caller is in 16-bit mode. +; +; @remarks Obviously returns to 32-bit mode, even if the caller was +; in 16-bit or 64-bit mode. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToPE32_Safe), function, 0 +BS3_PROC_BEGIN_MODE Bs3SwitchToPE32, BS3_PBC_NEAR +%ifdef TMPL_PE32 + ret + +%elif BS3_MODE_IS_V86(TMPL_MODE) + ; + ; V8086 - Switch to 16-bit ring-0 and call worker for that mode. + ; + extern BS3_CMN_NM(Bs3SwitchToRing0) + call BS3_CMN_NM(Bs3SwitchToRing0) + extern %[BS3_MODE_R0_NM_ %+ TMPL_MODE](Bs3SwitchToPE32) + jmp %[BS3_MODE_R0_NM_ %+ TMPL_MODE](Bs3SwitchToPE32) + +%else + ; + ; Switch to real mode. + ; + %if TMPL_BITS != 32 + %if TMPL_BITS > 32 + shl xPRE [xSP], 32 ; Adjust the return address from 64-bit to 32-bit. + add rsp, xCB - 4 + %else + push word 0 ; Reserve space to expand the return address. + %endif + %endif + %if TMPL_BITS != 16 + ; Must be in 16-bit segment when calling Bs3SwitchTo16Bit. + jmp .sixteen_bit_segment +BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .sixteen_bit_segment + %endif + ; + ; Switch to real mode. + ; + extern TMPL_NM(Bs3SwitchToRM) + call TMPL_NM(Bs3SwitchToRM) + BS3_SET_BITS 16 + + push eax + pushfd + cli + + ; + ; Load the GDT and enable PE32. + ; +BS3_EXTERN_SYSTEM16 Bs3LgdtDef_Gdt +BS3_EXTERN_SYSTEM16 Bs3Lgdt_Gdt +BS3_BEGIN_TEXT16 + mov ax, BS3SYSTEM16 + mov ds, ax + lgdt [Bs3LgdtDef_Gdt] ; Will only load 24-bit base! + + mov eax, cr0 + or eax, X86_CR0_PE + mov cr0, eax + jmp BS3_SEL_R0_CS32:dword .thirty_two_bit wrt FLAT +BS3_BEGIN_TEXT32 +BS3_GLOBAL_LOCAL_LABEL .thirty_two_bit + + ; + ; Convert the (now) real mode stack pointer to 32-bit flat. + ; + xor eax, eax + mov ax, ss + shl eax, 4 + and esp, 0ffffh + add esp, eax + + mov ax, BS3_SEL_R0_SS32 + mov ss, ax + + ; + ; Call rountine for doing mode specific setups. + ; + extern NAME(Bs3EnteredMode_pe32) + call NAME(Bs3EnteredMode_pe32) + + ; Load full 32-bit GDT base address. + lgdt [Bs3Lgdt_Gdt wrt FLAT] + + ; + ; Restore eax and flags (IF). + ; + %if TMPL_BITS < 32 + and esp, 0ffffh ; Make sure the high word is zero. + movzx eax, word [esp + 8 + 2] ; Load return address. + add eax, BS3_ADDR_BS3TEXT16 ; Convert it to a flat address. + mov [esp + 8], eax ; Store it in the place right for 32-bit returns. + %endif + popfd + pop eax + ret + + %if TMPL_BITS != 32 +TMPL_BEGIN_TEXT + %endif +%endif +BS3_PROC_END_MODE Bs3SwitchToPE32 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToPE32, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToPE32) + BS3_SET_BITS 32 + + ; Jmp to common code for the tedious conversion. + %if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + extern _Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn_c32 + jmp _Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn_c32 + %else + extern _Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn_c32 + jmp _Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn_c32 + %endif + BS3_SET_BITS 16 +BS3_PROC_END_MODE Bs3SwitchToPE32 +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE32_16.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE32_16.asm new file mode 100644 index 00000000..4dc5b926 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE32_16.asm @@ -0,0 +1,132 @@ +; $Id: bs3-mode-SwitchToPE32_16.asm $ +;; @file +; BS3Kit - Bs3SwitchToPE32_16 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to 16-bit code under 32-bit unpaged protected mode sys/tss from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToPE32_16(void); +; +; @uses Nothing (except high 32-bit register parts). +; +; @remarks Obviously returns to 16-bit mode, even if the caller was +; in 32-bit or 64-bit mode. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +%if TMPL_BITS == 16 +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToPE32_16_Safe), function , 0 +%endif +BS3_PROC_BEGIN_MODE Bs3SwitchToPE32_16, BS3_PBC_NEAR +%if TMPL_MODE == BS3_MODE_PE32_16 + ret + +%elif TMPL_MODE == BS3_MODE_PE32 + extern BS3_CMN_NM(Bs3SwitchTo16Bit) + jmp BS3_CMN_NM(Bs3SwitchTo16Bit) + +%else + ; + ; Switch to PE32. + ; + extern TMPL_NM(Bs3SwitchToPE32) + call TMPL_NM(Bs3SwitchToPE32) + BS3_SET_BITS 32 + + ; + ; Make sure we're in the 16-bit segment and then do the switch to 16-bit. + ; + %if TMPL_BITS != 16 + jmp .sixteen_bit_segment +BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .sixteen_bit_segment + %endif + extern _Bs3SwitchTo16Bit_c32 + %if TMPL_BITS == 32 + jmp _Bs3SwitchTo16Bit_c32 + %else + call _Bs3SwitchTo16Bit_c32 + BS3_SET_BITS 16 + %if TMPL_BITS == 16 + ret + %else + ret 6 ; Return and pop 6 bytes of "parameters" (unused return address). + %endif + %endif +%endif +BS3_PROC_END_MODE Bs3SwitchToPE32_16 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToPE32_16, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToPE32_16) + + %if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + ; Jmp to common code for the tedious conversion. + BS3_EXTERN_CMN Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn + jmp Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn + %else + pop bp + dec bp + retf + %endif +BS3_PROC_END_MODE Bs3SwitchToPE32_16 + +%else +;; +; Safe far return to non-BS3TEXT16 code. +BS3_EXTERN_CMN Bs3SwitchHlpConvFlatRetToRetfProtMode +BS3_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_PROC_BEGIN_MODE Bs3SwitchToPE32_16_Safe, BS3_PBC_NEAR + call Bs3SwitchHlpConvFlatRetToRetfProtMode ; Special internal function. Uses nothing, but modifies the stack. + call TMPL_NM(Bs3SwitchToPE32_16) + BS3_SET_BITS 16 + retf +BS3_PROC_END_MODE Bs3SwitchToPE32_16_Safe +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPEV86.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPEV86.asm new file mode 100644 index 00000000..7613f9ef --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPEV86.asm @@ -0,0 +1,118 @@ +; $Id: bs3-mode-SwitchToPEV86.asm $ +;; @file +; BS3Kit - Bs3SwitchToPEV86 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to 16-bit v8086 unpaged protected mode with 32-bit sys+tss from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToPEV86(void); +; +; @uses Nothing (except high 32-bit register parts). +; +; @remarks Obviously returns to 16-bit v8086 mode, even if the caller was +; in 32-bit or 64-bit mode. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +%if TMPL_BITS == 16 +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToPEV86_Safe), function , 0 +%endif +BS3_PROC_BEGIN_MODE Bs3SwitchToPEV86, BS3_PBC_NEAR +%if TMPL_MODE == BS3_MODE_PEV86 + ret + +%else + ; + ; Switch to 32-bit PE32 and from there to V8086. + ; + extern TMPL_NM(Bs3SwitchToPE32) + call TMPL_NM(Bs3SwitchToPE32) + BS3_SET_BITS 32 + + ; + ; Switch to v8086 mode after adjusting the return address. + ; + %if TMPL_BITS == 16 + push word [esp] + mov word [esp + 2], 0 + %elif TMPL_BITS == 64 + pop dword [esp + 4] + %endif + extern _Bs3SwitchTo16BitV86_c32 + jmp _Bs3SwitchTo16BitV86_c32 +%endif +BS3_PROC_END_MODE Bs3SwitchToPEV86 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToPEV86, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToPEV86) + + %if !BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + ; Jmp to common code for the tedious conversion. + BS3_EXTERN_CMN Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn + jmp Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn + %else + pop bp + dec bp + retf + %endif +BS3_PROC_END_MODE Bs3SwitchToPEV86 + +%else +;; +; Safe far return to non-BS3TEXT16 code. +BS3_EXTERN_CMN Bs3SwitchHlpConvFlatRetToRetfProtMode +BS3_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_PROC_BEGIN_MODE Bs3SwitchToPEV86_Safe, BS3_PBC_NEAR + call Bs3SwitchHlpConvFlatRetToRetfProtMode ; Special internal function. Uses nothing, but modifies the stack. + call TMPL_NM(Bs3SwitchToPEV86) + BS3_SET_BITS 16 + retf +BS3_PROC_END_MODE Bs3SwitchToPEV86_Safe +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP16.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP16.asm new file mode 100644 index 00000000..3986939d --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP16.asm @@ -0,0 +1,258 @@ +; $Id: bs3-mode-SwitchToPP16.asm $ +;; @file +; BS3Kit - Bs3SwitchToPP16 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +%ifndef TMPL_PP16 +BS3_BEGIN_TEXT16 +extern NAME(Bs3EnteredMode_pp16) + %ifdef TMPL_PP32 + BS3_EXTERN_CMN Bs3SwitchTo16Bit + %endif +TMPL_BEGIN_TEXT +%endif + + +;; +; Switch to 16-bit paged protected mode from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToPP16(void); +; +; @uses Nothing (except high 32-bit register parts). +; +; @remarks Obviously returns to 16-bit mode, even if the caller was +; in 32-bit or 64-bit mode. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +%if TMPL_BITS == 16 +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToPP16_Safe), function , 0 +%endif +BS3_PROC_BEGIN_MODE Bs3SwitchToPP16, BS3_PBC_NEAR +%ifdef TMPL_PP16 + extern BS3_CMN_NM(Bs3SwitchToRing0) + call BS3_CMN_NM(Bs3SwitchToRing0) + push ax + mov ax, BS3_SEL_R0_DS16 + mov ds, ax + mov es, ax + pop ax + ret + +%elif BS3_MODE_IS_V86(TMPL_MODE) + ; + ; V8086 - Switch to 16-bit ring-0 and call worker for that mode. + ; + extern BS3_CMN_NM(Bs3SwitchToRing0) + call BS3_CMN_NM(Bs3SwitchToRing0) + extern %[BS3_MODE_R0_NM_ %+ TMPL_MODE](Bs3SwitchToPP16) + jmp %[BS3_MODE_R0_NM_ %+ TMPL_MODE](Bs3SwitchToPP16) + +%else + + ; + ; Switch to 16-bit text segment and prepare for returning in 16-bit mode. + ; + %if TMPL_BITS != 16 + shl xPRE [xSP], TMPL_BITS - 16 ; Adjust the return address. + add xSP, xCB - 2 + + ; Must be in 16-bit segment when calling Bs3SwitchToRM and Bs3SwitchTo16Bit. + jmp .sixteen_bit_segment +BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .sixteen_bit_segment + %endif + + %ifdef TMPL_PP32 + ; + ; No need to go to real-mode here, we use the same CR3 and stuff. + ; Just switch to 32-bit mode and call the Bs3EnteredMode routine to + ; load the right descriptor tables. + ; + call Bs3SwitchTo16Bit + BS3_SET_BITS 16 + call NAME(Bs3EnteredMode_pp16) + ret + %else + + ; + ; Switch to real mode. + ; + extern TMPL_NM(Bs3SwitchToRM) + call TMPL_NM(Bs3SwitchToRM) + BS3_SET_BITS 16 + + push eax + push ecx + pushfd +%ifdef BS3_STRICT + mov ax, ds + cmp ax, BS3_ADDR_BS3DATA16 >> 4 + je .real_mode_ds_ok + hlt +.real_mode_ds_ok: +%endif + + ; + ; Get the page directory (returned in eax). + ; Will lazy init page tables (in 16-bit prot mode). + ; + extern NAME(Bs3PagingGetRootForPP16_rm) + call NAME(Bs3PagingGetRootForPP16_rm) + + cli + mov cr3, eax + + ; + ; Make sure PAE is really off and that PSE is enabled when supported. + ; +BS3_EXTERN_DATA16 g_uBs3CpuDetected +BS3_BEGIN_TEXT16 + test byte [1 + BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_CPUID >> 8) + jz .cr4_is_fine + mov eax, cr4 + mov ecx, eax + and eax, ~(X86_CR4_PAE | X86_CR4_PSE) + test byte [1 + BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_PSE >> 8) + jz .no_pse + or eax, X86_CR4_PSE +.no_pse: + cmp eax, ecx + je .cr4_is_fine + mov cr4, eax +.cr4_is_fine: + + ; + ; Load the GDT and enable PP16. + ; +BS3_EXTERN_SYSTEM16 Bs3LgdtDef_Gdt +BS3_EXTERN_SYSTEM16 Bs3Lgdt_Gdt +BS3_BEGIN_TEXT16 + mov ax, BS3SYSTEM16 + mov ds, ax + lgdt [Bs3LgdtDef_Gdt] ; Will only load 24-bit base! + + mov eax, cr0 + or eax, X86_CR0_PE | X86_CR0_PG + mov cr0, eax + jmp BS3_SEL_R0_CS16:.reload_cs_and_stuff +.reload_cs_and_stuff: + + ; + ; Convert the (now) real mode stack to 16-bit. + ; + mov ax, .stack_fix_return + extern NAME(Bs3ConvertRMStackToP16UsingCxReturnToAx_c16) + jmp NAME(Bs3ConvertRMStackToP16UsingCxReturnToAx_c16) +.stack_fix_return: + + ; + ; Call rountine for doing mode specific setups. + ; + call NAME(Bs3EnteredMode_pp16) + + ; + ; Load full 32-bit GDT base address from 32-bit segment. + ; + push ds + mov ax, BS3_SEL_SYSTEM16 + mov ds, ax + jmp dword BS3_SEL_R0_CS32:.load_full_gdt_base wrt FLAT +.load_full_gdt_base: + BS3_SET_BITS 32 + lgdt [Bs3Lgdt_Gdt wrt BS3SYSTEM16] + jmp BS3_SEL_R0_CS16:.back_to_16bit +.back_to_16bit: + BS3_SET_BITS 16 + pop ds + + popfd + pop ecx + pop eax + ret + + %endif ; !TMPL_PP32 + %if TMPL_BITS != 16 +TMPL_BEGIN_TEXT + %endif +%endif +BS3_PROC_END_MODE Bs3SwitchToPP16 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToPP16, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToPP16) + + %if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + ; Jmp to common code for the tedious conversion. + BS3_EXTERN_CMN Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn + jmp Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn + %else + pop bp + dec bp + retf + %endif +BS3_PROC_END_MODE Bs3SwitchToPP16 + +%else +;; +; Safe far return to non-BS3TEXT16 code. +BS3_EXTERN_CMN Bs3SwitchHlpConvFlatRetToRetfProtMode +BS3_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_PROC_BEGIN_MODE Bs3SwitchToPP16_Safe, BS3_PBC_NEAR + call Bs3SwitchHlpConvFlatRetToRetfProtMode ; Special internal function. Uses nothing, but modifies the stack. + call TMPL_NM(Bs3SwitchToPP16) + BS3_SET_BITS 16 + retf +BS3_PROC_END_MODE Bs3SwitchToPP16_Safe +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP16_32.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP16_32.asm new file mode 100644 index 00000000..0dc97c3a --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP16_32.asm @@ -0,0 +1,114 @@ +; $Id: bs3-mode-SwitchToPP16_32.asm $ +;; @file +; BS3Kit - Bs3SwitchToPP16_32 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to 32-bit code under 16-bit paged protected mode sys/tss from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToPP16_32(void); +; +; @uses Nothing (except high 32-bit register parts). +; +; @remarks Obviously returns to 32-bit mode, even if the caller was +; in 16-bit or 64-bit mode. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToPP16_32_Safe), function, 0 +BS3_PROC_BEGIN_MODE Bs3SwitchToPP16_32, BS3_PBC_NEAR +%ifdef TMPL_PP16_32 + ret + +%else + ; + ; Make sure we're in the 16-bit segment and then call Bs3SwitchToPP16. + ; + %if TMPL_BITS != 16 + jmp .sixteen_bit_segment +BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .sixteen_bit_segment + %endif + extern TMPL_NM(Bs3SwitchToPP16) + call TMPL_NM(Bs3SwitchToPP16) + BS3_SET_BITS 16 + + ; + ; Switch to 32-bit mode. + ; + extern _Bs3SwitchTo32Bit_c16 + %if TMPL_BITS == 16 + jmp _Bs3SwitchTo32Bit_c16 + %else + call _Bs3SwitchTo32Bit_c16 + BS3_SET_BITS 32 + %if TMPL_BITS == 32 + ret + %else + ret 4 ; Return and pop 4 bytes of "parameters" (unused return address). + %endif + %endif +%endif +BS3_PROC_END_MODE Bs3SwitchToPP16_32 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToPP16_32, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToPP16_32) + BS3_SET_BITS 32 + + ; Jmp to common code for the tedious conversion. + %if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + extern _Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn_c32 + jmp _Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn_c32 + %else + extern _Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn_c32 + jmp _Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn_c32 + %endif + BS3_SET_BITS 16 +BS3_PROC_END_MODE Bs3SwitchToPP16_32 +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP16_V86.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP16_V86.asm new file mode 100644 index 00000000..0647fa90 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP16_V86.asm @@ -0,0 +1,124 @@ +; $Id: bs3-mode-SwitchToPP16_V86.asm $ +;; @file +; BS3Kit - Bs3SwitchToPP16_V86 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to 16-bit paged protected mode with 16-bit sys+tss from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToPP16(void); +; +; @uses Nothing (except high 32-bit register parts). +; +; @remarks Obviously returns to v8086 16-bit mode, even if the caller was +; in 16-bit, 32-bit or 64-bit mode. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +%if TMPL_BITS == 16 +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToPP16_V86_Safe), function , 0 +%endif +BS3_PROC_BEGIN_MODE Bs3SwitchToPP16_V86, BS3_PBC_NEAR +%ifdef TMPL_PP16_V86 + ret + +%else + ; + ; Convert the return address and jump to the 16-bit code segment. + ; + %if TMPL_BITS != 16 + shl xPRE [xSP], TMPL_BITS - 16 + add xSP, (TMPL_BITS - 16) / 8 + jmp .sixteen_bit_segment +BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .sixteen_bit_segment + %endif + + ; + ; Switch to 16-bit PP16 and from there to V8086. + ; + extern TMPL_NM(Bs3SwitchToPP16) + call TMPL_NM(Bs3SwitchToPP16) + BS3_SET_BITS 16 + + ; + ; Switch to v8086 mode (return address is already 16-bit). + ; + extern _Bs3SwitchTo16BitV86_c16 + jmp _Bs3SwitchTo16BitV86_c16 +%endif +BS3_PROC_END_MODE Bs3SwitchToPP16_V86 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToPP16_V86, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToPP16_V86) + + %if !BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + ; Jmp to common code for the tedious conversion. + BS3_EXTERN_CMN Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn + jmp Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn + %else + pop bp + dec bp + retf + %endif +BS3_PROC_END_MODE Bs3SwitchToPP16_V86 + +%else +;; +; Safe far return to non-BS3TEXT16 code. +BS3_EXTERN_CMN Bs3SwitchHlpConvFlatRetToRetfProtMode +BS3_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_PROC_BEGIN_MODE Bs3SwitchToPP16_V86_Safe, BS3_PBC_NEAR + call Bs3SwitchHlpConvFlatRetToRetfProtMode ; Special internal function. Uses nothing, but modifies the stack. + call TMPL_NM(Bs3SwitchToPP16_V86) + BS3_SET_BITS 16 + retf +BS3_PROC_END_MODE Bs3SwitchToPP16_V86_Safe +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP32.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP32.asm new file mode 100644 index 00000000..455127f5 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP32.asm @@ -0,0 +1,209 @@ +; $Id: bs3-mode-SwitchToPP32.asm $ +;; @file +; BS3Kit - Bs3SwitchToPP32 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to 32-bit paged protected mode from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToPE32(void); +; +; @uses Nothing (except high 32-bit register parts), upper part of ESP is +; cleared if caller is in 16-bit mode. +; +; @remarks Obviously returns to 32-bit mode, even if the caller was +; in 16-bit or 64-bit mode. It doesn't not preserve the callers +; ring, but instead changes to ring-0. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToPP32_Safe), function, 0 +BS3_PROC_BEGIN_MODE Bs3SwitchToPP32, BS3_PBC_NEAR +%ifdef TMPL_PP32 + ret + +%elif BS3_MODE_IS_V86(TMPL_MODE) + ; + ; V8086 - Switch to 16-bit ring-0 and call worker for that mode. + ; + extern BS3_CMN_NM(Bs3SwitchToRing0) + call BS3_CMN_NM(Bs3SwitchToRing0) + extern %[BS3_MODE_R0_NM_ %+ TMPL_MODE](Bs3SwitchToPP32) + jmp %[BS3_MODE_R0_NM_ %+ TMPL_MODE](Bs3SwitchToPP32) + +%else + ; + ; Switch to real mode. + ; + %if TMPL_BITS != 32 + %if TMPL_BITS > 32 + shl xPRE [xSP], 32 ; Adjust the return address from 64-bit to 32-bit. + add rsp, xCB - 4 + %else + push word 0 ; Reserve space to expand the return address. + %endif + %endif + %if TMPL_BITS != 16 + ; Must be in 16-bit segment when calling Bs3SwitchTo16Bit. + jmp .sixteen_bit_segment +BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .sixteen_bit_segment + %endif + + ; + ; Switch to real mode. + ; + extern TMPL_NM(Bs3SwitchToRM) + call TMPL_NM(Bs3SwitchToRM) + BS3_SET_BITS 16 + + push eax + push ecx + pushfd + + ; + ; Make sure PAE is really off and that PSE is on when supported. + ; +BS3_EXTERN_DATA16 g_uBs3CpuDetected +BS3_BEGIN_TEXT16 + test byte [1 + BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_CPUID >> 8) + jz .cr4_is_fine + mov eax, cr4 + mov ecx, eax + and eax, ~(X86_CR4_PAE | X86_CR4_PSE) + test byte [1 + BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_PSE >> 8) + jz .no_pse + or eax, X86_CR4_PSE +.no_pse: + cmp eax, ecx + je .cr4_is_fine + mov cr4, eax +.cr4_is_fine: + + ; + ; Get the page directory (returned in eax). + ; Will lazy init page tables (in 16-bit prot mode). + ; + extern NAME(Bs3PagingGetRootForPP32_rm) + call NAME(Bs3PagingGetRootForPP32_rm) + + cli + mov cr3, eax + + ; + ; Load the GDT and enable PE32. + ; +BS3_EXTERN_SYSTEM16 Bs3LgdtDef_Gdt +BS3_EXTERN_SYSTEM16 Bs3Lgdt_Gdt +BS3_BEGIN_TEXT16 + mov ax, BS3SYSTEM16 + mov ds, ax + lgdt [Bs3LgdtDef_Gdt] ; Will only load 24-bit base! + + mov eax, cr0 + or eax, X86_CR0_PE | X86_CR0_PG + mov cr0, eax + jmp BS3_SEL_R0_CS32:dword .thirty_two_bit wrt FLAT +BS3_BEGIN_TEXT32 +BS3_GLOBAL_LOCAL_LABEL .thirty_two_bit + ; + ; Convert the (now) real mode stack pointer to 32-bit flat. + ; + xor eax, eax + mov ax, ss + shl eax, 4 + and esp, 0ffffh + add esp, eax + + mov ax, BS3_SEL_R0_SS32 + mov ss, ax + + ; + ; Call rountine for doing mode specific setups. + ; + extern NAME(Bs3EnteredMode_pp32) + call NAME(Bs3EnteredMode_pp32) + + ; Load full 32-bit GDT base address. + lgdt [Bs3Lgdt_Gdt wrt FLAT] + + ; + ; Restore ecx, eax and flags (IF). + ; + %if TMPL_BITS < 32 + movzx eax, word [esp + 12 + 2] ; Load return address. + add eax, BS3_ADDR_BS3TEXT16 ; Convert it to a flat address. + mov [esp + 12], eax ; Store it in the place right for 32-bit returns. + %endif + popfd + pop ecx + pop eax + ret + + %if TMPL_BITS != 32 +TMPL_BEGIN_TEXT + %endif +%endif +BS3_PROC_END_MODE Bs3SwitchToPP32 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToPP32, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToPP32) + BS3_SET_BITS 32 + + ; Jmp to common code for the tedious conversion. + %if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + extern _Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn_c32 + jmp _Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn_c32 + %else + extern _Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn_c32 + jmp _Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn_c32 + %endif + BS3_SET_BITS 16 +BS3_PROC_END_MODE Bs3SwitchToPP32 +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP32_16.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP32_16.asm new file mode 100644 index 00000000..41f14beb --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP32_16.asm @@ -0,0 +1,132 @@ +; $Id: bs3-mode-SwitchToPP32_16.asm $ +;; @file +; BS3Kit - Bs3SwitchToPP32_16 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to 16-bit code under 32-bit paged protected mode sys/tss from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToPP32_16(void); +; +; @uses Nothing (except high 32-bit register parts). +; +; @remarks Obviously returns to 16-bit mode, even if the caller was +; in 32-bit or 64-bit mode. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +%if TMPL_BITS == 16 +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToPP32_16_Safe), function , 0 +%endif +BS3_PROC_BEGIN_MODE Bs3SwitchToPP32_16, BS3_PBC_NEAR +%if TMPL_MODE == BS3_MODE_PP32_16 + ret + +%elif TMPL_MODE == BS3_MODE_PP32 + extern BS3_CMN_NM(Bs3SwitchTo16Bit) + jmp BS3_CMN_NM(Bs3SwitchTo16Bit) + +%else + ; + ; Switch to PP32. + ; + extern TMPL_NM(Bs3SwitchToPP32) + call TMPL_NM(Bs3SwitchToPP32) + BS3_SET_BITS 32 + + ; + ; Make sure we're in the 16-bit segment and then do the switch to 16-bit. + ; + %if TMPL_BITS != 16 + jmp .sixteen_bit_segment +BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +.sixteen_bit_segment: + %endif + extern _Bs3SwitchTo16Bit_c32 + %if TMPL_BITS == 32 + jmp _Bs3SwitchTo16Bit_c32 + %else + call _Bs3SwitchTo16Bit_c32 + BS3_SET_BITS 16 + %if TMPL_BITS == 16 + ret + %else + ret 6 ; Return and pop 6 bytes of "parameters" (unused return address). + %endif + %endif +%endif +BS3_PROC_END_MODE Bs3SwitchToPP32_16 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToPP32_16, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToPP32_16) + + %if BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + ; Jmp to common code for the tedious conversion. + BS3_EXTERN_CMN Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn + jmp Bs3SwitchHlpConvRealModeRetfPopBpDecBpAndReturn + %else + pop bp + dec bp + retf + %endif +BS3_PROC_END_MODE Bs3SwitchToPP32_16 + +%else +;; +; Safe far return to non-BS3TEXT16 code. +BS3_EXTERN_CMN Bs3SwitchHlpConvFlatRetToRetfProtMode +BS3_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_PROC_BEGIN_MODE Bs3SwitchToPP32_16_Safe, BS3_PBC_NEAR + call Bs3SwitchHlpConvFlatRetToRetfProtMode ; Special internal function. Uses nothing, but modifies the stack. + call TMPL_NM(Bs3SwitchToPP32_16) + BS3_SET_BITS 16 + retf +BS3_PROC_END_MODE Bs3SwitchToPP32_16_Safe +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPPV86.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPPV86.asm new file mode 100644 index 00000000..9d492b9a --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPPV86.asm @@ -0,0 +1,118 @@ +; $Id: bs3-mode-SwitchToPPV86.asm $ +;; @file +; BS3Kit - Bs3SwitchToPPV86 +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; Switch to 16-bit v8086 paged protected mode with 32-bit sys+tss from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToPPV86(void); +; +; @uses Nothing (except high 32-bit register parts). +; +; @remarks Obviously returns to 16-bit v8086 mode, even if the caller was +; in 32-bit or 64-bit mode. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +%if TMPL_BITS == 16 +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToPPV86_Safe), function , 0 +%endif +BS3_PROC_BEGIN_MODE Bs3SwitchToPPV86, BS3_PBC_NEAR +%if TMPL_MODE == BS3_MODE_PPV86 + ret + +%else + ; + ; Switch to 32-bit PP32 and from there to V8086. + ; + extern TMPL_NM(Bs3SwitchToPP32) + call TMPL_NM(Bs3SwitchToPP32) + BS3_SET_BITS 32 + + ; + ; Switch to v8086 mode after adjusting the return address. + ; + %if TMPL_BITS == 16 + push word [esp] + mov word [esp + 2], 0 + %elif TMPL_BITS == 64 + pop dword [esp + 4] + %endif + extern _Bs3SwitchTo16BitV86_c32 + jmp _Bs3SwitchTo16BitV86_c32 +%endif +BS3_PROC_END_MODE Bs3SwitchToPPV86 + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToPPV86, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToPPV86) + + %if !BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + ; Jmp to common code for the tedious conversion. + BS3_EXTERN_CMN Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn + jmp Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn + %else + pop bp + dec bp + retf + %endif +BS3_PROC_END_MODE Bs3SwitchToPPV86 + +%else +;; +; Safe far return to non-BS3TEXT16 code. +BS3_EXTERN_CMN Bs3SwitchHlpConvFlatRetToRetfProtMode +BS3_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_PROC_BEGIN_MODE Bs3SwitchToPPV86_Safe, BS3_PBC_NEAR + call Bs3SwitchHlpConvFlatRetToRetfProtMode ; Special internal function. Uses nothing, but modifies the stack. + call TMPL_NM(Bs3SwitchToPPV86) + BS3_SET_BITS 16 + retf +BS3_PROC_END_MODE Bs3SwitchToPPV86_Safe +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToRM.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToRM.asm new file mode 100644 index 00000000..3e67cb3a --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToRM.asm @@ -0,0 +1,411 @@ +; $Id: bs3-mode-SwitchToRM.asm $ +;; @file +; BS3Kit - Bs3SwitchToRM +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +BS3_EXTERN_SYSTEM16 Bs3Gdt +%if TMPL_MODE == BS3_MODE_PE16 +BS3_EXTERN_DATA16 g_uBs3CpuDetected +BS3_EXTERN_CMN Bs3KbdWrite +BS3_EXTERN_CMN Bs3KbdWait +%endif + + +;********************************************************************************************************************************* +;* Global Variables * +;********************************************************************************************************************************* +%if TMPL_MODE == BS3_MODE_PE16 +BS3_BEGIN_DATA16 +;; Where to start restoring stack. +g_ResumeSp: dw 0xfeed +;; Where to start restoring stack. +g_ResumeSs: dw 0xface +%endif + +TMPL_BEGIN_TEXT + + +;; +; Switch to real mode from any other mode. +; +; @cproto BS3_DECL(void) Bs3SwitchToRM(void); +; +; @uses GPRs and EFLAGS are unchanged (except high 32-bit register (AMD64) parts). +; CS is loaded with CGROUP16. +; SS:[RE]SP is converted to real mode address. +; DS and ES are loaded with BS3DATA16_GROUP. +; FS and GS are loaded with zero if present. +; +; @remarks Obviously returns to 16-bit mode, even if the caller was +; in 32-bit or 64-bit mode. +; +; @remarks Does not require 20h of parameter scratch space in 64-bit mode. +; +%if TMPL_BITS == 16 +BS3_GLOBAL_NAME_EX TMPL_NM(Bs3SwitchToRM_Safe), function , 0 +%endif +BS3_PROC_BEGIN_MODE Bs3SwitchToRM, BS3_PBC_NEAR +%ifdef TMPL_RM + push ax + mov ax, BS3_SEL_DATA16 + mov ds, ax + mov es, ax + pop ax + ret + +%elif BS3_MODE_IS_V86(TMPL_MODE) + ; + ; V8086 - Switch to 16-bit ring-0 and call worker for that mode. + ; + extern BS3_CMN_NM(Bs3SwitchToRing0) + call BS3_CMN_NM(Bs3SwitchToRing0) + extern %[BS3_MODE_R0_NM_ %+ TMPL_MODE](Bs3SwitchToRM) + jmp %[BS3_MODE_R0_NM_ %+ TMPL_MODE](Bs3SwitchToRM) + +%else + ; + ; Protected mode. + ; 80286 requirements for PE16 clutters the code a little. + ; + %if TMPL_MODE == BS3_MODE_PE16 + cmp byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80286 + ja .do_386_prologue + push ax + push bx + pushf + push word 1 + jmp .done_prologue + %endif +.do_386_prologue: + push sAX + push sBX + sPUSHF + %if TMPL_MODE == BS3_MODE_PE16 + push word 0 + %elif BS3_MODE_IS_64BIT_SYS(TMPL_MODE) + push sDX + push sCX + %endif +.done_prologue: + + ; + ; Get to 16-bit ring-0 and disable interrupts. + ; + extern BS3_CMN_NM(Bs3SwitchToRing0) + call BS3_CMN_NM(Bs3SwitchToRing0) + + cli + + %if TMPL_MODE == BS3_MODE_PE16 + ; + ; On 80286 we must reset the CPU to get back to real mode. + ; + CPU 286 + pop ax + push ax + test ax, ax + jz .is_386_or_better + + ; Save registers and flags, storing SS:SP in at a known global address. +%ifdef BS3_STRICT + mov ax, 0feedh + mov bx, 0faceh +%endif + push di + push si + push bp + push bx + push dx + push cx + push ax + pushf + + ; Convert ss:sp to real mode address. + BS3_EXTERN_CMN Bs3SelProtFar32ToFlat32 + mov ax, sp + push ss + push 0 + push ax + call Bs3SelProtFar32ToFlat32 + add sp, 6 + + mov [g_ResumeSp], ax + shl dx, 12 + mov [g_ResumeSs], dx + + ; Setup resume vector. + mov bx, BS3_SEL_R0_SS16 + mov es, bx + mov word [es:467h], .resume + mov word [es:467h+2], BS3_SEL_TEXT16 + + mov al, 0fh | 80h + out 70h, al ; set register index + in al, 80h + mov al, 0ah ; shutdown action command - no EOI, no 287 reset. + out 71h, al ; set cmos[f] = al - invoke testResume as early as possible. + in al, 71h ; flush + + %if 0 ; for testing in VM + CPU 386 + mov ax, BS3_SEL_R0_DS16 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + mov eax, cr0 + and ax, ~X86_CR0_PE + mov cr0, eax + jmp BS3_SEL_TEXT16:.resume + %endif + + ; Port A reset. (FYI: tripple fault does not do the trick) + in al, 92h + or al, 1 + out 92h, al + in al, 80h ; flush + mov cx, 0ffffh +.reset_delay: + loop .reset_delay + + ; Keyboard controller reset. + call Bs3KbdWait + push 0 ; zero data (whatever. + push 0fh ; KBD_CCMD_RESET + call Bs3KbdWrite +.forever: + jmp .forever + + ; This is the resume point. We should be in real mode now, at least in theory. +.resume: + mov ax, BS3_SEL_DATA16 + mov ds, ax + mov es, ax + mov ax, [g_ResumeSp] + mov ss, [g_ResumeSs] + mov sp, ax + + popf + pop ax + pop cx + pop dx + pop bx + pop bp + pop si + pop di + %ifdef BS3_STRICT + cmp ax, 0feedh + jne .bad_286_rm_switch + cmp bx, 0faceh + jne .bad_286_rm_switch + %endif + jmp .enter_mode + + %ifdef BS3_STRICT +.bad_286_rm_switch: + mov ax, 0e00h + 'Q' + mov bx, 0ff00h + int 10h + jmp .bad_286_rm_switch + %endif + + CPU 386 + %elif TMPL_BITS != 16 + ; + ; Must be in 16-bit segment when calling Bs3SwitchTo16Bit. + ; + jmp .sixteen_bit_segment wrt FLAT +BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .sixteen_bit_segment + + extern BS3_CMN_NM(Bs3SwitchTo16Bit) + call BS3_CMN_NM(Bs3SwitchTo16Bit) + BS3_SET_BITS 16 + %endif + ; + ; Before exiting to real mode we must load sensible selectors into the + ; segment registers so the hidden parts (which doesn't get reloaded in + ; real mode) are real mode compatible. + ; + ; ASSUMES BS3_SEL_R0_SS16 and BS3_SEL_R0_CS16 are both maxed out and + ; has no funny bits set! + ; +.is_386_or_better: +;; @todo Testcase: Experiment leaving weird stuff in the hidden segment registers. + mov ax, BS3_SEL_R0_DS16 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + ; + ; Exit to real mode. + ; + mov eax, cr0 + and eax, X86_CR0_NO_PE_NO_PG + mov cr0, eax + jmp CGROUP16:.reload_cs +.reload_cs: + + ; + ; Convert the stack (now 16-bit prot) to real mode. + ; + mov ax, BS3_SEL_SYSTEM16 + mov ds, ax + mov bx, ss + and bx, X86_SEL_MASK ; ASSUMES GDT stack selector + mov al, [bx + 4 + Bs3Gdt] + mov ah, [bx + 7 + Bs3Gdt] + add sp, [bx + 2 + Bs3Gdt] ; ASSUMES not expand down segment. + adc ax, 0 + %ifdef BS3_STRICT + test ax, 0fff0h + jz .stack_conv_ok + int3 +.stack_conv_ok: + %endif + shl ax, 12 + mov ss, ax + %if TMPL_BITS != 16 + and esp, 0ffffh + %endif + + %if BS3_MODE_IS_64BIT_SYS(TMPL_MODE) + ; + ; Clear the long mode enable bit. + ; + mov ecx, MSR_K6_EFER + rdmsr + and eax, ~MSR_K6_EFER_LME + wrmsr + %endif + + ; + ; Call routine for doing mode specific setups. + ; +.enter_mode: + extern NAME(Bs3EnteredMode_rm) + call NAME(Bs3EnteredMode_rm) + + %if TMPL_MODE == BS3_MODE_PE16 + pop ax + test ax, ax + jz .do_386_epilogue + popf + pop bx + pop ax + ret + %endif +.do_386_epilogue: + %if BS3_MODE_IS_64BIT_SYS(TMPL_MODE) + pop ecx +TONLY64 pop eax + pop edx +TONLY64 pop eax + %endif + popfd +TONLY64 pop eax + pop ebx +TONLY64 pop eax + pop eax +TONLY64 add sp, 4 + retn (TMPL_BITS - 16) / 8 + + %if TMPL_BITS != 16 +TMPL_BEGIN_TEXT + %endif +%endif +BS3_PROC_END_MODE Bs3SwitchToRM + + +%if TMPL_BITS == 16 +;; +; Custom far stub. +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_MODE Bs3SwitchToRM, BS3_PBC_FAR + inc bp + push bp + mov bp, sp + + ; Call the real thing. + call TMPL_NM(Bs3SwitchToRM) + + %if !BS3_MODE_IS_RM_OR_V86(TMPL_MODE) + ; Jmp to common code for the tedious conversion. + BS3_EXTERN_CMN Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn + jmp Bs3SwitchHlpConvProtModeRetfPopBpDecBpAndReturn + %else + pop bp + dec bp + retf + %endif +BS3_PROC_END_MODE Bs3SwitchToRM + +%else +;; +; Safe far return to non-BS3TEXT16 code. +BS3_EXTERN_CMN Bs3SelFlatCodeToRealMode +BS3_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_PROC_BEGIN_MODE Bs3SwitchToRM_Safe, BS3_PBC_NEAR + %if TMPL_BITS == 64 + push xAX + push xCX + sub xSP, 20h + + mov xCX, [xSP + xCB*2 + 20h] + call Bs3SelFlatCodeToRealMode ; well behaved assembly function, only clobbers ecx + mov [xSP + xCB*2 + 20h + 4], eax + + add xSP, 20h + pop xCX + pop xAX + add xSP, 4 + %else + xchg eax, [xSP] + push xAX + call Bs3SelFlatCodeToRealMode ; well behaved assembly function, only clobbers eax + add xSP, 4 + xchg [xSP], eax + %endif + call TMPL_NM(Bs3SwitchToRM) + BS3_SET_BITS 16 + retf +BS3_PROC_END_MODE Bs3SwitchToRM_Safe +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModes.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModes.c new file mode 100644 index 00000000..a7adf446 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModes.c @@ -0,0 +1,380 @@ +/* $Id: bs3-mode-TestDoModes.c $ */ +/** @file + * BS3Kit - Bs3TestDoModes + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#if TMPL_MODE == BS3_MODE_RM +# define BS3_USE_RM_TEXT_SEG 1 /* Real mode version in RMTEXT16 segment to save space. */ +# include "bs3kit-template-header.h" +# include "bs3-cmn-test.h" +#else +# include "bs3kit-template-header.h" +# include "bs3-cmn-test.h" +#endif +#include "bs3-mode-TestDoModes.h" + + + +/** + * Warns about CPU modes that must be skipped. + * + * It will try not warn about modes for which there are no tests. + * + * @param paEntries The mode test entries. + * @param cEntries The number of tests. + * @param bCpuType The CPU type byte (see #BS3CPU_TYPE_MASK). + * @param fHavePae Whether the CPU has PAE. + * @param fHaveLongMode Whether the CPU does long mode. + */ +static void bs3TestWarnAboutSkippedModes(PCBS3TESTMODEENTRY paEntries, unsigned cEntries, + uint8_t bCpuType, bool fHavePae, bool fHaveLongMode) +{ + bool fComplained286 = false; + bool fComplained386 = false; + bool fComplainedPAE = false; + bool fComplainedAMD64 = false; + unsigned i; + + /* + * Complaint run. + */ + for (i = 0; i < cEntries; i++) + { + if ( !fComplained286 + && paEntries[i].pfnDoPE16) + { + if (bCpuType < BS3CPU_80286) + { + Bs3Printf("Only executing real-mode tests as no 80286+ CPU was detected.\n"); + break; + } + fComplained286 = true; + } + + if ( !fComplained386 + && ( paEntries[i].pfnDoPE16_32 + || paEntries[i].pfnDoPE16_V86 + || paEntries[i].pfnDoPE32 + || paEntries[i].pfnDoPE32_16 + || paEntries[i].pfnDoPEV86 + || paEntries[i].pfnDoPP16 + || paEntries[i].pfnDoPP16_32 + || paEntries[i].pfnDoPP16_V86 + || paEntries[i].pfnDoPP32 + || paEntries[i].pfnDoPP32_16 + || paEntries[i].pfnDoPPV86) ) + { + if (bCpuType < BS3CPU_80386) + { + Bs3Printf("80286 CPU: Only executing 16-bit protected and real mode tests.\n"); + break; + } + fComplained386 = true; + } + + if ( !fComplainedPAE + && ( paEntries[i].pfnDoPAE16 + || paEntries[i].pfnDoPAE16_32 + || paEntries[i].pfnDoPAE16_V86 + || paEntries[i].pfnDoPAE32 + || paEntries[i].pfnDoPAE32_16 + || paEntries[i].pfnDoPAEV86) ) + { + if (!fHavePae) + { + Bs3Printf("PAE and long mode tests will be skipped.\n"); + break; + } + fComplainedPAE = true; + } + + if ( !fComplainedAMD64 + && ( paEntries[i].pfnDoLM16 + || paEntries[i].pfnDoLM32 + || paEntries[i].pfnDoLM64) ) + { + if (!fHaveLongMode) + { + Bs3Printf("Long mode tests will be skipped.\n"); + break; + } + fComplainedAMD64 = true; + } + } +} + +#undef Bs3TestDoModes +BS3_MODE_DEF(void, Bs3TestDoModes,(PCBS3TESTMODEENTRY paEntries, size_t cEntries)) +{ + bool const fVerbose = true; + bool const fDoV86Modes = true; + bool const fDoWeirdV86Modes = true; + uint16_t const uCpuDetected = g_uBs3CpuDetected; + uint8_t const bCpuType = uCpuDetected & BS3CPU_TYPE_MASK; + bool const fHavePae = RT_BOOL(uCpuDetected & BS3CPU_F_PAE); + bool const fHaveLongMode = RT_BOOL(uCpuDetected & BS3CPU_F_LONG_MODE); + unsigned i; + +#if 1 /* debug. */ + Bs3Printf("Bs3TestDoModes: uCpuDetected=%#x fHavePae=%d fHaveLongMode=%d\n", uCpuDetected, fHavePae, fHaveLongMode); +#endif + bs3TestWarnAboutSkippedModes(paEntries, cEntries, bCpuType, fHavePae, fHaveLongMode); + + /* + * The real run. + */ + for (i = 0; i < cEntries; i++) + { + const char *pszFmtStr = "Error #%u (%#x) in %s!\n"; + bool fSkipped = true; + uint8_t bErrNo; + + if (paEntries[i].pszSubTest != NULL) + Bs3TestSub(paEntries[i].pszSubTest); + +#define PRE_DO_CALL(a_szModeName) do { if (fVerbose) Bs3TestPrintf("...%s\n", a_szModeName); } while (0) +#define CHECK_RESULT(a_szModeName) \ + do { \ + if (bErrNo != BS3TESTDOMODE_SKIPPED) \ + { \ + /*Bs3Printf("bErrNo=%#x %s\n", bErrNo, a_szModeName);*/ \ + fSkipped = false; \ + if (bErrNo != 0) \ + Bs3TestFailedF(pszFmtStr, bErrNo, bErrNo, a_szModeName); \ + } \ + } while (0) + + if (paEntries[i].pfnDoRM) + { + PRE_DO_CALL(g_szBs3ModeName_rm); + bErrNo = TMPL_NM(Bs3TestCallDoerInRM)(CONV_TO_RM_FAR16(paEntries[i].pfnDoRM)); + CHECK_RESULT(g_szBs3ModeName_rm); + } + + if (bCpuType < BS3CPU_80286) + { + if (fSkipped) + Bs3TestSkipped(NULL); + continue; + } + + /* + * Unpaged prot mode. + */ + if (paEntries[i].pfnDoPE16) + { + PRE_DO_CALL(g_szBs3ModeName_pe16); + bErrNo = TMPL_NM(Bs3TestCallDoerInPE16)(CONV_TO_PROT_FAR16(paEntries[i].pfnDoPE16)); + CHECK_RESULT(g_szBs3ModeName_pe16); + } + if (bCpuType < BS3CPU_80386) + { + if (fSkipped) + Bs3TestSkipped(NULL); + continue; + } + + if (paEntries[i].pfnDoPE16_32) + { + PRE_DO_CALL(g_szBs3ModeName_pe16_32); + bErrNo = TMPL_NM(Bs3TestCallDoerInPE16_32)(CONV_TO_FLAT(paEntries[i].pfnDoPE16_32), BS3_MODE_PE16_32); + CHECK_RESULT(g_szBs3ModeName_pe16_32); + } + + if (paEntries[i].pfnDoPE16_V86 && fDoWeirdV86Modes) + { + PRE_DO_CALL(g_szBs3ModeName_pe16_v86); + bErrNo = TMPL_NM(Bs3TestCallDoerInPE16_V86)(CONV_TO_RM_FAR16(paEntries[i].pfnDoPE16_V86)); + CHECK_RESULT(g_szBs3ModeName_pe16_v86); + } + + if (paEntries[i].pfnDoPE32) + { + PRE_DO_CALL(g_szBs3ModeName_pe32); + bErrNo = TMPL_NM(Bs3TestCallDoerInPE32)(CONV_TO_FLAT(paEntries[i].pfnDoPE32), BS3_MODE_PE32); + CHECK_RESULT(g_szBs3ModeName_pe32); + } + + if (paEntries[i].pfnDoPE32_16) + { + PRE_DO_CALL(g_szBs3ModeName_pe32_16); + bErrNo = TMPL_NM(Bs3TestCallDoerInPE32_16)(CONV_TO_PROT_FAR16(paEntries[i].pfnDoPE32_16)); + CHECK_RESULT(g_szBs3ModeName_pe32_16); + } + + if (paEntries[i].pfnDoPEV86 && fDoV86Modes) + { + PRE_DO_CALL(g_szBs3ModeName_pev86); + bErrNo = TMPL_NM(Bs3TestCallDoerInPEV86)(CONV_TO_RM_FAR16(paEntries[i].pfnDoPEV86)); + CHECK_RESULT(g_szBs3ModeName_pev86); + } + + /* + * Paged protected mode. + */ + if (paEntries[i].pfnDoPP16) + { + PRE_DO_CALL(g_szBs3ModeName_pp16); + bErrNo = TMPL_NM(Bs3TestCallDoerInPP16)(CONV_TO_PROT_FAR16(paEntries[i].pfnDoPP16)); + CHECK_RESULT(g_szBs3ModeName_pp16); + } + + if (paEntries[i].pfnDoPP16_32) + { + PRE_DO_CALL(g_szBs3ModeName_pp16_32); + bErrNo = TMPL_NM(Bs3TestCallDoerInPP16_32)(CONV_TO_FLAT(paEntries[i].pfnDoPP16_32), BS3_MODE_PP16_32); + CHECK_RESULT(g_szBs3ModeName_pp16_32); + } + + if (paEntries[i].pfnDoPP16_V86 && fDoWeirdV86Modes) + { + PRE_DO_CALL(g_szBs3ModeName_pp16_v86); + bErrNo = TMPL_NM(Bs3TestCallDoerInPP16_V86)(CONV_TO_RM_FAR16(paEntries[i].pfnDoPP16_V86)); + CHECK_RESULT(g_szBs3ModeName_pp16_v86); + } + + if (paEntries[i].pfnDoPP32) + { + PRE_DO_CALL(g_szBs3ModeName_pp32); + bErrNo = TMPL_NM(Bs3TestCallDoerInPP32)(CONV_TO_FLAT(paEntries[i].pfnDoPP32), BS3_MODE_PP32); + CHECK_RESULT(g_szBs3ModeName_pp32); + } + + if (paEntries[i].pfnDoPP32_16) + { + PRE_DO_CALL(g_szBs3ModeName_pp32_16); + bErrNo = TMPL_NM(Bs3TestCallDoerInPP32_16)(CONV_TO_PROT_FAR16(paEntries[i].pfnDoPP32_16)); + CHECK_RESULT(g_szBs3ModeName_pp32_16); + } + + if (paEntries[i].pfnDoPPV86 && fDoV86Modes) + { + PRE_DO_CALL(g_szBs3ModeName_ppv86); + bErrNo = TMPL_NM(Bs3TestCallDoerInPPV86)(CONV_TO_RM_FAR16(paEntries[i].pfnDoPPV86)); + CHECK_RESULT(g_szBs3ModeName_ppv86); + } + + /* + * Protected mode with PAE paging. + */ + if (!fHavePae) + { + if (fSkipped) + Bs3TestSkipped(NULL); + continue; + } + + if (paEntries[i].pfnDoPAE16) + { + PRE_DO_CALL(g_szBs3ModeName_pae16); + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE16)(CONV_TO_PROT_FAR16(paEntries[i].pfnDoPAE16)); + CHECK_RESULT(g_szBs3ModeName_pae16); + } + + if (paEntries[i].pfnDoPAE16_32) + { + PRE_DO_CALL(g_szBs3ModeName_pae16_32); + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE16_32)(CONV_TO_FLAT(paEntries[i].pfnDoPAE16_32), BS3_MODE_PAE16_32); + CHECK_RESULT(g_szBs3ModeName_pae16_32); + } + + if (paEntries[i].pfnDoPAE16_V86 && fDoWeirdV86Modes) + { + PRE_DO_CALL(g_szBs3ModeName_pae16_v86); + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE16_V86)(CONV_TO_RM_FAR16(paEntries[i].pfnDoPAE16_V86)); + CHECK_RESULT(g_szBs3ModeName_pae16_v86); + } + + if (paEntries[i].pfnDoPAE32) + { + PRE_DO_CALL(g_szBs3ModeName_pae32); + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE32)(CONV_TO_FLAT(paEntries[i].pfnDoPAE32), BS3_MODE_PAE32); + CHECK_RESULT(g_szBs3ModeName_pae32); + } + + if (paEntries[i].pfnDoPAE32_16) + { + PRE_DO_CALL(g_szBs3ModeName_pae32_16); + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE32_16)(CONV_TO_PROT_FAR16(paEntries[i].pfnDoPAE32_16)); + CHECK_RESULT(g_szBs3ModeName_pae32_16); + } + + if (paEntries[i].pfnDoPAEV86 && fDoV86Modes) + { + PRE_DO_CALL(g_szBs3ModeName_paev86); + bErrNo = TMPL_NM(Bs3TestCallDoerInPAEV86)(CONV_TO_RM_FAR16(paEntries[i].pfnDoPAEV86)); + CHECK_RESULT(g_szBs3ModeName_paev86); + } + + /* + * Long mode. + */ + if (!fHaveLongMode) + { + if (fSkipped) + Bs3TestSkipped(NULL); + continue; + } + + if (paEntries[i].pfnDoLM16) + { + PRE_DO_CALL(g_szBs3ModeName_lm16); + bErrNo = TMPL_NM(Bs3TestCallDoerInLM16)(CONV_TO_PROT_FAR16(paEntries[i].pfnDoLM16)); + CHECK_RESULT(g_szBs3ModeName_lm16); + } + + if (paEntries[i].pfnDoLM32) + { + PRE_DO_CALL(g_szBs3ModeName_lm32); + bErrNo = TMPL_NM(Bs3TestCallDoerInLM32)(CONV_TO_FLAT(paEntries[i].pfnDoLM32)); + CHECK_RESULT(g_szBs3ModeName_lm32); + } + + if (paEntries[i].pfnDoLM64) + { + PRE_DO_CALL(g_szBs3ModeName_lm64); + bErrNo = TMPL_NM(Bs3TestCallDoerInLM64)(CONV_TO_FLAT(paEntries[i].pfnDoLM64), BS3_MODE_LM64); + CHECK_RESULT(g_szBs3ModeName_lm64); + } + + if (fSkipped) + Bs3TestSkipped("skipped\n"); + } + Bs3TestSubDone(); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModes.h b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModes.h new file mode 100644 index 00000000..26c93009 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModes.h @@ -0,0 +1,99 @@ +/* $Id: bs3-mode-TestDoModes.h $ */ +/** @file + * BS3Kit - Common header for the Bs3TestDoModes family. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#ifndef BS3KIT_INCLUDED_bs3_mode_TestDoModes_h +#define BS3KIT_INCLUDED_bs3_mode_TestDoModes_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include "bs3kit.h" + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +/** @def CONV_TO_FLAT + * Get flat address. In 16-bit the parameter is a real mode far address, while + * in 32-bit and 64-bit modes it is already flat. + */ +/** @def CONV_TO_PROT_FAR16 + * Get a 32-bit value that makes a protected mode far 16:16 address. + */ +/** @def CONV_TO_RM_FAR16 + * Get a 32-bit value that makes a real mode far 16:16 address. In 16-bit mode + * this is already what we've got, except must be converted to uint32_t. + */ +#if ARCH_BITS == 16 +# define CONV_TO_FLAT(a_fpfn) (((uint32_t)BS3_FP_SEG(a_fpfn) << 4) + BS3_FP_OFF(a_fpfn)) +# define CONV_TO_PROT_FAR16(a_fpfn) RT_MAKE_U32(BS3_FP_OFF(a_fpfn), Bs3SelRealModeCodeToProtMode(BS3_FP_SEG(a_fpfn))) +# define CONV_TO_RM_FAR16(a_fpfn) RT_MAKE_U32(BS3_FP_OFF(a_fpfn), BS3_FP_SEG(a_fpfn)) +#else +# define CONV_TO_FLAT(a_fpfn) ((uint32_t)(uintptr_t)(a_fpfn)) +# define CONV_TO_PROT_FAR16(a_fpfn) Bs3SelFlatCodeToProtFar16((uint32_t)(uintptr_t)(a_fpfn)) +# define CONV_TO_RM_FAR16(a_fpfn) Bs3SelFlatCodeToRealMode( (uint32_t)(uintptr_t)(a_fpfn)) +#endif + + +/********************************************************************************************************************************* +* Assembly Symbols * +*********************************************************************************************************************************/ +/* These are in the same code segment as the main API, so no FAR necessary. */ +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInRM)(uint32_t uCallbackFarPtr); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInPE16)(uint32_t uCallbackFarPtr); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInPE16_32)(uint32_t uFlatAddrCallback, uint8_t bMode); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInPE16_V86)(uint32_t uCallbackFarPtr); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInPE32)(uint32_t uFlatAddrCallback, uint8_t bMode); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInPE32_16)(uint32_t uCallbackFarPtr); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInPEV86)(uint32_t uCallbackFarPtr); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInPP16)(uint32_t uCallbackFarPtr); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInPP16_32)(uint32_t uFlatAddrCallback, uint8_t bMode); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInPP16_V86)(uint32_t uCallbackFarPtr); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInPP32)(uint32_t uFlatAddrCallback, uint8_t bMode); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInPP32_16)(uint32_t uCallbackFarPtr); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInPPV86)(uint32_t uCallbackFarPtr); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInPAE16)(uint32_t uCallbackFarPtr); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInPAE16_32)(uint32_t uFlatAddrCallback, uint8_t bMode); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInPAE16_V86)(uint32_t uCallbackFarPtr); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInPAE32)(uint32_t uFlatAddrCallback, uint8_t bMode); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInPAE32_16)(uint32_t uCallbackFarPtr); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInPAEV86)(uint32_t uCallbackFarPtr); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInLM16)(uint32_t uCallbackFarPtr); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInLM32)(uint32_t uFlatAddrCallback); +BS3_DECL_NEAR(uint8_t) TMPL_NM(Bs3TestCallDoerInLM64)(uint32_t uFlatAddrCallback, uint8_t bMode); + +#endif /* !BS3KIT_INCLUDED_bs3_mode_TestDoModes_h */ + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesByMax.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesByMax.c new file mode 100644 index 00000000..3bb86b9d --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesByMax.c @@ -0,0 +1,380 @@ +/* $Id: bs3-mode-TestDoModesByMax.c $ */ +/** @file + * BS3Kit - Bs3TestDoModesByMax + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#if TMPL_MODE == BS3_MODE_RM +# define BS3_USE_RM_TEXT_SEG 1 /* Real mode version in RMTEXT16 segment to save space. */ +# include "bs3kit-template-header.h" +# include "bs3-cmn-test.h" +#else +# include "bs3kit-template-header.h" +# include "bs3-cmn-test.h" +#endif +#include "bs3-mode-TestDoModes.h" + + + +/** + * Warns about CPU modes that must be skipped. + * + * It will try not warn about modes for which there are no tests. + * + * @param paEntries The mode test entries. + * @param cEntries The number of tests. + * @param bCpuType The CPU type byte (see #BS3CPU_TYPE_MASK). + * @param fHavePae Whether the CPU has PAE. + * @param fHaveLongMode Whether the CPU does long mode. + */ +static void bs3TestWarnAboutSkippedModes(PCBS3TESTMODEBYMAXENTRY paEntries, unsigned cEntries, + uint8_t bCpuType, bool fHavePae, bool fHaveLongMode) +{ + bool fComplained286 = false; + bool fComplained386 = false; + bool fComplainedPAE = false; + bool fComplainedAMD64 = false; + unsigned i; + + /* + * Complaint run. + */ + for (i = 0; i < cEntries; i++) + { + if ( !fComplained286 + && paEntries[i].pfnDoPE16) + { + if (bCpuType < BS3CPU_80286) + { + Bs3Printf("Only executing real-mode tests as no 80286+ CPU was detected.\n"); + break; + } + fComplained286 = true; + } + + if ( !fComplained386 + && ( paEntries[i].fDoPE16_32 + || paEntries[i].fDoPE16_V86 + || paEntries[i].fDoPE32 + || paEntries[i].fDoPE32_16 + || paEntries[i].fDoPEV86 + || paEntries[i].fDoPP16 + || paEntries[i].fDoPP16_32 + || paEntries[i].fDoPP16_V86 + || paEntries[i].fDoPP32 + || paEntries[i].fDoPP32_16 + || paEntries[i].fDoPPV86) ) + { + if (bCpuType < BS3CPU_80386) + { + Bs3Printf("80286 CPU: Only executing 16-bit protected and real mode tests.\n"); + break; + } + fComplained386 = true; + } + + if ( !fComplainedPAE + && ( paEntries[i].fDoPAE16 + || paEntries[i].fDoPAE16_32 + || paEntries[i].fDoPAE16_V86 + || paEntries[i].fDoPAE32 + || paEntries[i].fDoPAE32_16 + || paEntries[i].fDoPAEV86) ) + { + if (!fHavePae) + { + Bs3Printf("PAE and long mode tests will be skipped.\n"); + break; + } + fComplainedPAE = true; + } + + if ( !fComplainedAMD64 + && ( paEntries[i].fDoLM16 + || paEntries[i].fDoLM32 + || paEntries[i].fDoLM64) ) + { + if (!fHaveLongMode) + { + Bs3Printf("Long mode tests will be skipped.\n"); + break; + } + fComplainedAMD64 = true; + } + } +} + +#undef Bs3TestDoModesByMax +BS3_MODE_DEF(void, Bs3TestDoModesByMax,(PCBS3TESTMODEBYMAXENTRY paEntries, size_t cEntries)) +{ + bool const fVerbose = true; + bool const fDoV86Modes = true; + bool const fDoWeirdV86Modes = true; + uint16_t const uCpuDetected = g_uBs3CpuDetected; + uint8_t const bCpuType = uCpuDetected & BS3CPU_TYPE_MASK; + bool const fHavePae = RT_BOOL(uCpuDetected & BS3CPU_F_PAE); + bool const fHaveLongMode = RT_BOOL(uCpuDetected & BS3CPU_F_LONG_MODE); + unsigned i; + +#if 1 /* debug. */ + Bs3Printf("Bs3TestDoModes: uCpuDetected=%#x fHavePae=%d fHaveLongMode=%d\n", uCpuDetected, fHavePae, fHaveLongMode); +#endif + bs3TestWarnAboutSkippedModes(paEntries, cEntries, bCpuType, fHavePae, fHaveLongMode); + + /* + * The real run. + */ + for (i = 0; i < cEntries; i++) + { + const char *pszFmtStr = "Error #%u (%#x) in %s!\n"; + bool fSkipped = true; + uint8_t bErrNo; + + if (paEntries[i].pszSubTest != NULL) + Bs3TestSub(paEntries[i].pszSubTest); + +#define PRE_DO_CALL(a_szModeName) do { if (fVerbose) Bs3TestPrintf("...%s\n", a_szModeName); } while (0) +#define CHECK_RESULT(a_szModeName) \ + do { \ + if (bErrNo != BS3TESTDOMODE_SKIPPED) \ + { \ + /*Bs3Printf("bErrNo=%#x %s\n", bErrNo, a_szModeName);*/ \ + fSkipped = false; \ + if (bErrNo != 0) \ + Bs3TestFailedF(pszFmtStr, bErrNo, bErrNo, a_szModeName); \ + } \ + } while (0) + + if (paEntries[i].fDoRM) + { + PRE_DO_CALL(g_szBs3ModeName_rm); + bErrNo = TMPL_NM(Bs3TestCallDoerInRM)(CONV_TO_RM_FAR16(paEntries[i].pfnDoRM)); + CHECK_RESULT(g_szBs3ModeName_rm); + } + + if (bCpuType < BS3CPU_80286) + { + if (fSkipped) + Bs3TestSkipped(NULL); + continue; + } + + /* + * Unpaged prot mode. + */ + if (paEntries[i].fDoPE16) + { + PRE_DO_CALL(g_szBs3ModeName_pe16); + bErrNo = TMPL_NM(Bs3TestCallDoerInPE16)(CONV_TO_PROT_FAR16(paEntries[i].pfnDoPE16)); + CHECK_RESULT(g_szBs3ModeName_pe16); + } + if (bCpuType < BS3CPU_80386) + { + if (fSkipped) + Bs3TestSkipped(NULL); + continue; + } + + if (paEntries[i].fDoPE16_32) + { + PRE_DO_CALL(g_szBs3ModeName_pe16_32); + bErrNo = TMPL_NM(Bs3TestCallDoerInPE16_32)(CONV_TO_FLAT(paEntries[i].pfnDoPE16_32), BS3_MODE_PE16_32); + CHECK_RESULT(g_szBs3ModeName_pe16_32); + } + + if (paEntries[i].fDoPE16_V86 && fDoWeirdV86Modes) + { + PRE_DO_CALL(g_szBs3ModeName_pe16_v86); + bErrNo = TMPL_NM(Bs3TestCallDoerInPE16_32)(CONV_TO_FLAT(paEntries[i].pfnDoPE16_32), BS3_MODE_PE16_V86); + CHECK_RESULT(g_szBs3ModeName_pe16_v86); + } + + if (paEntries[i].fDoPE32) + { + PRE_DO_CALL(g_szBs3ModeName_pe32); + bErrNo = TMPL_NM(Bs3TestCallDoerInPE32)(CONV_TO_FLAT(paEntries[i].pfnDoPE32), BS3_MODE_PE32); + CHECK_RESULT(g_szBs3ModeName_pe32); + } + + if (paEntries[i].fDoPE32_16) + { + PRE_DO_CALL(g_szBs3ModeName_pe32_16); + bErrNo = TMPL_NM(Bs3TestCallDoerInPE32)(CONV_TO_FLAT(paEntries[i].pfnDoPE32), BS3_MODE_PE32_16); + CHECK_RESULT(g_szBs3ModeName_pe32_16); + } + + if (paEntries[i].fDoPEV86 && fDoV86Modes) + { + PRE_DO_CALL(g_szBs3ModeName_pev86); + bErrNo = TMPL_NM(Bs3TestCallDoerInPE32)(CONV_TO_FLAT(paEntries[i].pfnDoPE32), BS3_MODE_PEV86); + CHECK_RESULT(g_szBs3ModeName_pev86); + } + + /* + * Paged protected mode. + */ + if (paEntries[i].fDoPP16) + { + PRE_DO_CALL(g_szBs3ModeName_pp16); + bErrNo = TMPL_NM(Bs3TestCallDoerInPP16_32)(CONV_TO_FLAT(paEntries[i].pfnDoPP16_32), BS3_MODE_PP16); + CHECK_RESULT(g_szBs3ModeName_pp16); + } + + if (paEntries[i].fDoPP16_32) + { + PRE_DO_CALL(g_szBs3ModeName_pp16_32); + bErrNo = TMPL_NM(Bs3TestCallDoerInPP16_32)(CONV_TO_FLAT(paEntries[i].pfnDoPP16_32), BS3_MODE_PP16_32); + CHECK_RESULT(g_szBs3ModeName_pp16_32); + } + + if (paEntries[i].fDoPP16_V86 && fDoWeirdV86Modes) + { + PRE_DO_CALL(g_szBs3ModeName_pp16_v86); + bErrNo = TMPL_NM(Bs3TestCallDoerInPP16_32)(CONV_TO_FLAT(paEntries[i].pfnDoPP16_32), BS3_MODE_PP16_V86); + CHECK_RESULT(g_szBs3ModeName_pp16_v86); + } + + if (paEntries[i].fDoPP32) + { + PRE_DO_CALL(g_szBs3ModeName_pp32); + bErrNo = TMPL_NM(Bs3TestCallDoerInPP32)(CONV_TO_FLAT(paEntries[i].pfnDoPP32), BS3_MODE_PP32); + CHECK_RESULT(g_szBs3ModeName_pp32); + } + + if (paEntries[i].fDoPP32_16) + { + PRE_DO_CALL(g_szBs3ModeName_pp32_16); + bErrNo = TMPL_NM(Bs3TestCallDoerInPP32)(CONV_TO_FLAT(paEntries[i].pfnDoPP32), BS3_MODE_PP32_16); + CHECK_RESULT(g_szBs3ModeName_pp32_16); + } + + if (paEntries[i].fDoPPV86 && fDoV86Modes) + { + PRE_DO_CALL(g_szBs3ModeName_ppv86); + bErrNo = TMPL_NM(Bs3TestCallDoerInPP32)(CONV_TO_FLAT(paEntries[i].pfnDoPP32), BS3_MODE_PPV86); + CHECK_RESULT(g_szBs3ModeName_ppv86); + } + + /* + * Protected mode with PAE paging. + */ + if (!fHavePae) + { + if (fSkipped) + Bs3TestSkipped(NULL); + continue; + } + + if (paEntries[i].fDoPAE16) + { + PRE_DO_CALL(g_szBs3ModeName_pae16); + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE16_32)(CONV_TO_FLAT(paEntries[i].pfnDoPAE16_32), BS3_MODE_PAE16); + CHECK_RESULT(g_szBs3ModeName_pae16); + } + + if (paEntries[i].fDoPAE16_32) + { + PRE_DO_CALL(g_szBs3ModeName_pae16_32); + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE16_32)(CONV_TO_FLAT(paEntries[i].pfnDoPAE16_32), BS3_MODE_PAE16_32); + CHECK_RESULT(g_szBs3ModeName_pae16_32); + } + + if (paEntries[i].fDoPAE16_V86 && fDoWeirdV86Modes) + { + PRE_DO_CALL(g_szBs3ModeName_pae16_v86); + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE16_32)(CONV_TO_FLAT(paEntries[i].pfnDoPAE16_32), BS3_MODE_PAE16_V86); + CHECK_RESULT(g_szBs3ModeName_pae16_v86); + } + + if (paEntries[i].fDoPAE32) + { + PRE_DO_CALL(g_szBs3ModeName_pae32); + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE32)(CONV_TO_FLAT(paEntries[i].pfnDoPAE32), BS3_MODE_PAE32); + CHECK_RESULT(g_szBs3ModeName_pae32); + } + + if (paEntries[i].fDoPAE32_16) + { + PRE_DO_CALL(g_szBs3ModeName_pae32_16); + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE32)(CONV_TO_FLAT(paEntries[i].pfnDoPAE32), BS3_MODE_PAE32_16); + CHECK_RESULT(g_szBs3ModeName_pae32_16); + } + + if (paEntries[i].fDoPAEV86 && fDoV86Modes) + { + PRE_DO_CALL(g_szBs3ModeName_paev86); + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE32)(CONV_TO_FLAT(paEntries[i].pfnDoPAE32), BS3_MODE_PAEV86); + CHECK_RESULT(g_szBs3ModeName_paev86); + } + + /* + * Long mode. + */ + if (!fHaveLongMode) + { + if (fSkipped) + Bs3TestSkipped(NULL); + continue; + } + + if (paEntries[i].fDoLM16) + { + PRE_DO_CALL(g_szBs3ModeName_lm16); + bErrNo = TMPL_NM(Bs3TestCallDoerInLM64)(CONV_TO_FLAT(paEntries[i].pfnDoLM64), BS3_MODE_LM16); + CHECK_RESULT(g_szBs3ModeName_lm16); + } + + if (paEntries[i].fDoLM32) + { + PRE_DO_CALL(g_szBs3ModeName_lm32); + bErrNo = TMPL_NM(Bs3TestCallDoerInLM64)(CONV_TO_FLAT(paEntries[i].pfnDoLM64), BS3_MODE_LM32); + CHECK_RESULT(g_szBs3ModeName_lm32); + } + + if (paEntries[i].fDoLM64) + { + PRE_DO_CALL(g_szBs3ModeName_lm64); + bErrNo = TMPL_NM(Bs3TestCallDoerInLM64)(CONV_TO_FLAT(paEntries[i].pfnDoLM64), BS3_MODE_LM64); + CHECK_RESULT(g_szBs3ModeName_lm64); + } + + if (fSkipped) + Bs3TestSkipped("skipped\n"); + } + Bs3TestSubDone(); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesByMaxStub.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesByMaxStub.asm new file mode 100644 index 00000000..a2f35324 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesByMaxStub.asm @@ -0,0 +1,63 @@ +; $Id: bs3-mode-TestDoModesByMaxStub.asm $ +;; @file +; BS3Kit - Bs3TestDoModesByMax near stub. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + +; +; Near stub for the API call (16-bit only). +; +%if TMPL_BITS == 16 + %if TMPL_MODE == BS3_MODE_RM +BS3_BEGIN_RMTEXT16 + %endif +BS3_BEGIN_TEXT16_NEARSTUBS +BS3_PROC_BEGIN_MODE Bs3TestDoModesByMax, BS3_PBC_NEAR + pop ax + push cs + push ax + %if TMPL_MODE == BS3_MODE_RM + extern TMPL_FAR_NM(Bs3TestDoModesByMax):wrt BS3GROUPRMTEXT16 + jmp far TMPL_FAR_NM(Bs3TestDoModesByMax) + %else + extern TMPL_FAR_NM(Bs3TestDoModesByMax):wrt CGROUP16 + jmp TMPL_NM(Bs3TestDoModesByMax) + %endif +BS3_PROC_END_MODE Bs3TestDoModesByMax +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesByOne.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesByOne.c new file mode 100644 index 00000000..7a057d5a --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesByOne.c @@ -0,0 +1,424 @@ +/* $Id: bs3-mode-TestDoModesByOne.c $ */ +/** @file + * BS3Kit - Bs3TestDoModesByOne + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#if TMPL_MODE == BS3_MODE_RM +# define BS3_USE_RM_TEXT_SEG 1 /* Real mode version in RMTEXT16 segment to save space. */ +# include "bs3kit-template-header.h" +# include "bs3-cmn-test.h" +#else +# include "bs3kit-template-header.h" +# include "bs3-cmn-test.h" +#endif +#include "bs3-mode-TestDoModes.h" + + +/********************************************************************************************************************************* +* Assembly Symbols * +*********************************************************************************************************************************/ +/* Assembly helpers for switching to the work bitcount and calling it. */ +BS3_DECL_FAR(uint8_t) Bs3TestCallDoerTo16_f16(uint8_t bMode); +BS3_DECL_FAR(uint8_t) Bs3TestCallDoerTo16_c32(uint8_t bMode); +BS3_DECL_FAR(uint8_t) Bs3TestCallDoerTo16_c64(uint8_t bMode); +BS3_DECL_FAR(uint8_t) Bs3TestCallDoerTo32_f16(uint8_t bMode); +BS3_DECL_FAR(uint8_t) Bs3TestCallDoerTo32_c32(uint8_t bMode); +BS3_DECL_FAR(uint8_t) Bs3TestCallDoerTo32_c64(uint8_t bMode); +BS3_DECL_FAR(uint8_t) Bs3TestCallDoerTo64_f16(uint8_t bMode); +BS3_DECL_FAR(uint8_t) Bs3TestCallDoerTo64_c32(uint8_t bMode); +BS3_DECL_FAR(uint8_t) Bs3TestCallDoerTo64_c64(uint8_t bMode); + + +/** The current worker function, picked up by our assembly helpers. */ +#ifndef DOXYGEN_RUNNING +# define g_pfnBs3TestDoModesByOneCurrent BS3_CMN_NM(g_pfnBs3TestDoModesByOneCurrent) +#endif +extern PFNBS3TESTDOMODE g_pfnBs3TestDoModesByOneCurrent; + +#include <iprt/asm-amd64-x86.h> + + +#undef Bs3TestDoModesByOne +BS3_MODE_DEF(void, Bs3TestDoModesByOne,(PCBS3TESTMODEBYONEENTRY paEntries, size_t cEntries, uint32_t fFlags)) +{ + bool const fVerbose = true; + bool const fDoV86Modes = true; + bool const fDoWeirdV86Modes = true; + uint16_t const uCpuDetected = g_uBs3CpuDetected; + uint8_t const bCpuType = uCpuDetected & BS3CPU_TYPE_MASK; + bool const fHavePae = RT_BOOL(uCpuDetected & BS3CPU_F_PAE); + bool const fHaveLongMode = RT_BOOL(uCpuDetected & BS3CPU_F_LONG_MODE); + unsigned i; + +#if 1 /* debug. */ + Bs3Printf("Bs3TestDoModesByOne: uCpuDetected=%#x fHavePae=%d fHaveLongMode=%d\n", uCpuDetected, fHavePae, fHaveLongMode); +#endif + + /* + * Inform about modes we won't test (if any). + */ + if (bCpuType < BS3CPU_80286) + Bs3Printf("Only executing real-mode tests as no 80286+ CPU was detected.\n"); + else if (bCpuType < BS3CPU_80386) + Bs3Printf("80286 CPU: Only executing 16-bit protected and real mode tests.\n"); + else if (!fHavePae) + Bs3Printf("PAE and long mode tests will be skipped.\n"); + else if (!fHaveLongMode) + Bs3Printf("Long mode tests will be skipped.\n"); +#if ARCH_BITS != 16 + Bs3Printf("Real-mode tests will be skipped.\n"); +#endif + + /* + * The real run. + */ + for (i = 0; i < cEntries; i++) + { + const char *pszFmtStr = "Error #%u (%#x) in %s!\n"; + bool fSkipped = true; + bool const fOnlyPaging = RT_BOOL((paEntries[i].fFlags | fFlags) & BS3TESTMODEBYONEENTRY_F_ONLY_PAGING); + bool const fMinimal = RT_BOOL((paEntries[i].fFlags | fFlags) & BS3TESTMODEBYONEENTRY_F_MINIMAL); + bool const fCurDoV86Modes = fDoV86Modes && !fMinimal; + bool const fCurDoWeirdV86Modes = fDoWeirdV86Modes && fCurDoV86Modes; + uint8_t bErrNo; + Bs3TestSub(paEntries[i].pszSubTest); + +#define PRE_DO_CALL(a_szModeName) do { if (fVerbose) Bs3TestPrintf("...%s\n", a_szModeName); } while (0) +#define CHECK_RESULT(a_szModeName) \ + do { \ + if (bErrNo != BS3TESTDOMODE_SKIPPED) \ + { \ + /*Bs3Printf("bErrNo=%#x %s\n", bErrNo, a_szModeName);*/ \ + fSkipped = false; \ + if (bErrNo != 0) \ + Bs3TestFailedF(pszFmtStr, bErrNo, bErrNo, a_szModeName); \ + } \ + } while (0) + + g_pfnBs3TestDoModesByOneCurrent = paEntries[i].pfnWorker; + +#if ARCH_BITS != 64 + +# if ARCH_BITS == 16 + if (!fOnlyPaging) + { + PRE_DO_CALL(g_szBs3ModeName_rm); + bErrNo = TMPL_NM(Bs3TestCallDoerInRM)(CONV_TO_RM_FAR16(paEntries[i].pfnWorker)); + CHECK_RESULT(g_szBs3ModeName_rm); + } +# else + if (!fOnlyPaging && (paEntries[i].fFlags | fFlags) & BS3TESTMODEBYONEENTRY_F_REAL_MODE_READY) + { + PRE_DO_CALL(g_szBs3ModeName_rm); + bErrNo = TMPL_NM(Bs3TestCallDoerInPE32)(CONV_TO_FLAT(paEntries[i].pfnWorker), BS3_MODE_RM); + CHECK_RESULT(g_szBs3ModeName_rm); + } +# endif + + if (bCpuType < BS3CPU_80286) + { + if (fSkipped) + Bs3TestSkipped(NULL); + continue; + } + + /* + * Unpaged prot mode. + */ + if (!fOnlyPaging && (!fMinimal || bCpuType < BS3CPU_80386)) + { + PRE_DO_CALL(g_szBs3ModeName_pe16); +# if ARCH_BITS == 16 + bErrNo = TMPL_NM(Bs3TestCallDoerInPE16)(CONV_TO_PROT_FAR16(paEntries[i].pfnWorker)); +# else + bErrNo = TMPL_NM(Bs3TestCallDoerInPE16)(CONV_TO_PROT_FAR16(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_f16))); +# endif + CHECK_RESULT(g_szBs3ModeName_pe16); + } + if (bCpuType < BS3CPU_80386) + { + if (fSkipped) + Bs3TestSkipped(NULL); + continue; + } + + if (!fOnlyPaging) + { + PRE_DO_CALL(g_szBs3ModeName_pe16_32); +# if ARCH_BITS == 32 + bErrNo = TMPL_NM(Bs3TestCallDoerInPE16_32)(CONV_TO_FLAT(paEntries[i].pfnWorker), BS3_MODE_PE16_32); +# else + bErrNo = TMPL_NM(Bs3TestCallDoerInPE16_32)(CONV_TO_FLAT(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_c32)), BS3_MODE_PE16_32); +# endif + CHECK_RESULT(g_szBs3ModeName_pe16_32); + } + + if (fCurDoWeirdV86Modes && !fOnlyPaging) + { + PRE_DO_CALL(g_szBs3ModeName_pe16_v86); +# if ARCH_BITS == 16 + bErrNo = TMPL_NM(Bs3TestCallDoerInPE16_V86)(CONV_TO_RM_FAR16(paEntries[i].pfnWorker)); +# else + bErrNo = TMPL_NM(Bs3TestCallDoerInPE16_V86)(CONV_TO_RM_FAR16(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_f16))); +# endif + CHECK_RESULT(g_szBs3ModeName_pe16_v86); + } + + if (!fOnlyPaging) + { + PRE_DO_CALL(g_szBs3ModeName_pe32); +# if ARCH_BITS == 32 + bErrNo = TMPL_NM(Bs3TestCallDoerInPE32)(CONV_TO_FLAT(paEntries[i].pfnWorker), BS3_MODE_PE32); +# else + bErrNo = TMPL_NM(Bs3TestCallDoerInPE32)(CONV_TO_FLAT(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_c32)), BS3_MODE_PE32); +# endif + CHECK_RESULT(g_szBs3ModeName_pe32); + } + + if (!fOnlyPaging && !fMinimal) + { + PRE_DO_CALL(g_szBs3ModeName_pe32_16); +# if ARCH_BITS == 16 + bErrNo = TMPL_NM(Bs3TestCallDoerInPE32_16)(CONV_TO_PROT_FAR16(paEntries[i].pfnWorker)); +# else + bErrNo = TMPL_NM(Bs3TestCallDoerInPE32_16)(CONV_TO_PROT_FAR16(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_f16))); +# endif + CHECK_RESULT(g_szBs3ModeName_pe32_16); + } + + if (fCurDoV86Modes && !fOnlyPaging) + { + PRE_DO_CALL(g_szBs3ModeName_pev86); +# if ARCH_BITS == 16 + bErrNo = TMPL_NM(Bs3TestCallDoerInPEV86)(CONV_TO_RM_FAR16(paEntries[i].pfnWorker)); +# else + bErrNo = TMPL_NM(Bs3TestCallDoerInPEV86)(CONV_TO_RM_FAR16(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_f16))); +# endif + CHECK_RESULT(g_szBs3ModeName_pev86); + } + + /* + * Paged protected mode. + */ + if (!fMinimal) + { + PRE_DO_CALL(g_szBs3ModeName_pp16); +# if ARCH_BITS == 16 + bErrNo = TMPL_NM(Bs3TestCallDoerInPP16)(CONV_TO_PROT_FAR16(paEntries[i].pfnWorker)); +# else + bErrNo = TMPL_NM(Bs3TestCallDoerInPP16)(CONV_TO_PROT_FAR16(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_f16))); +# endif + CHECK_RESULT(g_szBs3ModeName_pp16); + } + + if (!fMinimal) + { + PRE_DO_CALL(g_szBs3ModeName_pp16_32); +# if ARCH_BITS == 32 + bErrNo = TMPL_NM(Bs3TestCallDoerInPP16_32)(CONV_TO_FLAT(paEntries[i].pfnWorker), BS3_MODE_PP16_32); +# else + bErrNo = TMPL_NM(Bs3TestCallDoerInPP16_32)(CONV_TO_FLAT(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_c32)), BS3_MODE_PP16_32); +# endif + CHECK_RESULT(g_szBs3ModeName_pp16_32); + } + + if (fCurDoWeirdV86Modes) + { + PRE_DO_CALL(g_szBs3ModeName_pp16_v86); +# if ARCH_BITS == 16 + bErrNo = TMPL_NM(Bs3TestCallDoerInPP16_V86)(CONV_TO_RM_FAR16(paEntries[i].pfnWorker)); +# else + bErrNo = TMPL_NM(Bs3TestCallDoerInPP16_V86)(CONV_TO_RM_FAR16(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_f16))); +# endif + CHECK_RESULT(g_szBs3ModeName_pp16_v86); + } + + if (true) + { + PRE_DO_CALL(g_szBs3ModeName_pp32); +# if ARCH_BITS == 32 + bErrNo = TMPL_NM(Bs3TestCallDoerInPP32)(CONV_TO_FLAT(paEntries[i].pfnWorker), BS3_MODE_PP32); +# else + bErrNo = TMPL_NM(Bs3TestCallDoerInPP32)(CONV_TO_FLAT(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_c32)), BS3_MODE_PP32); +# endif + CHECK_RESULT(g_szBs3ModeName_pp32); + } + + if (!fMinimal) + { + PRE_DO_CALL(g_szBs3ModeName_pp32_16); +# if ARCH_BITS == 16 + bErrNo = TMPL_NM(Bs3TestCallDoerInPP32_16)(CONV_TO_PROT_FAR16(paEntries[i].pfnWorker)); +# else + bErrNo = TMPL_NM(Bs3TestCallDoerInPP32_16)(CONV_TO_PROT_FAR16(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_f16))); +# endif + CHECK_RESULT(g_szBs3ModeName_pp32_16); + } + + if (fCurDoV86Modes) + { + PRE_DO_CALL(g_szBs3ModeName_ppv86); +# if ARCH_BITS == 16 + bErrNo = TMPL_NM(Bs3TestCallDoerInPPV86)(CONV_TO_RM_FAR16(paEntries[i].pfnWorker)); +# else + bErrNo = TMPL_NM(Bs3TestCallDoerInPPV86)(CONV_TO_RM_FAR16(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_f16))); +# endif + CHECK_RESULT(g_szBs3ModeName_ppv86); + } + + + /* + * Protected mode with PAE paging. + */ + if (!fMinimal) + { + PRE_DO_CALL(g_szBs3ModeName_pae16); +# if ARCH_BITS == 16 + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE16)(CONV_TO_PROT_FAR16(paEntries[i].pfnWorker)); +# else + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE16)(CONV_TO_PROT_FAR16(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_f16))); +# endif + CHECK_RESULT(g_szBs3ModeName_pae16); + } + + if (!fMinimal) + { + PRE_DO_CALL(g_szBs3ModeName_pae16_32); +# if ARCH_BITS == 32 + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE16_32)(CONV_TO_FLAT(paEntries[i].pfnWorker), BS3_MODE_PAE16_32); +# else + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE16_32)(CONV_TO_FLAT(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_c32)), BS3_MODE_PAE16_32); +# endif + CHECK_RESULT(g_szBs3ModeName_pae16_32); + } + + if (fCurDoWeirdV86Modes) + { + PRE_DO_CALL(g_szBs3ModeName_pae16_v86); +# if ARCH_BITS == 16 + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE16_V86)(CONV_TO_RM_FAR16(paEntries[i].pfnWorker)); +# else + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE16_V86)(CONV_TO_RM_FAR16(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_f16))); +# endif + CHECK_RESULT(g_szBs3ModeName_pae16_v86); + } + + if (true) + { + PRE_DO_CALL(g_szBs3ModeName_pae32); +# if ARCH_BITS == 32 + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE32)(CONV_TO_FLAT(paEntries[i].pfnWorker), BS3_MODE_PAE32); +# else + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE32)(CONV_TO_FLAT(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_c32)), BS3_MODE_PAE32); +# endif + CHECK_RESULT(g_szBs3ModeName_pae32); + } + + if (!fMinimal) + { + PRE_DO_CALL(g_szBs3ModeName_pae32_16); +# if ARCH_BITS == 16 + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE32_16)(CONV_TO_PROT_FAR16(paEntries[i].pfnWorker)); +# else + bErrNo = TMPL_NM(Bs3TestCallDoerInPAE32_16)(CONV_TO_PROT_FAR16(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_f16))); +# endif + CHECK_RESULT(g_szBs3ModeName_pae32_16); + } + + if (fCurDoV86Modes) + { + PRE_DO_CALL(g_szBs3ModeName_paev86); +# if ARCH_BITS == 16 + bErrNo = TMPL_NM(Bs3TestCallDoerInPAEV86)(CONV_TO_RM_FAR16(paEntries[i].pfnWorker)); +# else + bErrNo = TMPL_NM(Bs3TestCallDoerInPAEV86)(CONV_TO_RM_FAR16(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_f16))); +# endif + CHECK_RESULT(g_szBs3ModeName_paev86); + } + +#endif /* ARCH_BITS != 64 */ + + /* + * Long mode. + */ + if (!fHaveLongMode) + { + if (fSkipped) + Bs3TestSkipped(NULL); + continue; + } + + if (!fMinimal) + { + PRE_DO_CALL(g_szBs3ModeName_lm16); +#if ARCH_BITS == 16 + bErrNo = TMPL_NM(Bs3TestCallDoerInLM16)(CONV_TO_PROT_FAR16(paEntries[i].pfnWorker)); +#else + bErrNo = TMPL_NM(Bs3TestCallDoerInLM16)(CONV_TO_PROT_FAR16(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_f16))); +#endif + CHECK_RESULT(g_szBs3ModeName_lm16); + } + + if (!fMinimal) + { + PRE_DO_CALL(g_szBs3ModeName_lm32); +#if ARCH_BITS == 32 + bErrNo = TMPL_NM(Bs3TestCallDoerInLM32)(CONV_TO_FLAT(paEntries[i].pfnWorker)); +#else + bErrNo = TMPL_NM(Bs3TestCallDoerInLM32)(CONV_TO_FLAT(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_c32))); +#endif + CHECK_RESULT(g_szBs3ModeName_lm32); + } + + if (true) + { + PRE_DO_CALL(g_szBs3ModeName_lm64); +#if ARCH_BITS == 64 + bErrNo = TMPL_NM(Bs3TestCallDoerInLM64)(CONV_TO_FLAT(paEntries[i].pfnWorker), BS3_MODE_LM64); +#else + bErrNo = TMPL_NM(Bs3TestCallDoerInLM64)(CONV_TO_FLAT(RT_CONCAT3(Bs3TestCallDoerTo,ARCH_BITS,_c64)), BS3_MODE_LM64); +#endif + CHECK_RESULT(g_szBs3ModeName_lm64); + } + + if (fSkipped) + Bs3TestSkipped("skipped\n"); + } + Bs3TestSubDone(); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesByOneStub.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesByOneStub.asm new file mode 100644 index 00000000..2f9c9916 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesByOneStub.asm @@ -0,0 +1,63 @@ +; $Id: bs3-mode-TestDoModesByOneStub.asm $ +;; @file +; BS3Kit - Bs3TestDoModesByOne near stub. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + +; +; Near stub for the API call (16-bit only). +; +%if TMPL_BITS == 16 + %if TMPL_MODE == BS3_MODE_RM +BS3_BEGIN_RMTEXT16 + %endif +BS3_BEGIN_TEXT16_NEARSTUBS +BS3_PROC_BEGIN_MODE Bs3TestDoModesByOne, BS3_PBC_NEAR + pop ax + push cs + push ax + %if TMPL_MODE == BS3_MODE_RM + extern TMPL_FAR_NM(Bs3TestDoModesByOne):wrt BS3GROUPRMTEXT16 + jmp far TMPL_FAR_NM(Bs3TestDoModesByOne) + %else + extern TMPL_FAR_NM(Bs3TestDoModesByOne):wrt CGROUP16 + jmp TMPL_NM(Bs3TestDoModesByOne) + %endif +BS3_PROC_END_MODE Bs3TestDoModesByOne +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesHlp.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesHlp.asm new file mode 100644 index 00000000..cb4b19f1 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesHlp.asm @@ -0,0 +1,1139 @@ +; $Id: bs3-mode-TestDoModesHlp.asm $ +;; @file +; BS3Kit - Bs3TestDoModes helpers +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* Defined Constants And Macros * +;********************************************************************************************************************************* +; +; We put most of this mess in the RMTEXT16 segment when in real mode. +; +%if TMPL_MODE == BS3_MODE_RM + %define MY_BEGIN_TEXT BS3_BEGIN_RMTEXT16 + %define MY_BEGIN_TEXT16 BS3_BEGIN_RMTEXT16 + %define MY_TEXT16_WRT(a_Label) a_Label wrt BS3GROUPRMTEXT16 +%else + %define MY_BEGIN_TEXT TMPL_BEGIN_TEXT + %define MY_BEGIN_TEXT16 BS3_BEGIN_TEXT16 + %define MY_TEXT16_WRT(a_Label) BS3_TEXT16_WRT(a_Label) +%endif + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +%if TMPL_MODE == BS3_MODE_RM +BS3_BEGIN_TEXT16_FARSTUBS +extern TMPL_FAR_NM(Bs3SwitchToRM) +extern TMPL_FAR_NM(Bs3SwitchToPE16) +extern TMPL_FAR_NM(Bs3SwitchToPE16_32) +extern TMPL_FAR_NM(Bs3SwitchToPE16_V86) +extern TMPL_FAR_NM(Bs3SwitchToPE32) +extern TMPL_FAR_NM(Bs3SwitchToPE32_16) +extern TMPL_FAR_NM(Bs3SwitchToPEV86) +extern TMPL_FAR_NM(Bs3SwitchToPP16) +extern TMPL_FAR_NM(Bs3SwitchToPP16_32) +extern TMPL_FAR_NM(Bs3SwitchToPP16_V86) +extern TMPL_FAR_NM(Bs3SwitchToPP32) +extern TMPL_FAR_NM(Bs3SwitchToPP32_16) +extern TMPL_FAR_NM(Bs3SwitchToPPV86) +extern TMPL_FAR_NM(Bs3SwitchToPAE16) +extern TMPL_FAR_NM(Bs3SwitchToPAE16_32) +extern TMPL_FAR_NM(Bs3SwitchToPAE16_V86) +extern TMPL_FAR_NM(Bs3SwitchToPAE32) +extern TMPL_FAR_NM(Bs3SwitchToPAE32_16) +extern TMPL_FAR_NM(Bs3SwitchToPAEV86) +extern TMPL_FAR_NM(Bs3SwitchToLM16) +extern TMPL_FAR_NM(Bs3SwitchToLM32) +extern TMPL_FAR_NM(Bs3SwitchToLM64) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_rm_far) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pe16_far) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pe16_v86_far) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pe32_16_far) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pev86_far) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pp16_far) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pp16_v86_far) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pp32_16_far) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_ppv86_far) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pae16_far) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pae16_v86_far) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pae32_16_far) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_paev86_far) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_lm16_far) +%else +BS3_BEGIN_TEXT16 +extern TMPL_NM(Bs3SwitchToRM) +extern TMPL_NM(Bs3SwitchToPE16) +extern TMPL_NM(Bs3SwitchToPE16_32) +extern TMPL_NM(Bs3SwitchToPE16_V86) +extern TMPL_NM(Bs3SwitchToPE32) +extern TMPL_NM(Bs3SwitchToPE32_16) +extern TMPL_NM(Bs3SwitchToPEV86) +extern TMPL_NM(Bs3SwitchToPP16) +extern TMPL_NM(Bs3SwitchToPP16_32) +extern TMPL_NM(Bs3SwitchToPP16_V86) +extern TMPL_NM(Bs3SwitchToPP32) +extern TMPL_NM(Bs3SwitchToPP32_16) +extern TMPL_NM(Bs3SwitchToPPV86) +extern TMPL_NM(Bs3SwitchToPAE16) +extern TMPL_NM(Bs3SwitchToPAE16_32) +extern TMPL_NM(Bs3SwitchToPAE16_V86) +extern TMPL_NM(Bs3SwitchToPAE32) +extern TMPL_NM(Bs3SwitchToPAE32_16) +extern TMPL_NM(Bs3SwitchToPAEV86) +extern TMPL_NM(Bs3SwitchToLM16) +extern TMPL_NM(Bs3SwitchToLM32) +extern TMPL_NM(Bs3SwitchToLM64) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_rm) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe16) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe16_v86) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe32_16) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pev86) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp16) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp16_v86) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp32_16) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_ppv86) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae16) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae16_v86) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae32_16) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_paev86) +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_lm16) +%endif +BS3_BEGIN_TEXT16 +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe16_32):wrt BS3FLAT +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe32):wrt BS3FLAT +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp16_32):wrt BS3FLAT +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp32):wrt BS3FLAT +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae16_32):wrt BS3FLAT +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae32):wrt BS3FLAT +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_lm32):wrt BS3FLAT +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_lm64):wrt BS3FLAT + + +MY_BEGIN_TEXT16 ; need the group definition +MY_BEGIN_TEXT + +;; +; Shared prologue code. +; @param xAX Where to jump to for the main event. +; +BS3_GLOBAL_NAME_EX TMPL_NM(bs3TestCallDoerPrologue), , 0 + BS3_CALL_CONV_PROLOG 1 + push xBP + mov xBP, xSP + xPUSHF + + ; Save non-volatile registers so the DO function doesn't have to. + push xBX + push xCX + push xDX + push xSI + push xDI +%if TMPL_BITS != 64 + push ds + push es + push ss + %if TMPL_BITS != 16 + push fs + push gs + %endif +%endif +%if TMPL_BITS == 64 + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 +%endif + + ; Jump to the main code. + jmp xAX + +;; +; Shared epilogue code. +; @param xAX Return code. +; +BS3_GLOBAL_NAME_EX TMPL_NM(bs3TestCallDoerEpilogue), , 0 + ; Restore registers. +%if TMPL_BITS == 16 + sub bp, (1+5+3)*2 + mov sp, bp +%elif TMPL_BITS == 32 + lea xSP, [xBP - (1+5+5)*4] +%else + lea xSP, [xBP - (1+5+8)*8] + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 +%endif +%if TMPL_BITS != 64 + %if TMPL_BITS != 16 + pop gs + pop fs + %endif + pop ss + pop es + pop ds +%endif + pop xDI + pop xSI + pop xDX + pop xCX + pop xBX + xPOPF + pop xBP + ret + +; +; For checking that the mode switching macros doesn't screw up GPRs. +; Note! Does not work on pre 286 hardware! So, for debugging only. +; +%if 0 + %macro STRICT_SAVE_REGS 0 + movzx esp, sp + sub esp, BS3REGCTX_size + mov [esp + BS3REGCTX.rax], eax + mov dword [esp + BS3REGCTX.rax+4], 0xdead0000 + mov [esp + BS3REGCTX.rcx], ecx + mov dword [esp + BS3REGCTX.rcx+4], 0xdead0001 + mov [esp + BS3REGCTX.rdx], edx + mov dword [esp + BS3REGCTX.rdx+4], 0xdead0002 + mov [esp + BS3REGCTX.rbx], ebx + mov dword [esp + BS3REGCTX.rbx+4], 0xdead0003 + mov [esp + BS3REGCTX.rbp], ebp + mov [esp + BS3REGCTX.rsp], esp + mov [esp + BS3REGCTX.rsi], esi + mov [esp + BS3REGCTX.rdi], edi + %endmacro + + %macro STRICT_CHECK_REGS 0 +%%_esp: cmp [esp + BS3REGCTX.rsp], esp + jne %%_esp +%%_eax: cmp [esp + BS3REGCTX.rax], eax + jne %%_eax +%%_ecx: mov [esp + BS3REGCTX.rcx], ecx + jne %%_ecx +%%_edx: cmp [esp + BS3REGCTX.rdx], edx + jne %%_edx +%%_ebx: cmp [esp + BS3REGCTX.rbx], ebx + jne %%_ebx +%%_ebp: cmp [esp + BS3REGCTX.rbp], ebp + jne %%_ebp +%%_esi: cmp [esp + BS3REGCTX.rsi], esi + jne %%_esi +%%_edi: cmp [esp + BS3REGCTX.rdi], edi + jne %%_edi + add esp, BS3REGCTX_size + %endmacro +%else + + %macro STRICT_SAVE_REGS 0 + %endmacro + %macro STRICT_CHECK_REGS 0 + %endmacro +%endif + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Real mode +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInRM(uint16_t offBs3Text16); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInRM, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +MY_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .doit + mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer. + mov dx, [xBP + xCB + cbCurRetAddr + 2] + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToRM) +%else + call TMPL_NM(Bs3SwitchToRM) +%endif + BS3_SET_BITS 16 + STRICT_CHECK_REGS + + mov cx, BS3_MODE_RM + push cx + push cs + mov cx, .return + push cx + push dx + push ax + retf +.return: + + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_rm_far) +%else + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_rm) +%endif + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +MY_BEGIN_TEXT +BS3_PROC_END_MODE Bs3TestCallDoerInRM + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Unpage protection mode. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPE16(uint16_t offBs3Text16); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPE16, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +MY_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .doit + mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer. + mov dx, [xBP + xCB + cbCurRetAddr + 2] + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToPE16) +%else + call TMPL_NM(Bs3SwitchToPE16) +%endif + BS3_SET_BITS 16 + STRICT_CHECK_REGS + + push BS3_MODE_PE16 + push cs + push .return + push dx + push ax + retf +.return: + + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pe16_far) +%else + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe16) +%endif + BS3_SET_BITS TMPL_BITS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +MY_BEGIN_TEXT +BS3_PROC_END_MODE Bs3TestCallDoerInPE16 + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPE16_32(uint32_t FlatWorkerAddr, uint8_t bMode); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPE16_32, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +.doit: + mov eax, [xBP + xCB + cbCurRetAddr] ; Load function pointer. + movzx edx, byte [xBP + xCB + cbCurRetAddr + sCB] ; bMode + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToPE16_32) +%else + call TMPL_NM(Bs3SwitchToPE16_32) +%endif + BS3_SET_BITS 32 + STRICT_CHECK_REGS + + push edx ; bMode + call eax + + STRICT_SAVE_REGS + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe16_32) + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +BS3_PROC_END_MODE Bs3TestCallDoerInPE16_32 + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPE16_V86(uint16_t offBs3Text16); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPE16_V86, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +MY_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .doit + mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer. + mov dx, [xBP + xCB + cbCurRetAddr + 2] + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToPE16_V86) +%else + call TMPL_NM(Bs3SwitchToPE16_V86) +%endif + BS3_SET_BITS 16 + STRICT_CHECK_REGS + + push BS3_MODE_PE16_V86 + push cs + push .return + push dx + push ax + retf +.return: + + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pe16_v86_far) +%else + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe16_v86) +%endif + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +MY_BEGIN_TEXT +BS3_PROC_END_MODE Bs3TestCallDoerInPE16_V86 + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPE32(uint32_t FlatWorkerAddr, uint8_t bMode); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPE32, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +.doit: + mov eax, [xBP + xCB + cbCurRetAddr] ; Load function pointer. + movzx edx, byte [xBP + xCB + cbCurRetAddr + sCB] ; bMode + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToPE32) +%else + call TMPL_NM(Bs3SwitchToPE32) +%endif + BS3_SET_BITS 32 + STRICT_CHECK_REGS + + push edx ; bMode + call eax + + STRICT_SAVE_REGS + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe32) + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +BS3_PROC_END_MODE Bs3TestCallDoerInPE32 + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPE32_16(uint16_t offBs3Text16); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPE32_16, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +MY_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .doit + mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer. + mov dx, [xBP + xCB + cbCurRetAddr + 2] + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToPE32_16) +%else + call TMPL_NM(Bs3SwitchToPE32_16) +%endif + BS3_SET_BITS 16 + STRICT_CHECK_REGS + + push BS3_MODE_PE32_16 + push cs + push .return + push dx + push ax + retf +.return: + + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pe32_16_far) +%else + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pe32_16) +%endif + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +MY_BEGIN_TEXT +BS3_PROC_END_MODE Bs3TestCallDoerInPE32_16 + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPEV86(uint16_t offBs3Text16); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPEV86, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +MY_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .doit + mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer. + mov dx, [xBP + xCB + cbCurRetAddr + 2] + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToPEV86) +%else + call TMPL_NM(Bs3SwitchToPEV86) +%endif + BS3_SET_BITS 16 + STRICT_CHECK_REGS + + push BS3_MODE_PEV86 + push cs + push .return + push dx + push ax + retf +.return: + + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pev86_far) +%else + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pev86) +%endif + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +MY_BEGIN_TEXT +BS3_PROC_END_MODE Bs3TestCallDoerInPEV86 + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Page protection mode. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPP16(uint16_t offBs3Text16); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPP16, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +MY_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .doit + mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer. + mov dx, [xBP + xCB + cbCurRetAddr + 2] + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToPP16) +%else + call TMPL_NM(Bs3SwitchToPP16) +%endif + BS3_SET_BITS 16 + STRICT_CHECK_REGS + + push BS3_MODE_PP16 + push cs + push .return + push dx + push ax + retf +.return: + + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pp16_far) +%else + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp16) +%endif + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +MY_BEGIN_TEXT +BS3_PROC_END_MODE Bs3TestCallDoerInPP16 + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPP16_32(uint32_t uFlatWorkerAddr, uint8_t bMode); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPP16_32, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +.doit: + mov eax, [xBP + xCB + cbCurRetAddr] ; Load function pointer. + movzx edx, byte [xBP + xCB + cbCurRetAddr + sCB] ; bMode + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToPP16_32) +%else + call TMPL_NM(Bs3SwitchToPP16_32) +%endif + BS3_SET_BITS 32 + STRICT_CHECK_REGS + + push edx + call eax + + STRICT_SAVE_REGS + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp16_32) + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +BS3_PROC_END_MODE Bs3TestCallDoerInPP16_32 + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPP16_V86(uint16_t offBs3Text16); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPP16_V86, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +MY_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .doit + mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer. + mov dx, [xBP + xCB + cbCurRetAddr + 2] + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToPP16_V86) +%else + call TMPL_NM(Bs3SwitchToPP16_V86) +%endif + BS3_SET_BITS 16 + STRICT_CHECK_REGS + + push BS3_MODE_PP16_V86 + push cs + push .return + push dx + push ax + retf +.return: + + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pp16_v86_far) +%else + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp16_v86) +%endif + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +MY_BEGIN_TEXT +BS3_PROC_END_MODE Bs3TestCallDoerInPP16_V86 + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPP32(uint32_t uFlatWorkerAddr, uint8_t bMode); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPP32, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +.doit: + mov eax, [xBP + xCB + cbCurRetAddr] ; Load function pointer. + movzx edx, byte [xBP + xCB + cbCurRetAddr + sCB] ; bMode + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToPP32) +%else + call TMPL_NM(Bs3SwitchToPP32) +%endif + BS3_SET_BITS 32 + STRICT_CHECK_REGS + + push edx ; bMode + call eax + + STRICT_SAVE_REGS + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp32) + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +BS3_PROC_END_MODE Bs3TestCallDoerInPP32 + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPP32_16(uint16_t offBs3Text16); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPP32_16, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +MY_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .doit + mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer. + mov dx, [xBP + xCB + cbCurRetAddr + 2] + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToPP32_16) +%else + call TMPL_NM(Bs3SwitchToPP32_16) +%endif + BS3_SET_BITS 16 + STRICT_CHECK_REGS + + push BS3_MODE_PP32_16 + push cs + push .return + push dx + push ax + retf +.return: + + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pp32_16_far) +%else + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pp32_16) +%endif + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +MY_BEGIN_TEXT +BS3_PROC_END_MODE Bs3TestCallDoerInPP32_16 + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPPV86(uint16_t offBs3Text16); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPPV86, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +MY_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .doit + mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer. + mov dx, [xBP + xCB + cbCurRetAddr + 2] + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToPPV86) +%else + call TMPL_NM(Bs3SwitchToPPV86) +%endif + BS3_SET_BITS 16 + STRICT_CHECK_REGS + + push BS3_MODE_PPV86 + push cs + push .return + push dx + push ax + retf +.return: + + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_ppv86_far) +%else + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_ppv86) +%endif + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +MY_BEGIN_TEXT +BS3_PROC_END_MODE Bs3TestCallDoerInPPV86 + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PAE paged protection mode. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPAE16(uint16_t offBs3Text16); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPAE16, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +MY_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .doit + mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer. + mov dx, [xBP + xCB + cbCurRetAddr + 2] + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToPAE16) +%else + call TMPL_NM(Bs3SwitchToPAE16) +%endif + BS3_SET_BITS 16 + STRICT_CHECK_REGS + + push BS3_MODE_PAE16 + push cs + push .return + push dx + push ax + retf +.return: + + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pae16_far) +%else + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae16) +%endif + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +MY_BEGIN_TEXT +BS3_PROC_END_MODE Bs3TestCallDoerInPAE16 + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPAE16_32(uint32_t uFlatWorkerAddr, uint8_t bMode); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPAE16_32, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +.doit: + mov eax, [xBP + xCB + cbCurRetAddr] ; Load function pointer. + movzx edx, byte [xBP + xCB + cbCurRetAddr + sCB] ; bMode + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToPAE16_32) +%else + call TMPL_NM(Bs3SwitchToPAE16_32) +%endif + BS3_SET_BITS 32 + STRICT_CHECK_REGS + + push edx ; bMode + call eax + + STRICT_SAVE_REGS + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae16_32) + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +BS3_PROC_END_MODE Bs3TestCallDoerInPAE16_32 + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPAE16_V86(uint16_t offBs3Text16); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPAE16_V86, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +MY_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .doit + mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer. + mov dx, [xBP + xCB + cbCurRetAddr + 2] + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToPAE16_V86) +%else + call TMPL_NM(Bs3SwitchToPAE16_V86) +%endif + BS3_SET_BITS 16 + STRICT_CHECK_REGS + + push BS3_MODE_PAE16_V86 + push cs + push .return + push dx + push ax + retf +.return: + + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pae16_v86_far) +%else + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae16_v86) +%endif + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +MY_BEGIN_TEXT +BS3_PROC_END_MODE Bs3TestCallDoerInPAE16_V86 + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPAE32(uint32_t uFlatWorkerAddr, uint8_t bMode); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPAE32, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +.doit: + mov eax, [xBP + xCB + cbCurRetAddr] ; Load function pointer. + movzx edx, byte [xBP + xCB + cbCurRetAddr + sCB] ; bMode + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToPAE32) +%else + call TMPL_NM(Bs3SwitchToPAE32) +%endif + BS3_SET_BITS 32 + STRICT_CHECK_REGS + + push edx ; bMode + call eax + + STRICT_SAVE_REGS + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae32) + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +BS3_PROC_END_MODE Bs3TestCallDoerInPAE32 + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPAE32_16(uint16_t offBs3Text16); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPAE32_16, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +MY_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .doit + mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer. + mov dx, [xBP + xCB + cbCurRetAddr + 2] + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToPAE32_16) +%else + call TMPL_NM(Bs3SwitchToPAE32_16) +%endif + BS3_SET_BITS 16 + STRICT_CHECK_REGS + + push BS3_MODE_PAE32_16 + push cs + push .return + push dx + push ax + retf +.return: + + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_pae32_16_far) +%else + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_pae32_16) +%endif + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +MY_BEGIN_TEXT +BS3_PROC_END_MODE Bs3TestCallDoerInPAE32_16 + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInPAEV86(uint16_t offBs3Text16); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInPAEV86, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +MY_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .doit + mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer. + mov dx, [xBP + xCB + cbCurRetAddr + 2] + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToPAEV86) +%else + call TMPL_NM(Bs3SwitchToPAEV86) +%endif + BS3_SET_BITS 16 + STRICT_CHECK_REGS + + push BS3_MODE_PAEV86 + push cs + push .return + push dx + push ax + retf +.return: + + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_paev86_far) +%else + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_paev86) +%endif + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +MY_BEGIN_TEXT +BS3_PROC_END_MODE Bs3TestCallDoerInPAEV86 + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Long mode +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInLM16(uint16_t offBs3Text16); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInLM16, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +MY_BEGIN_TEXT16 +BS3_SET_BITS TMPL_BITS +BS3_GLOBAL_LOCAL_LABEL .doit + mov ax, [xBP + xCB + cbCurRetAddr] ; Load far function pointer. + mov dx, [xBP + xCB + cbCurRetAddr + 2] + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToLM16) +%else + call TMPL_NM(Bs3SwitchToLM16) +%endif + BS3_SET_BITS 16 + STRICT_CHECK_REGS + + push BS3_MODE_LM16 + push cs + push .return + push dx + push ax + retf +.return: + + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_lm16_far) +%else + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_lm16) +%endif + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +MY_BEGIN_TEXT +BS3_PROC_END_MODE Bs3TestCallDoerInLM16 + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInLM32(uint16_t offBs3Text16); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInLM32, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +.doit: + mov eax, [xBP + xCB + cbCurRetAddr] ; Load function pointer. + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToLM32) +%else + call TMPL_NM(Bs3SwitchToLM32) +%endif + BS3_SET_BITS 32 + STRICT_CHECK_REGS + + and esp, ~03h + push BS3_MODE_LM32 + call eax + + STRICT_SAVE_REGS + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_lm32) + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +BS3_PROC_END_MODE Bs3TestCallDoerInLM32 + +;; +; @cproto BS3_DECL(uint8_t) Bs3TestCallDoerInLM64(uint32_t uFlatWorkerAddr, uint8_t bMode); +; @uses rax +BS3_PROC_BEGIN_MODE Bs3TestCallDoerInLM64, BS3_PBC_NEAR + BS3_LEA_MOV_WRT_RIP(xAX, MY_TEXT16_WRT(.doit)) + jmp TMPL_NM(bs3TestCallDoerPrologue) +.doit: + mov eax, [xBP + xCB + cbCurRetAddr] ; Load function pointer. + movzx edx, byte [xBP + xCB + cbCurRetAddr + sCB] ; bMode + + ; Mode switch, make the call, switch back. + STRICT_SAVE_REGS +%if TMPL_MODE == BS3_MODE_RM + call far TMPL_FAR_NM(Bs3SwitchToLM64) +%else + call TMPL_NM(Bs3SwitchToLM64) +%endif + BS3_SET_BITS 64 + STRICT_CHECK_REGS + + and rsp, ~0fh + sub rsp, 18h + push rdx ; bMode + BS3_CALL rax, 1 + + STRICT_SAVE_REGS + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_lm64) + BS3_SET_BITS TMPL_BITS + STRICT_CHECK_REGS + jmp TMPL_NM(bs3TestCallDoerEpilogue) +BS3_PROC_END_MODE Bs3TestCallDoerInLM64 + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesStub.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesStub.asm new file mode 100644 index 00000000..8b8f05ee --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesStub.asm @@ -0,0 +1,63 @@ +; $Id: bs3-mode-TestDoModesStub.asm $ +;; @file +; BS3Kit - Bs3TestDoModes near stub. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + +; +; Near stub for the API call (16-bit only). +; +%if TMPL_BITS == 16 + %if TMPL_MODE == BS3_MODE_RM +BS3_BEGIN_RMTEXT16 + %endif +BS3_BEGIN_TEXT16_NEARSTUBS +BS3_PROC_BEGIN_MODE Bs3TestDoModes, BS3_PBC_NEAR + pop ax + push cs + push ax + %if TMPL_MODE == BS3_MODE_RM + extern TMPL_FAR_NM(Bs3TestDoModes):wrt BS3GROUPRMTEXT16 + jmp far TMPL_FAR_NM(Bs3TestDoModes) + %else + extern TMPL_FAR_NM(Bs3TestDoModes):wrt CGROUP16 + jmp TMPL_NM(Bs3TestDoModes) + %endif +BS3_PROC_END_MODE Bs3TestDoModes +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TrapInit.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TrapInit.c new file mode 100644 index 00000000..56066d8d --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TrapInit.c @@ -0,0 +1,61 @@ +/* $Id: bs3-mode-TrapInit.c $ */ +/** @file + * BS3Kit - Bs3TrapInit + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit-template-header.h" + + +#undef Bs3TrapInit +BS3_MODE_DEF(void, Bs3TrapInit,(void)) +{ +#if BS3_MODE_IS_RM_SYS(TMPL_MODE) + Bs3TrapRmV86Init(); +#elif BS3_MODE_IS_16BIT_SYS(TMPL_MODE) + Bs3TrapRmV86Init(); + Bs3Trap16Init(); +#elif BS3_MODE_IS_32BIT_SYS(TMPL_MODE) + Bs3TrapRmV86Init(); + Bs3Trap32Init(); +#elif BS3_MODE_IS_64BIT_SYS(TMPL_MODE) + Bs3Trap64Init(); +#else +# error "TMPL_MODE" +#endif +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TrapSetJmpAndRestoreInRmAsm.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TrapSetJmpAndRestoreInRmAsm.asm new file mode 100644 index 00000000..52c0928a --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TrapSetJmpAndRestoreInRmAsm.asm @@ -0,0 +1,174 @@ +; $Id: bs3-mode-TrapSetJmpAndRestoreInRmAsm.asm $ +;; @file +; BS3Kit - Bs3TrapSetJmpAndRestoreInRm helper +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_BEGIN_TEXT16 +extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_rm) +extern _Bs3TrapSetJmpAndRestore_c16 + +TMPL_BEGIN_TEXT +extern TMPL_NM(Bs3SwitchToRM) + + +;; +; Shared prologue code. +; @param xAX Where to jump to for the main event. +; +BS3_PROC_BEGIN_MODE Bs3TrapSetJmpAndRestoreInRmAsm, BS3_PBC_NEAR + BS3_CALL_CONV_PROLOG 2 + push xBP + mov xBP, xSP + xPUSHF + + ; + ; Save non-volatile registers so the DO function doesn't have to. + ; + push xBX + push xCX + push xDX + push xSI + push xDI +%if TMPL_BITS != 64 + push ds + push es + push ss + %if TMPL_BITS != 16 + push fs + push gs + %endif +%endif +%if TMPL_BITS == 64 + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 +%endif + + ; + ; Load EAX and EDX with the two pointers. + ; + mov eax, [xBP + xCB + cbCurRetAddr] + mov edx, [xBP + xCB + cbCurRetAddr + sCB] + + ; + ; Jump to 16-bit segment for the mode switching. + ; +%if TMPL_BITS != 16 + jmp .in_16bit_segment +BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +.in_16bit_segment: +%endif + + ; + ; Switch to real-mode. + ; + call TMPL_NM(Bs3SwitchToRM) + BS3_SET_BITS 16 + + ; + ; Now we do the + ; + push edx + push eax + call _Bs3TrapSetJmpAndRestore_c16 + add sp, 8h + + ; + ; Switch back to the original mode. + ; + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_Safe_rm) + BS3_SET_BITS TMPL_BITS + + ; + ; Jump back to the 32-bit or 64-bit segment. + ; +%if TMPL_BITS != 16 + jmp .in_text_segment +TMPL_BEGIN_TEXT +.in_text_segment: +%endif + + ; + ; Restore registers. + ; +%if TMPL_BITS == 16 + sub bp, (1+5+3)*2 + mov sp, bp +%elif TMPL_BITS == 32 + lea xSP, [xBP - (1+5+5)*4] +%else + lea xSP, [xBP - (1+5+8)*8] + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 +%endif +%if TMPL_BITS != 64 + %if TMPL_BITS != 16 + pop gs + pop fs + %endif + pop ss + pop es + pop ds +%endif + pop xDI + pop xSI + pop xDX + pop xCX + pop xBX + xPOPF + pop xBP + ret +BS3_PROC_END_MODE Bs3TrapSetJmpAndRestoreInRmAsm + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TrapSystemCallHandler.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TrapSystemCallHandler.asm new file mode 100644 index 00000000..313774c0 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TrapSystemCallHandler.asm @@ -0,0 +1,891 @@ +; $Id: bs3-mode-TrapSystemCallHandler.asm $ +;; @file +; BS3Kit - System call trap handler. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +;********************************************************************************************************************************* +;* Header Files * +;********************************************************************************************************************************* +%include "bs3kit-template-header.mac" + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_EXTERN_DATA16 g_bBs3CurrentMode +%if TMPL_BITS != 64 +BS3_EXTERN_DATA16 g_uBs3CpuDetected +%endif +%if TMPL_BITS == 16 +BS3_EXTERN_DATA16 g_uBs3TrapEipHint +%endif +TMPL_BEGIN_TEXT + +BS3_EXTERN_CMN Bs3SelProtFar32ToFlat32 +BS3_EXTERN_CMN Bs3RegCtxConvertToRingX +BS3_EXTERN_CMN Bs3RegCtxRestore +BS3_EXTERN_CMN Bs3Panic + +BS3_BEGIN_TEXT16 +extern Bs3PrintStrN_c16_CX_Bytes_At_DS_SI +TMPL_BEGIN_TEXT + + +;; +; System call handler. +; +; This is an assembly trap handler that is called in response to a system call +; request from 'user' code. The only fixed parameter is [ER]AX which contains +; the system call number. Other registers are assigned on a per system call +; basis, ditto for which registers are preserved and which are used to return +; stuff. Generally, though, we preserve all registers not used as return +; values or otherwise implicitly transformed by the call. +; +; Note! The 16-bit versions of this code must be careful with using extended +; registers as we wish this code to work on real 80286 (maybe even 8086) +; CPUs too! +; +BS3_PROC_BEGIN_MODE Bs3TrapSystemCallHandler, BS3_PBC_NEAR ; Near because we'll probably only ever need this from CGROUP16. + ; + ; This prologue is kind of complicated because of 80286 and older CPUs + ; as well as different requirements for 64-bit and the other modes. + ; +%define VAR_CALLER_BP [xBP] +%if TMPL_BITS != 64 + %define VAR_CALLER_DS [xBP - xCB] +%endif +%define VAR_CALLER_BX [xBP - sCB*1 - xCB] ; Note! the upper word is not clean on pre-386 (16-bit mode). +%define VAR_CALLER_AX [xBP - sCB*2 - xCB] +%define VAR_CALLER_CX [xBP - sCB*3 - xCB] +%define VAR_CALLER_DX [xBP - sCB*4 - xCB] +%define VAR_CALLER_SI [xBP - sCB*5 - xCB] +%define VAR_CALLER_SI_HI [xBP - sCB*5 - xCB + 2] +%define VAR_CALLER_DI [xBP - sCB*6 - xCB] +%define VAR_CALLER_DI_HI [xBP - sCB*6 - xCB + 2] +%if TMPL_BITS == 16 + %define VAR_CALLER_EBP [xBP - sCB*7 - xCB] + %define VAR_CALLER_ESP [xBP - sCB*8 - xCB] + %define VAR_CALLER_EFLAGS [xBP - sCB*9 - xCB] + %define VAR_CALLER_MODE [xBP - sCB*9 - xCB*2] + %define BP_TOP_STACK_EXPR xBP - sCB*9 - xCB*2 +%else + %define VAR_CALLER_MODE [xBP - sCB*6 - xCB*2] + %define BP_TOP_STACK_EXPR xBP - sCB*6 - xCB*2 +%endif + push xBP + mov xBP, xSP +%if TMPL_BITS == 64 + push 0 + mov [rsp+2], es + mov [rsp], ds +%else + push ds + %ifdef TMPL_CMN_R86 + push BS3_SEL_DATA16 + %else + push RT_CONCAT(BS3_SEL_R0_DS,TMPL_BITS) + %endif + pop ds ; DS = BS3KIT_GRPNM_DATA16 or FLAT and we can safely access data + %if TMPL_BITS == 16 && (TMPL_MODE == BS3_MODE_RM || TMPL_MODE == BS3_MODE_PE16) + cmp byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80286 + jbe .prologue_pre_80386 + %endif +%endif + push sBX + push sAX + push sCX + push sDX + push sSI + push sDI +%if TMPL_BITS == 16 + push ebp + push esp + pushfd + %if TMPL_MODE == BS3_MODE_RM || TMPL_MODE == BS3_MODE_PE16 + jmp .prologue_end + +.prologue_pre_80386: + push bx ; dummy + push bx + xor bx, bx + push bx ; dummy + push ax + push bx ; dummy + push cx + push bx ; dummy + push dx + push bx ; dummy + push si + push bx ; dummy + push di + sub sp, 0ch ; dummy + %endif +%endif +.prologue_end: + + ; + ; VAR_CALLER_MODE: Save the current mode (important for v8086 with 16-bit kernel). + ; + xor xBX, xBX + mov bl, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + push xBX + + ; + ; Dispatch the system call. + ; + cmp ax, BS3_SYSCALL_LAST + ja .invalid_syscall +%if TMPL_BITS == 16 + mov bx, ax + shl bx, 1 + jmp word [cs:.aoffSyscallHandlers + bx] +%else + movzx ebx, ax + mov ebx, [.aoffSyscallHandlers + ebx * 4] + jmp xBX +%endif +.aoffSyscallHandlers: +%ifdef TMPL_16BIT + dw .invalid_syscall wrt CGROUP16 + dw .print_chr wrt CGROUP16 + dw .print_str wrt CGROUP16 + dw .to_ringX wrt CGROUP16 + dw .to_ringX wrt CGROUP16 + dw .to_ringX wrt CGROUP16 + dw .to_ringX wrt CGROUP16 + dw .restore_ctx wrt CGROUP16 +%else + dd .invalid_syscall wrt FLAT + dd .print_chr wrt FLAT + dd .print_str wrt FLAT + dd .to_ringX wrt FLAT + dd .to_ringX wrt FLAT + dd .to_ringX wrt FLAT + dd .to_ringX wrt FLAT + dd .restore_ctx wrt FLAT +%endif + + ; + ; Invalid system call. + ; +.invalid_syscall: + int3 + jmp .return + + ; + ; Print char in the CL register. + ; + ; We use the vga bios teletype interrupt to do the writing, so we must + ; be in some kind of real mode for this to work. 16-bit code segment + ; requried for the mode switching code. + ; +BS3_BEGIN_TEXT16 + BS3_SET_BITS TMPL_BITS +.print_chr: +%if TMPL_BITS != 64 + push es + mov di, ss ; Must save and restore SS for supporting 16/32 and 32/16 caller/kernel ring-0 combinations. +%endif +%ifndef TMPL_CMN_R86 + ; Switch to real mode (20h param scratch area not required). + extern TMPL_NM(Bs3SwitchToRM) + call TMPL_NM(Bs3SwitchToRM) + BS3_SET_BITS 16 +%endif + + ; Print the character, turning '\n' into '\r\n'. + cmp cl, 0ah ; \n + je .print_chr_newline + mov ah, 0eh + mov al, cl + mov bx, 0ff00h + int 10h + jmp .print_chr_done + +.print_chr_newline: + mov ax, 0e0dh ; cmd + \r + mov bx, 0ff00h + int 10h + mov ax, 0e0ah ; cmd + \n + mov bx, 0ff00h + int 10h + +.print_chr_done: +%ifndef TMPL_CMN_R86 + ; Switch back (20h param scratch area not required). + extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_rm) + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_rm) + BS3_SET_BITS TMPL_BITS +%endif +%if TMPL_BITS != 64 + mov ss, di + pop es +%endif + jmp .return +TMPL_BEGIN_TEXT + + + ; + ; Prints DX chars from the string pointed to by CX:xSI to the screen. + ; + ; We use the vga bios teletype interrupt to do the writing, so we must + ; be in some kind of real mode for this to work. The string must be + ; accessible from real mode too. + ; +.print_str: +%if TMPL_BITS != 64 + push es + push ss ; Must save and restore SS for supporting 16/32 and 32/16 caller/kernel ring-0 combinations. +%endif + ; Convert the incoming pointer to real mode (assuming caller checked + ; that real mode can access it). + call .convert_ptr_arg_to_real_mode_ax_si + mov cx, VAR_CALLER_DX + + ; Switch to real mode (no 20h scratch required) +%ifndef TMPL_CMN_R86 + %if TMPL_BITS != 16 + jmp .print_str_to_16bit +BS3_BEGIN_TEXT16 +.print_str_to_16bit: + BS3_SET_BITS TMPL_BITS + %endif + extern TMPL_NM(Bs3SwitchToRM) + call TMPL_NM(Bs3SwitchToRM) + BS3_SET_BITS 16 +%endif + ; Call code in Bs3PrintStrN to do the work. + mov ds, ax + call Bs3PrintStrN_c16_CX_Bytes_At_DS_SI + + ; Switch back (20h param scratch area not required). +%ifndef TMPL_CMN_R86 + extern RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_rm) + call RT_CONCAT3(_Bs3SwitchTo,TMPL_MODE_UNAME,_rm) + %if TMPL_BITS != 16 + BS3_SET_BITS TMPL_BITS + jmp .print_str_end +TMPL_BEGIN_TEXT + %endif +.print_str_end: +%endif +%if TMPL_BITS != 64 + pop ss + pop es +%endif + jmp .return + + + ; + ; Switch the caller to ring-0, ring-1, ring-2 or ring-3. + ; + ; This implement this by saving the entire register context, calling + ; a transformation function (C) and restoring the modified register + ; context using a generic worker. + ; +.to_ringX: + sub xSP, BS3REGCTX_size + mov xBX, xSP ; xBP = BS3REGCTX pointer. + call .save_context + +%if TMPL_BITS == 32 + ; Convert xBP to flat pointer in 32-bit + push ss + push xBX + call Bs3SelProtFar32ToFlat32 + add sSP, 8 + mov xBX, xAX +%endif + push xBX ; Save pointer for the final restore call. + + ; Convert the register context from whatever it is to ring-0. +BONLY64 sub rsp, 10h + mov ax, VAR_CALLER_AX + sub ax, BS3_SYSCALL_TO_RING0 + push xAX +BONLY16 push ss + push xBX + BS3_CALL Bs3RegCtxConvertToRingX, 2 + add xSP, sCB + xCB BS3_ONLY_64BIT(+ 10h) + + ; Restore the register context (does not return). + pop xBX ; restore saved pointer. +BONLY64 sub rsp, 18h +BONLY16 push ss + push xBX + BS3_CALL Bs3RegCtxRestore, 1 + jmp Bs3Panic + + + ; + ; Restore context pointed to by cx:xSI. + ; +.restore_ctx: + call .convert_ptr_arg_to_cx_xSI +BONLY64 sub rsp, 10h + mov xDX, VAR_CALLER_DX + push xDX +BONLY16 push cx + push xSI + BS3_CALL Bs3RegCtxRestore, 2 + jmp Bs3Panic + + ; + ; Return. + ; +.return: + pop xBX ; saved mode + mov [BS3_DATA16_WRT(g_bBs3CurrentMode)], bl +%if TMPL_BITS == 16 + and bl, BS3_MODE_CODE_MASK + cmp bl, BS3_MODE_CODE_V86 + je .return_to_v8086_from_16bit_krnl + cmp bl, BS3_MODE_CODE_32 + je .return_to_32bit_from_16bit_krnl + %if TMPL_MODE == BS3_MODE_RM || TMPL_MODE == BS3_MODE_PE16 + cmp byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80286 + jbe .return_pre_80386 + %endif + + popfd + pop esp + pop ebp +%endif + pop sDI + pop sSI + pop sDX + pop sCX + pop sAX + pop sBX +%if TMPL_BITS != 64 + pop ds + leave + iret +%else + mov es, [rsp+2] + mov ds, [rsp] + leave ; skips ds + iretq +%endif + +%if TMPL_BITS == 16 + %if TMPL_MODE == BS3_MODE_RM || TMPL_MODE == BS3_MODE_PE16 + ; Variant of the above for 80286 and older. +.return_pre_80386: + add sp, 0ch + pop di + pop bx ; dummy + pop si + pop bx ; dummy + pop dx + pop bx ; dummy + pop cx + pop bx ; dummy + pop ax + pop bx ; dummy + pop bx ; pushed twice + pop bx + pop ds + pop bp + iret + %endif + +.return_to_v8086_from_16bit_krnl: + int3 + jmp .return_to_v8086_from_16bit_krnl + + ; + ; Returning to 32-bit code may require us to expand and seed the eip + ; and esp addresses in the iret frame since these are truncated when + ; using a 16-bit interrupt handler. + ; + ; Incoming stack: New stack diff cpl: + ; bp + 0ah: [ss] + ; bp + 08h: [sp] bx + 38h: [ss] New stack same cpl: + ; bp + 06h: flags + ; bp + 04h: cs bx + 34h: [esp] bx + 30h: eflags + ; bp + 02h: ip + ; -------------- bx + 30h: eflags bx + 2ch: cs + ; bp + 00h: bp + ; bp - 02h: ds bx + 2ch: cs bx + 28h: eip + ; ------------- + ; bp - 06h: ebx bx + 28h: eip bx + 26h: bp + ; -------------- bx + 24h: ds + ; bp - 0ah: eax bx + 26h: bp + ; bx + 24h: ds bx + 20h: ebx + ; bp - 0eh: ecx + ; bx + 20h: ebx bx + 1ch: eax + ; bp - 12h: edx + ; bx + 1ch: eax bx + 18h: ecx + ; bp - 16h: esi + ; bx + 18h: ecx bx + 14h: edx + ; bp - 1ah: edi + ; bx + 14h: edx bx + 10h: esi + ; bp - 1eh: esp + ; bx + 10h: esi bx + 0ch: edi + ; bp - 22h: ebp + ; bx + 0ch: edi bx + 08h: esp + ; bp - 26h: eflags + ; bx + 08h: esp bx + 04h: ebp + ; + ; bx + 04h: ebp bx + 00h: eflags + ; + ; bx + 00h: eflags + ; + ; + ; If we're returning to the same CPL, we're still using the stack of + ; the 32-bit caller. The high ESP word does not need restoring. + ; + ; If we're returning to a lower CPL, there on a 16-bit ring-0 stack, + ; however, the high ESP word is still that of the caller. + ; +.return_to_32bit_from_16bit_krnl: + mov ax, cs + and al, 3 + mov ah, 3 + and ah, [xBP + xCB*2] + ; The iret frame doubles in size, so allocate more stack. + cmp al, ah + je .return_to_32bit_from_16bit_krnl_same_cpl_sub_sp + sub sp, 2*2 +.return_to_32bit_from_16bit_krnl_same_cpl_sub_sp: + sub sp, 3*2 + mov bx, sp + ; Copy the saved registers. + xor di, di +.return_to_32bit_from_16bit_krnl_copy_loop: + mov ecx, [bp + di - 26h] + mov [ss:bx + di], ecx + add di, 4 + cmp di, 28h + jb .return_to_32bit_from_16bit_krnl_copy_loop + ; Convert the 16-bit iret frame to a 32-bit iret frame. + mov ecx, [BS3_DATA16_WRT(g_uBs3TrapEipHint)] + mov cx, [bp + 02h] ; ip + mov [ss:bx + 28h], ecx + mov ecx, 0f00d0000h + mov cx, [bp + 04h] ; cs + mov [ss:bx + 2ch], ecx + mov ecx, [ss:bx] ; caller eflags + mov cx, [bp + 06h] ; flags + mov [ss:bx + 30h], ecx + cmp al, ah + jz .return_to_32bit_from_16bit_krnl_do_return + mov ecx, [ss:bx + 08h] ; caller esp + mov cx, [bp + 08h] ; sp + mov [ss:bx + 34h], ecx + mov ecx, 0f00d0000h + mov cx, [bp + 0ah] ; ss + mov [ss:bx + 38h], ecx +.return_to_32bit_from_16bit_krnl_do_return: + popfd + pop ecx ; esp - only the high bits! + mov cx, sp + mov esp, ecx + pop ebp + lea bp, [bx + 26h] + pop edi + pop esi + pop edx + pop ecx + pop eax + pop ebx + pop ds + leave + iretd + +%endif ; 16-bit + + + ; + ; Internal function. ss:xBX = Pointer to register frame (BS3REGCTX). + ; @uses xAX + ; +.save_context: +%if TMPL_BITS == 16 + cmp byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80386 + jae .save_context_full + + ; + ; 80286 or earlier. + ; + + ; Clear the state area first. + push di + xor di, di +.save_context_16_clear_loop: + mov word [ss:bx + di], 0 + mov word [ss:bx + di + 2], 0 + mov word [ss:bx + di + 4], 0 + mov word [ss:bx + di + 6], 0 + add di, 8 + cmp di, BS3REGCTX_size + jb .save_context_16_clear_loop + pop di + + ; Do the 8086/80186/80286 state saving. + mov ax, VAR_CALLER_AX + mov [ss:bx + BS3REGCTX.rax], ax + mov cx, VAR_CALLER_CX + mov [ss:bx + BS3REGCTX.rcx], ax + mov ax, VAR_CALLER_DX + mov [ss:bx + BS3REGCTX.rdx], ax + mov ax, VAR_CALLER_BX + mov [ss:bx + BS3REGCTX.rbx], ax + mov [ss:bx + BS3REGCTX.rsi], si + mov [ss:bx + BS3REGCTX.rdi], di + mov ax, VAR_CALLER_BP + mov [ss:bx + BS3REGCTX.rbp], ax + mov ax, VAR_CALLER_DS + mov [ss:bx + BS3REGCTX.ds], ax + mov [ss:bx + BS3REGCTX.es], es + mov ax, [xBP + xCB] + mov [ss:bx + BS3REGCTX.rip], ax + mov ax, [xBP + xCB*2] + mov [ss:bx + BS3REGCTX.cs], ax + and al, X86_SEL_RPL + mov [ss:bx + BS3REGCTX.bCpl], al + cmp al, 0 + je .save_context_16_same + mov ax, [xBP + xCB*4] + mov [ss:bx + BS3REGCTX.rsp], ax + mov ax, [xBP + xCB*5] + mov [ss:bx + BS3REGCTX.ss], ax + jmp .save_context_16_done_stack +.save_context_16_same: + mov ax, bp + add ax, xCB * (1 + 3) + mov [ss:bx + BS3REGCTX.rsp], ax + mov ax, ss + mov [ss:bx + BS3REGCTX.ss], ax +.save_context_16_done_stack: + mov ax, [xBP + xCB*3] + mov [ss:bx + BS3REGCTX.rflags], ax + mov al, VAR_CALLER_MODE + mov [ss:bx + BS3REGCTX.bMode], al + cmp byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80286 + jne .save_context_16_return + smsw [ss:bx + BS3REGCTX.cr0] + str [ss:bx + BS3REGCTX.tr] + sldt [ss:bx + BS3REGCTX.ldtr] +.save_context_16_return: + or byte [ss:bx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_AMD64 | BS3REG_CTX_F_NO_CR4 + ret +%endif ; TMPL_BITS == 16 + + ; + ; 80386 or later. + ; +.save_context_full: + + ; Clear the state area. + push xDI + xor xDI, xDI + AssertCompileSizeAlignment(BS3REGCTX, 16) +.save_context_full_clear_loop: +%if TMPL_BITS != 64 + mov dword [ss:xBX + xDI], 0 + mov dword [ss:xBX + xDI + 4], 0 + add xDI, 8 +%else + mov qword [xBX + xDI], 0 + mov qword [xBX + xDI + 8], 0 + add xDI, 10h +%endif + cmp xDI, BS3REGCTX_size + jb .save_context_full_clear_loop + pop xDI + + ; Do the 386+ state saving. +%if TMPL_BITS == 16 ; save the high word of registered pushed on the stack. + mov ecx, VAR_CALLER_AX + mov [ss:bx + BS3REGCTX.rax], ecx + mov ecx, VAR_CALLER_CX + mov [ss:bx + BS3REGCTX.rcx], ecx + mov ecx, VAR_CALLER_DX + mov [ss:bx + BS3REGCTX.rdx], ecx + mov ecx, VAR_CALLER_BX + mov [ss:bx + BS3REGCTX.rbx], ecx + mov ecx, VAR_CALLER_EBP + mov [ss:bx + BS3REGCTX.rbp], ecx + mov ecx, VAR_CALLER_ESP + mov [ss:bx + BS3REGCTX.rsp], ecx + mov ecx, VAR_CALLER_SI + mov [ss:bx + BS3REGCTX.rsi], ecx + mov ecx, VAR_CALLER_DI + mov [ss:bx + BS3REGCTX.rdi], ecx + mov ecx, VAR_CALLER_EFLAGS + mov [ss:bx + BS3REGCTX.rflags], ecx + + ; Seed high EIP word if 32-bit CS. + lar ecx, [bp + 4] + jnz .save_context_full_done_16bit_high_word + test ecx, X86LAR_F_D + jz .save_context_full_done_16bit_high_word + mov ecx, [BS3_DATA16_WRT(g_uBs3TrapEipHint)] + mov [ss:bx + BS3REGCTX.rip], ecx +.save_context_full_done_16bit_high_word: +%endif ; 16-bit + mov xAX, VAR_CALLER_AX + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rax], xAX + mov xCX, VAR_CALLER_CX + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rcx], xCX + mov xAX, VAR_CALLER_DX + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rdx], xAX + mov xAX, VAR_CALLER_BX + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rbx], xAX + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rsi], sSI + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rdi], sDI + mov xAX, VAR_CALLER_BP + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rbp], xAX +%if TMPL_BITS != 64 + mov ax, VAR_CALLER_DS + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ds], ax +%else + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ds], ds +%endif + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.es], es + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.fs], fs + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.gs], gs + mov xAX, [xBP + xCB] + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rip], xAX + mov ax, [xBP + xCB*2] + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.cs], ax +%if TMPL_MODE != BS3_MODE_RM + and al, X86_SEL_RPL + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.bCpl], al + cmp al, 0 + je .save_context_full_same + mov xAX, [xBP + xCB*4] + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rsp], xAX + mov ax, [xBP + xCB*5] + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ss], ax + jmp .save_context_full_done_stack +%else + mov byte [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.bCpl], 0 +%endif +.save_context_full_same: + mov xAX, xBP + add xAX, xCB * (1 + 3) + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rsp], xAX + mov ax, ss + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ss], ax +.save_context_full_done_stack: + mov xAX, [xBP + xCB*3] + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rflags], xAX + + mov al, VAR_CALLER_MODE + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.bMode], al +%if TMPL_BITS == 64 + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r8], r8 + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r9], r9 + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r10], r10 + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r11], r11 + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r12], r12 + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r13], r13 + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r14], r14 + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.r15], r15 +%endif + str [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.tr] + sldt [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ldtr] + mov sAX, cr0 + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.cr0], sAX + mov sAX, cr2 + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.cr2], sAX + mov sAX, cr3 + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.cr3], sAX +%if TMPL_BITS != 64 + test byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_CPUID >> 8) + jnz .have_cr4 + or byte [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR4 + jmp .done_cr4 +.have_cr4: +%endif + mov sAX, cr4 + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.cr4], sAX +%if TMPL_BITS != 64 +.done_cr4: + or byte [ss:xBX + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_AMD64 + + ; Deal with extended v8086 frame. + %if TMPL_BITS == 32 + test dword [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rflags], X86_EFL_VM + jz .save_context_full_return + %else + test byte VAR_CALLER_MODE, BS3_MODE_CODE_V86 + jz .save_context_full_return + mov dword [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rflags], X86_EFL_VM + %endif + mov xAX, [xBP + xCB*4] + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.rsp], xAX + mov ax, [xBP + xCB*5] + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ss], ax + mov ax, [xBP + xCB*6] + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.es], ax + mov ax, [xBP + xCB*7] + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.ds], ax + mov ax, [xBP + xCB*8] + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.fs], ax + mov ax, [xBP + xCB*9] + mov [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.gs], ax + mov byte [BS3_NOT_64BIT(ss:) xBX + BS3REGCTX.bCpl], 3 + jmp .save_context_full_return + +%endif ; !64-bit + +.save_context_full_return: + ret + +%if TMPL_BITS == 16 + CPU 286 +%endif + + ; + ; Internal function for converting a syscall pointer parameter (cx:xSI) + ; to a pointer we can use here in this context. + ; + ; Returns the result in cx:xSI. + ; @uses xAX, xCX, xDX + ; +.convert_ptr_arg_to_cx_xSI: + call .convert_ptr_arg_to_flat +%if TMPL_BITS == 16 + ; Convert to tiled address. + mov si, ax ; offset. + shl dx, X86_SEL_SHIFT + add dx, BS3_SEL_TILED + mov cx, dx +%else + ; Just supply a flat selector. + mov xSI, xAX + mov cx, ds +%endif + ret + + ; + ; Internal function for converting a syscall pointer parameter (caller CX:xSI) + ; to a real mode pointer. + ; + ; Returns the result in AX:SI. + ; @uses xAX, xCX, xDX + ; +.convert_ptr_arg_to_real_mode_ax_si: + call .convert_ptr_arg_to_flat + mov si, ax +%if TMPL_BITS == 16 + mov ax, dx +%else + shr eax, 16 +%endif + shl ax, 12 + ret + + ; + ; Internal function for the above that wraps the Bs3SelProtFar32ToFlat32 call. + ; + ; @returns eax (32-bit, 64-bit), dx+ax (16-bit). + ; @uses eax, ecx, edx + ; +.convert_ptr_arg_to_flat: +%if TMPL_BITS == 16 + ; Convert to (32-bit) flat address first. + test byte VAR_CALLER_MODE, BS3_MODE_CODE_V86 + jz .convert_ptr_arg_to_flat_prot_16 + + mov ax, VAR_CALLER_CX + mov dx, ax + shl ax, 4 + shr dx, 12 + add ax, VAR_CALLER_SI + adc dx, 0 + ret + +.convert_ptr_arg_to_flat_prot_16: + push es + push bx + push word VAR_CALLER_CX ; selector + xor ax, ax + test byte VAR_CALLER_MODE, BS3_MODE_CODE_16 + jnz .caller_is_16_bit + mov ax, VAR_CALLER_SI_HI +.caller_is_16_bit: + push ax ; offset high + push word VAR_CALLER_SI ; offset low + call Bs3SelProtFar32ToFlat32 + add sp, 2*3 + pop bx + pop es + ret + +%else ; 32 or 64 bit + test byte VAR_CALLER_MODE, BS3_MODE_CODE_V86 + jz .convert_ptr_arg_to_cx_xSI_prot + + ; Convert real mode address to flat address and return it. + movzx eax, word VAR_CALLER_CX + shl eax, 4 + movzx edx, word VAR_CALLER_SI + add eax, edx + ret + + ; Convert to (32-bit) flat address. +.convert_ptr_arg_to_cx_xSI_prot: + %if TMPL_BITS == 64 + push r11 + push r10 + push r9 + push r8 + sub rsp, 10h + %endif + movzx ecx, word VAR_CALLER_CX + push xCX + mov eax, VAR_CALLER_SI + test byte VAR_CALLER_MODE, BS3_MODE_CODE_16 + jz .no_masking_offset + and eax, 0ffffh +.no_masking_offset: + push xAX + BS3_CALL Bs3SelProtFar32ToFlat32,2 + add xSP, xCB*2 BS3_ONLY_64BIT(+ 10h) + %if TMPL_BITS == 64 + pop r8 + pop r9 + pop r10 + pop r11 + %endif +%endif + ret + +BS3_PROC_END_MODE Bs3TrapSystemCallHandler + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-rm-InitAll.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-rm-InitAll.c new file mode 100644 index 00000000..3d22fb5c --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-rm-InitAll.c @@ -0,0 +1,100 @@ +/* $Id: bs3-rm-InitAll.c $ */ +/** @file + * BS3Kit - Initialize all components, real mode. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +//#define BS3_USE_RM_TEXT_SEG 1 +#include "bs3kit-template-header.h" +#include "bs3-cmn-test.h" +#include <iprt/asm-amd64-x86.h> + +BS3_MODE_PROTO_NOSB(void, Bs3EnteredMode,(void)); + + +BS3_DECL(void) Bs3InitAll_rm(void) +{ + uint8_t volatile BS3_FAR *pcTicksFlpyOff; + + /* + * Detect CPU first as the memory init code will otherwise use 386 + * instrunctions and cause trouble on older CPUs. + */ + Bs3CpuDetect_rm_far(); + Bs3InitMemory_rm_far(); + Bs3InitGdt_rm_far(); + + /* + * Before we disable all interrupts, try convince the BIOS to stop the + * floppy motor, as it is kind of disturbing when the floppy light remains + * on for the whole testcase execution. + */ + ASMIntDisable(); /* (probably already disabled, but no guarantees) */ + pcTicksFlpyOff = (uint8_t volatile BS3_FAR *)BS3_FP_MAKE(0x40, 0x40); + if (*pcTicksFlpyOff) + { + uint32_t volatile BS3_FAR *pcTicks = (uint32_t volatile BS3_FAR *)BS3_FP_MAKE(0x40, 0x6c); + uint32_t cInitialTicks; + + *pcTicksFlpyOff = 1; /* speed up the countdown, don't want to wait for two seconds here. */ + cInitialTicks = *pcTicks; + ASMIntEnable(); + + while (*pcTicks == cInitialTicks) + ASMHalt(); + } + ASMIntDisable(); + Bs3PicSetup(false /*fForcedReInit*/); + + /* + * Initialize IDTs and such. + */ + if (g_uBs3CpuDetected & BS3CPU_F_LONG_MODE) + Bs3Trap64Init(); + if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386) + Bs3Trap32Init(); + if ((g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80286) + Bs3Trap16Init(); + Bs3TrapRmV86Init(); + + /* + * Perform a real-mode enter to make some final environment adjustments + * (like installing our syscall). + */ + Bs3EnteredMode_rm(); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-rm-InitGdt.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-rm-InitGdt.c new file mode 100644 index 00000000..9187875b --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-rm-InitGdt.c @@ -0,0 +1,71 @@ +/* $Id: bs3-rm-InitGdt.c $ */ +/** @file + * BS3Kit - Bs3InitGdt + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define BS3_USE_RM_TEXT_SEG 1 +#include "bs3kit-template-header.h" +#include <iprt/asm.h> + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ + + +BS3_DECL_FAR(void) Bs3InitGdt_rm_far(void) +{ +#if 0 /* This totaly messes us up when going back to raw-mode for BIOS work. */ + Bs3Gdte_R0_CS16.Gen.u16LimitLow = Bs3Text16_Size - 1; + Bs3Gdte_R1_CS16.Gen.u16LimitLow = Bs3Text16_Size - 1; + Bs3Gdte_R2_CS16.Gen.u16LimitLow = Bs3Text16_Size - 1; + Bs3Gdte_R3_CS16.Gen.u16LimitLow = Bs3Text16_Size - 1; +#endif + Bs3Gdte_RMTEXT16_CS.Gen.u16LimitLow = Bs3RmText16_Size - 1; + Bs3Gdte_X0TEXT16_CS.Gen.u16LimitLow = Bs3X0Text16_Size - 1; + Bs3Gdte_X1TEXT16_CS.Gen.u16LimitLow = Bs3X1Text16_Size - 1; + + Bs3Gdte_RMTEXT16_CS.Gen.u16BaseLow = (uint16_t)Bs3RmText16_FlatAddr; + Bs3Gdte_X0TEXT16_CS.Gen.u16BaseLow = (uint16_t)Bs3X0Text16_FlatAddr; + Bs3Gdte_X1TEXT16_CS.Gen.u16BaseLow = (uint16_t)Bs3X1Text16_FlatAddr; + + Bs3Gdte_RMTEXT16_CS.Gen.u8BaseHigh1 = (uint8_t)(Bs3RmText16_FlatAddr >> 16); + Bs3Gdte_X0TEXT16_CS.Gen.u8BaseHigh1 = (uint8_t)(Bs3X0Text16_FlatAddr >> 16); + Bs3Gdte_X1TEXT16_CS.Gen.u8BaseHigh1 = (uint8_t)(Bs3X1Text16_FlatAddr >> 16); +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-rm-InitMemory.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-rm-InitMemory.c new file mode 100644 index 00000000..7e3d4bd2 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-rm-InitMemory.c @@ -0,0 +1,317 @@ +/* $Id: bs3-rm-InitMemory.c $ */ +/** @file + * BS3Kit - Bs3InitMemory + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define BS3_USE_RM_TEXT_SEG 1 +#define BS3_BIOS_INLINE_RM +#include "bs3kit-template-header.h" +#include "bs3-cmn-memory.h" +#include <iprt/asm.h> +#include <VBox/VMMDevTesting.h> + + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +/** Slab control structure for the 4K management of low memory (< 1MB). */ +BS3SLABCTLLOW g_Bs3Mem4KLow; +/** Slab control structure for the 4K management of tiled upper memory, + * between 1 MB and 16MB. */ +BS3SLABCTLUPPERTILED g_Bs3Mem4KUpperTiled; + + +/** Translates a power of two request size to an slab list index. */ +uint8_t const g_aiBs3SlabListsByPowerOfTwo[12] = +{ + /* 2^0 = 1 */ 0, + /* 2^1 = 2 */ 0, + /* 2^2 = 4 */ 0, + /* 2^3 = 8 */ 0, + /* 2^4 = 16 */ 0, + /* 2^5 = 32 */ 1, + /* 2^6 = 64 */ 2, + /* 2^7 = 128 */ 3, + /* 2^8 = 256 */ 4, + /* 2^9 = 512 */ 5, + /* 2^10 = 1024 */ -1 + /* 2^11 = 2048 */ -1 +}; + +/** The slab list chunk sizes. */ +uint16_t const g_acbBs3SlabLists[BS3_MEM_SLAB_LIST_COUNT] = +{ + 16, + 32, + 64, + 128, + 256, + 512, +}; + +/** Low memory slab lists, sizes given by g_acbBs3SlabLists. */ +BS3SLABHEAD g_aBs3LowSlabLists[BS3_MEM_SLAB_LIST_COUNT]; +/** Upper tiled memory slab lists, sizes given by g_acbBs3SlabLists. */ +BS3SLABHEAD g_aBs3UpperTiledSlabLists[BS3_MEM_SLAB_LIST_COUNT]; + +/** Slab control structure sizes for the slab lists. + * This is to help the allocator when growing a list. */ +uint16_t const g_cbBs3SlabCtlSizesforLists[BS3_MEM_SLAB_LIST_COUNT] = +{ + RT_ALIGN(sizeof(BS3SLABCTL) - 4 + (4096 / 16 / 8 /*=32*/), 16), + RT_ALIGN(sizeof(BS3SLABCTL) - 4 + (4096 / 32 / 8 /*=16*/), 32), + RT_ALIGN(sizeof(BS3SLABCTL) - 4 + (4096 / 64 / 8 /*=8*/), 64), + RT_ALIGN(sizeof(BS3SLABCTL) - 4 + (4096 / 128 / 8 /*=4*/), 128), + RT_ALIGN(sizeof(BS3SLABCTL) - 4 + (4096 / 256 / 8 /*=2*/), 256), + RT_ALIGN(sizeof(BS3SLABCTL) - 4 + (4096 / 512 / 8 /*=1*/), 512), +}; + + +/** The end RAM address below 4GB (approximately). */ +uint32_t g_uBs3EndOfRamBelow4G = 0; +/** The end RAM address above 4GB, zero if no memory above 4GB. */ +uint64_t g_uBs3EndOfRamAbove4G = 0; + + +/** + * Adds a range of memory to the tiled slabs. + * + * @param uRange Start of range. + * @param cbRange Size of range. + */ +static void bs3InitMemoryAddRange32(uint32_t uRange, uint32_t cbRange) +{ + uint32_t uRangeEnd = uRange + cbRange; + if (uRangeEnd < uRange) + uRangeEnd = UINT32_MAX; + + /* Raise the end-of-ram-below-4GB marker? */ + if (uRangeEnd > g_uBs3EndOfRamBelow4G) + g_uBs3EndOfRamBelow4G = uRangeEnd; + + /* Applicable to tiled memory? */ + if ( uRange < BS3_SEL_TILED_AREA_SIZE + && ( uRange >= _1M + || uRangeEnd >= _1M)) + { + uint16_t cPages; + + /* Adjust the start of the range such that it's at or above 1MB and page aligned. */ + if (uRange < _1M) + { + cbRange -= _1M - uRange; + uRange = _1M; + } + else if (uRange & (_4K - 1U)) + { + cbRange -= uRange & (_4K - 1U); + uRange = RT_ALIGN_32(uRange, _4K); + } + + /* Adjust the end/size of the range such that it's page aligned and not beyond the tiled area. */ + if (uRangeEnd > BS3_SEL_TILED_AREA_SIZE) + { + cbRange -= uRangeEnd - BS3_SEL_TILED_AREA_SIZE; + uRangeEnd = BS3_SEL_TILED_AREA_SIZE; + } + else if (uRangeEnd & (_4K - 1U)) + { + cbRange -= uRangeEnd & (_4K - 1U); + uRangeEnd &= ~(uint32_t)(_4K - 1U); + } + + /* If there is still something, enable it. + (We're a bit paranoid here don't trust the BIOS to only report a page once.) */ + cPages = cbRange >> 12; /*div 4K*/ + if (cPages) + { + unsigned i; + uRange -= _1M; + i = uRange >> 12; /*div _4K*/ + while (cPages-- > 0) + { + uint16_t uLineToLong = ASMBitTestAndClear(g_Bs3Mem4KUpperTiled.Core.bmAllocated, i); + g_Bs3Mem4KUpperTiled.Core.cFreeChunks += uLineToLong; + i++; + } + } + } +} + + +BS3_DECL(void) BS3_FAR_CODE Bs3InitMemory_rm_far(void) +{ + INT15E820ENTRY Entry = { 0, 0, 0, 0 }; + uint32_t cbEntry = sizeof(Entry); + uint32_t uCont = 0; + uint16_t i; + uint16_t cPages; + uint32_t u32; + uint32_t BS3_FAR *pu32Mmio; + + /* + * Enable the A20 gate. + */ + Bs3A20Enable(); + + /* + * Low memory (4K chunks). + * - 0x00000 to 0x004ff - Interrupt Vector table, BIOS data area. + * - 0x01000 to 0x0ffff - Stacks. + * - 0x10000 to 0x1yyyy - BS3TEXT16 + * - 0x20000 to 0x26fff - BS3SYSTEM16 + * - 0x29000 to 0xzzzzz - BS3DATA16, BS3TEXT32, BS3TEXT64, BS3DATA32, BS3DATA64 (in that order). + * - 0xzzzzZ to 0x9fdff - Free conventional memory. + * - 0x9fc00 to 0x9ffff - Extended BIOS data area (exact start may vary). + * - 0xa0000 to 0xbffff - VGA MMIO + * - 0xc0000 to 0xc7fff - VGA BIOS + * - 0xc8000 to 0xeffff - ROMs, tables, unusable. + * - 0xf0000 to 0xfffff - PC BIOS. + */ + Bs3SlabInit(&g_Bs3Mem4KLow.Core, sizeof(g_Bs3Mem4KLow), 0 /*uFlatSlabPtr*/, 0xA0000 /* 640 KB*/, _4K); + + /* Mark the stacks and whole image as allocated. */ + cPages = (Bs3TotalImageSize + _4K - 1U) >> 12; + ASMBitSetRange(g_Bs3Mem4KLow.Core.bmAllocated, 0, 0x10 + cPages); + + /* Mark any unused pages between BS3TEXT16 and BS3SYSTEM16 as free. */ + cPages = (Bs3Text16_Size + (uint32_t)_4K - 1U) >> 12; + ASMBitClearRange(g_Bs3Mem4KLow.Core.bmAllocated, 0x10U + cPages, 0x20U); + + /* In case the system has less than 640KB of memory, check the BDA variable for it. */ + cPages = *(uint16_t BS3_FAR *)BS3_FP_MAKE(0x0000, 0x0413); /* KB of low memory */ + if (cPages < 640) + { + cPages = 640 - cPages; + cPages = RT_ALIGN(cPages, 4); + cPages >>= 2; + ASMBitSetRange(g_Bs3Mem4KLow.Core.bmAllocated, 0xA0 - cPages, 0xA0); + } + else + ASMBitSet(g_Bs3Mem4KLow.Core.bmAllocated, 0x9F); + + /* Recalc free pages. */ + cPages = 0; + i = g_Bs3Mem4KLow.Core.cChunks; + while (i-- > 0) + cPages += !ASMBitTest(g_Bs3Mem4KLow.Core.bmAllocated, i); + g_Bs3Mem4KLow.Core.cFreeChunks = cPages; + + /* + * First 16 MB of memory above 1MB. We start out by marking it all allocated. + */ + Bs3SlabInit(&g_Bs3Mem4KUpperTiled.Core, sizeof(g_Bs3Mem4KUpperTiled), _1M, BS3_SEL_TILED_AREA_SIZE - _1M, _4K); + + ASMBitSetRange(g_Bs3Mem4KUpperTiled.Core.bmAllocated, 0, g_Bs3Mem4KUpperTiled.Core.cChunks); + g_Bs3Mem4KUpperTiled.Core.cFreeChunks = 0; + + /* Ask the BIOS about where there's memory, and make pages in between 1MB + and BS3_SEL_TILED_AREA_SIZE present. This means we're only interested + in entries describing usable memory, ASSUMING of course no overlaps. */ + if ( (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80386 + && Bs3BiosInt15hE820_rm_far(&Entry, &cbEntry, &uCont)) + { + unsigned i = 0; + do + { + if (Entry.uType == INT15E820_TYPE_USABLE) + { + if (!(Entry.uBaseAddr >> 32)) + /* Convert from 64-bit to 32-bit value and record it. */ + bs3InitMemoryAddRange32((uint32_t)Entry.uBaseAddr, + (Entry.cbRange >> 32) ? UINT32_C(0xfffff000) : (uint32_t)Entry.cbRange); + else + { + uint64_t uEnd = Entry.uBaseAddr + Entry.cbRange; + if (uEnd > g_uBs3EndOfRamAbove4G) + g_uBs3EndOfRamAbove4G = uEnd; + } + } + + /* next */ + Entry.uType = 0; + cbEntry = sizeof(Entry); + i++; + } while ( uCont != 0 + && i < 2048 + && Bs3BiosInt15hE820_rm_far(&Entry, &cbEntry, &uCont)); + } + /* Try the 286+ API for getting memory above 1MB and (usually) below 16MB. */ + else if ( (g_uBs3CpuDetected & BS3CPU_TYPE_MASK) >= BS3CPU_80286 + && (u32 = Bs3BiosInt15h88()) != UINT32_MAX + && u32 > 0) + bs3InitMemoryAddRange32(_1M, u32 * _1K); + + /* + * Check if we've got the VMMDev MMIO testing memory mapped above 1MB. + */ + pu32Mmio = (uint32_t BS3_FAR *)BS3_FP_MAKE(VMMDEV_TESTING_MMIO_RM_SEL, + VMMDEV_TESTING_MMIO_RM_OFF2(VMMDEV_TESTING_MMIO_OFF_NOP)); + if (*pu32Mmio == VMMDEV_TESTING_NOP_RET) + { + Bs3Printf("Memory: Found VMMDev MMIO testing region\n"); + if (!ASMBitTestAndSet(g_Bs3Mem4KUpperTiled.Core.bmAllocated, 1)) + g_Bs3Mem4KUpperTiled.Core.cFreeChunks--; + + } + + /* + * Initialize the slab lists. + */ + for (i = 0; i < BS3_MEM_SLAB_LIST_COUNT; i++) + { + Bs3SlabListInit(&g_aBs3LowSlabLists[i], g_acbBs3SlabLists[i]); + Bs3SlabListInit(&g_aBs3UpperTiledSlabLists[i], g_acbBs3SlabLists[i]); + } + +#if 0 + /* + * For debugging. + */ + Bs3Printf("Memory-low: %u/%u chunks bmAllocated[]=", g_Bs3Mem4KLow.Core.cFreeChunks, g_Bs3Mem4KLow.Core.cChunks); + for (i = 0; i < 20; i++) + Bs3Printf("%02x ", g_Bs3Mem4KLow.Core.bmAllocated[i]); + Bs3Printf("\n"); + Bs3Printf("Memory-upt: %u/%u chunks bmAllocated[]=", g_Bs3Mem4KUpperTiled.Core.cFreeChunks, g_Bs3Mem4KUpperTiled.Core.cChunks); + for (i = 0; i < 32; i++) + Bs3Printf("%02x ", g_Bs3Mem4KUpperTiled.Core.bmAllocated[i]); + Bs3Printf("...\n"); +#endif +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-shutdown.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-shutdown.c new file mode 100644 index 00000000..58b64ca3 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-shutdown.c @@ -0,0 +1,87 @@ +/* $Id: bs3-shutdown.c $ */ +/** @file + * BS3Kit - Shutdown VM from PE16 - proof of concept (BS3Kit). + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "bs3kit.h" +#include <iprt/assert.h> +#include <iprt/asm-amd64-x86.h> + +AssertCompileSize(uint16_t, 2); +AssertCompileSize(uint32_t, 4); +AssertCompileSize(uint64_t, 8); + +extern uint16_t ASMGetMsw(); +#pragma aux ASMGetMsw = \ + ".286" \ + "smsw ax" \ + value [ax] \ + modify exact; + +extern void ASMSetMsw(uint16_t uMsw); +#pragma aux ASMSetMsw = \ + ".286p" \ + "lmsw ax" \ + parm [ax] \ + modify exact; + +/* Just a sample. */ +BS3_DECL(void) Main_pe16(void) +{ + uint16_t uMsw = ASMGetMsw(); + Bs3Printf("msw=%#x cr0=%RX32 g_uBs3CpuDetected=%#x\n", uMsw, ASMGetCR0(), g_uBs3CpuDetected); + Bs3Printf("cr2=%RX32 cr3=%RX32\n", ASMGetCR2(), ASMGetCR3()); + ASMSetMsw(X86_CR0_PE); + Bs3Printf("lmsw(PE) => msw=%#x cr0=%RX32\n", ASMGetMsw(), ASMGetCR0()); + ASMSetMsw(UINT16_MAX); + Bs3Printf("lmsw(0xffff) => msw=%#x cr0=%RX32\n", ASMGetMsw(), ASMGetCR0()); + ASMSetCR0(X86_CR0_PE); + Bs3Printf("ASMSetCR0(X86_CR0_PE) => msw=%#x cr0=%RX32\n", ASMGetMsw(), ASMGetCR0()); + ASMSetCR0(UINT32_C(0x7fffffff)); + Bs3Printf("ASMSetCR0(0x7fffffff) => msw=%#x cr0=%RX32\n", ASMGetMsw(), ASMGetCR0()); + + Bs3TestInit("bs3-shutdown"); + Bs3TestPrintf("detected cpu: %#x\n", g_uBs3CpuDetected); +#if 1 + ASMHalt(); +#else + Bs3Shutdown(); +#endif + return; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-system-data.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-system-data.asm new file mode 100644 index 00000000..6be79dc9 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-system-data.asm @@ -0,0 +1,1056 @@ +; $Id: bs3-system-data.asm $ +;; @file +; BS3Kit - GDT +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit.mac" + +%define BS3_SYSTEM16_BASE_16_23 ((BS3_ADDR_BS3SYSTEM16 >> 16) & 0xff) +%define BS3_SYSTEM16_BASE_LOW(a_DataSym) ((BS3_DATA_NM(a_DataSym) - StartSystem16) & 0xffff) + +;; +; The GDT (X86DESCGENERIC). +; +BS3_BEGIN_SYSTEM16 +StartSystem16: + db 10, 13, 'eye-catcher: SYSTEM16.......', 10, 13 ; 32 bytes long +BS3_GLOBAL_DATA Bs3Gdt, 4000h - 20h + +;; Macro for checking GDT offsets as we go along. +;; @param %1 The expected current offset. +%macro BS3GdtAssertOffset 1 + %ifndef KBUILD_GENERATING_MAKEFILE_DEPENDENCIES + %if ($ - BS3_DATA_NM(Bs3Gdt)) != %1 + %assign offActual ($ - BS3_DATA_NM(Bs3Gdt)) + %error "BS3GdtAssertOffset: Bad offset: " %+ offActual %+ ", expected " %+ %1 + %endif + %endif +%endmacro + + dw 00000h, 00000h, 00000h, 00000h ; null selector +BS3GdtAssertOffset 8 + + ; + ; 008h..0f8h - System selectors and other stuff + ; + dw 00000h, 00000h, 00000h, 00000h ; Entry 008h - currently unused + +BS3_GLOBAL_DATA Bs3Gdte_Ldt, 16 ; Entry 010h + dw BS3_DATA_NM(Bs3LdtEnd) - BS3_DATA_NM(Bs3Ldt) - 1 + dw BS3_SYSTEM16_BASE_LOW(Bs3Ldt) + db BS3_SYSTEM16_BASE_16_23 + db X86_SEL_TYPE_SYS_LDT | 0x80 + dw 00000h + dw 00000h, 00000h, 00000h, 00000h ; zero for 64-bit mode. + +BS3_GLOBAL_DATA Bs3Gdte_Tss16, 8 ; Entry 020h + dw 0002bh ; 16-bit TSS. + dw BS3_SYSTEM16_BASE_LOW(Bs3Tss16) + db BS3_SYSTEM16_BASE_16_23 + db X86_SEL_TYPE_SYS_286_TSS_AVAIL | 0x80 + dw 0 + +BS3_GLOBAL_DATA Bs3Gdte_Tss16DoubleFault, 8 ; Entry 028h + dw 0002bh ; 16-bit TSS, double fault. + dw BS3_SYSTEM16_BASE_LOW(Bs3Tss16DoubleFault) + db BS3_SYSTEM16_BASE_16_23 + db X86_SEL_TYPE_SYS_286_TSS_AVAIL | 0x80 + dw 0 + +BS3_GLOBAL_DATA Bs3Gdte_Tss16Spare0, 8 ; Entry 030h + dw 0002bh ; 16-bit TSS, spare 0. + dw BS3_SYSTEM16_BASE_LOW(Bs3Tss16Spare0) + db BS3_SYSTEM16_BASE_16_23 + db X86_SEL_TYPE_SYS_286_TSS_AVAIL | 0x80 + dw 0 + +BS3_GLOBAL_DATA Bs3Gdte_Tss16Spare1, 8 ; Entry 038h + dw 0002bh ; 16-bit TSS, spare 0. + dw BS3_SYSTEM16_BASE_LOW(Bs3Tss16Spare1) + db BS3_SYSTEM16_BASE_16_23 + db X86_SEL_TYPE_SYS_286_TSS_AVAIL | 0x80 + dw 0 + +BS3_GLOBAL_DATA Bs3Gdte_Tss32, 8 ; Entry 040h + dw 00067h ; 32-bit TSS. + dw BS3_SYSTEM16_BASE_LOW(Bs3Tss32) + db BS3_SYSTEM16_BASE_16_23 + db X86_SEL_TYPE_SYS_386_TSS_AVAIL | 0x80 + dw 0 + +BS3_GLOBAL_DATA Bs3Gdte_Tss32DoubleFault, 8 ; Entry 048h + dw 00067h ; 32-bit TSS, double fault. + dw BS3_SYSTEM16_BASE_LOW(Bs3Tss32DoubleFault) + db BS3_SYSTEM16_BASE_16_23 + db X86_SEL_TYPE_SYS_386_TSS_AVAIL | 0x80 + dw 0 + +BS3_GLOBAL_DATA Bs3Gdte_Tss32Spare0, 8 ; Entry 050h + dw 00067h ; 32-bit TSS, spare 0. + dw BS3_SYSTEM16_BASE_LOW(Bs3Tss32Spare0) + db BS3_SYSTEM16_BASE_16_23 + db X86_SEL_TYPE_SYS_386_TSS_AVAIL | 0x80 + dw 0 + +BS3_GLOBAL_DATA Bs3Gdte_Tss32Spare1, 8 ; Entry 058h + dw 00067h ; 32-bit TSS, spare 1. + dw BS3_SYSTEM16_BASE_LOW(Bs3Tss32Spare1) + db BS3_SYSTEM16_BASE_16_23 + db X86_SEL_TYPE_SYS_386_TSS_AVAIL | 0x80 + dw 0 + +BS3_GLOBAL_DATA Bs3Gdte_Tss32IobpIntRedirBm, 8 ; Entry 060h + ; 32-bit TSS, with I/O permission & interrupt redirection bitmaps. + dw BS3_DATA_NM(Bs3SharedIobpEnd) - BS3_DATA_NM(Bs3Tss32WithIopb) - 1 + dw BS3_SYSTEM16_BASE_LOW(Bs3Tss32WithIopb) + db BS3_SYSTEM16_BASE_16_23 + db X86_SEL_TYPE_SYS_386_TSS_AVAIL | 0x80 + dw 0 + +BS3_GLOBAL_DATA Bs3Gdte_Tss32IntRedirBm, 8 ; Entry 068h + ; 32-bit TSS, with interrupt redirection bitmap (IOBP stripped by limit). + dw BS3_DATA_NM(Bs3SharedIobp) - BS3_DATA_NM(Bs3Tss32WithIopb) - 1 + dw BS3_SYSTEM16_BASE_LOW(Bs3Tss32WithIopb) + db BS3_SYSTEM16_BASE_16_23 + db X86_SEL_TYPE_SYS_386_TSS_AVAIL | 0x80 + dw 0 + +BS3_GLOBAL_DATA Bs3Gdte_Tss64, 8 ; Entry 070h + dw 00067h ; 64-bit TSS. + dw BS3_SYSTEM16_BASE_LOW(Bs3Tss64) + db BS3_SYSTEM16_BASE_16_23 + db AMD64_SEL_TYPE_SYS_TSS_AVAIL | 0x80 + dw 0 + dw 00000h, 00000h, 00000h, 00000h + +BS3_GLOBAL_DATA Bs3Gdte_Tss64Spare0, 8 ; Entry 080h + dw 00067h ; 64-bit TSS, spare 0. + dw BS3_SYSTEM16_BASE_LOW(Bs3Tss64Spare0) + db BS3_SYSTEM16_BASE_16_23 + db AMD64_SEL_TYPE_SYS_TSS_AVAIL | 0x80 + dw 0 + dw 00000h, 00000h, 00000h, 00000h + +BS3_GLOBAL_DATA Bs3Gdte_Tss64Spare1, 8 ; Entry 090h + dw 00067h ; 64-bit TSS, spare 1. + dw BS3_SYSTEM16_BASE_LOW(Bs3Tss64Spare1) + db BS3_SYSTEM16_BASE_16_23 + db AMD64_SEL_TYPE_SYS_TSS_AVAIL | 0x80 + dw 0 + dw 00000h, 00000h, 00000h, 00000h + +BS3_GLOBAL_DATA Bs3Gdte_Tss64Iobp, 8 ; Entry 0a0h + ; 64-bit TSS, with I/O permission bitmap + dw BS3_DATA_NM(Bs3SharedIobp) - BS3_DATA_NM(Bs3Tss64WithIopb) - 1 + dw BS3_SYSTEM16_BASE_LOW(Bs3Tss64WithIopb) + db BS3_SYSTEM16_BASE_16_23 + db AMD64_SEL_TYPE_SYS_TSS_AVAIL | 0x80 + dw 0 + dw 00000h, 00000h, 00000h, 00000h + +BS3GdtAssertOffset 0b0h + dw 00000h, 00000h, 00000h, 00000h ; Entry 0b0h - currently unused + dw 00000h, 00000h, 00000h, 00000h ; Entry 0b8h - currently unused + dw 00000h, 00000h, 00000h, 00000h ; Entry 0c0h - currently unused + dw 00000h, 00000h, 00000h, 00000h ; Entry 0c8h - currently unused + dw 00000h, 00000h, 00000h, 00000h ; Entry 0d0h - currently unused + dw 00000h, 00000h, 00000h, 00000h ; Entry 0d8h - currently unused + + ; Misc selectors. +BS3_GLOBAL_DATA Bs3Gdte_RMTEXT16_CS, 8 ; Entry 0e0h + dw 0fffeh, 00000h ; 16-bit conforming code (read+exec) segment, accessed. Will be finalized at startup. + dw 09f00h, 00000h +BS3_GLOBAL_DATA Bs3Gdte_X0TEXT16_CS, 8 ; Entry 0e8h + dw 0fffeh, 00000h ; 16-bit conforming code (read+exec) segment, accessed. Will be finalized at startup. + dw 09f00h, 00000h +BS3_GLOBAL_DATA Bs3Gdte_X1TEXT16_CS, 8 ; Entry 0f0h + dw 0fffeh, 00000h ; 16-bit conforming code (read+exec) segment, accessed. Will be finalized at startup. + dw 09f00h, 00000h +BS3_GLOBAL_DATA Bs3Gdte_R0_MMIO16, 8 ; Entry 0f8h + dw 0ffffh, 0f000h, 0930dh, 00000h ; 16-bit VMMDev MMIO segment with base 0df000h. +BS3GdtAssertOffset 0100h + + +;; +; Macro that defines the selectors for ring-%1. +; +%macro BS3_GDT_RING_X_SELECTORS 1 +BS3_GLOBAL_DATA Bs3Gdte_R %+ %1 %+ _First, 80h +BS3_GLOBAL_DATA Bs3Gdte_R %+ %1 %+ _CS16, 8 ; Entry 100h + dw 0ffffh, (0xffff & BS3_ADDR_BS3TEXT16) ; 16-bit code segment with base 010000h. + dw 09b01h | (%1 << 0dh) | (0xff & (BS3_ADDR_BS3TEXT16 >> 16)), 00000h | (0xff00 & (BS3_ADDR_BS3TEXT16 >> 16)) + +BS3_GLOBAL_DATA Bs3Gdte_R %+ %1 %+ _DS16, 8 ; Entry 108h + dw 0ffffh, (0xffff & BS3_ADDR_BS3DATA16) ; 16-bit data segment with base 029000h. + dw 09300h | (%1 << 0dh) | (0xff & (BS3_ADDR_BS3DATA16 >> 16)), 00000h | (0xff00 & (BS3_ADDR_BS3DATA16 >> 16)) + +BS3_GLOBAL_DATA Bs3Gdte_R %+ %1 %+ _SS16, 8 ; Entry 110h + dw 0ffffh, 00000h ; 16-bit stack segment with base 0. + dw 09300h | (%1 << 0dh), 00000h + +BS3_GLOBAL_DATA Bs3Gdte_R %+ %1 %+ _CS32, 8 ; Entry 118h + dw 0ffffh, 00000h ; 32-bit flat code segment. + dw 09b00h | (%1 << 0dh), 000cfh + +BS3_GLOBAL_DATA Bs3Gdte_R %+ %1 %+ _DS32, 8 ; Entry 120h + dw 0ffffh, 00000h ; 32-bit flat data segment. + dw 09300h | (%1 << 0dh), 000cfh + +BS3_GLOBAL_DATA Bs3Gdte_R %+ %1 %+ _SS32, 8 ; Entry 128h + dw 0ffffh, 00000h ; 32-bit flat stack segment. + dw 09300h | (%1 << 0dh), 000cfh + +BS3_GLOBAL_DATA Bs3Gdte_R %+ %1 %+ _CS64, 8 ; Entry 130h + dw 0ffffh, 00000h ; 64-bit code segment. + dw 09a00h | (%1 << 0dh), 000afh + +BS3_GLOBAL_DATA Bs3Gdte_R %+ %1 %+ _DS64, 8 ; Entry 138h (also SS64) + dw 0ffffh, 00000h ; 64-bit stack and data segment. + dw 09300h | (%1 << 0dh), 000afh + +BS3_GLOBAL_DATA Bs3Gdte_R %+ %1 %+ _CS16_EO, 8 ; Entry 140h + dw 0ffffh, (0xffff & BS3_ADDR_BS3TEXT16) ; 16-bit code segment with base 01000h, not accessed, execute only, short limit. + dw 09800h | (%1 << 0dh) | (0xff & (BS3_ADDR_BS3TEXT16 >> 16)), 00000h | (0xff00 & (BS3_ADDR_BS3TEXT16 >> 16)) + +BS3_GLOBAL_DATA Bs3Gdte_R %+ %1 %+ _CS16_CNF, 8 ; Entry 148h + dw 0ffffh, (0xffff & BS3_ADDR_BS3TEXT16) ; 16-bit code segment with base 01000h, not accessed, execute only, short limit. + dw 09e00h | (%1 << 0dh) | (0xff & (BS3_ADDR_BS3TEXT16 >> 16)), 00000h | (0xff00 & (BS3_ADDR_BS3TEXT16 >> 16)) + +BS3_GLOBAL_DATA Bs3Gdte_R %+ %1 %+ _CS16_CND_EO, 8 ; Entry 150h + dw 0fffeh, 00000h ; 16-bit conforming code segment with base 0, not accessed, execute only, short limit. + dw 09c00h | (%1 << 0dh), 000cfh + +BS3_GLOBAL_DATA Bs3Gdte_R %+ %1 %+ _CS32_EO, 8 ; Entry 158h + dw 0ffffh, 00000h ; 32-bit flat code segment, not accessed, execute only. + dw 09800h | (%1 << 0dh), 000cfh + +BS3_GLOBAL_DATA Bs3Gdte_R %+ %1 %+ _CS32_CNF, 8 ; Entry 160h + dw 0ffffh, 00000h ; 32-bit flat conforming code segment, not accessed. + dw 09e00h | (%1 << 0dh), 000cfh + +BS3_GLOBAL_DATA Bs3Gdte_R %+ %1 %+ _CS32_CNF_EO, 8 ; Entry 168h + dw 0ffffh, 00000h ; 32-bit flat conforming code segment, not accessed, execute only. + dw 09c00h | (%1 << 0dh), 000cfh + +BS3_GLOBAL_DATA Bs3Gdte_R %+ %1 %+ _CS64_EO, 8 ; Entry 170h + dw 0ffffh, 00000h ; 64-bit code segment, not accessed, execute only. + dw 09800h | (%1 << 0dh), 000afh + +BS3_GLOBAL_DATA Bs3Gdte_R %+ %1 %+ _CS64_CNF, 8 ; Entry 178h + dw 0ffffh, 00000h ; 64-bit conforming code segment, not accessed. + dw 09e00h | (%1 << 0dh), 000afh + +BS3_GLOBAL_DATA Bs3Gdte_R %+ %1 %+ _CS64_CNF_EO, 8 ; Entry 180h + dw 0ffffh, 00000h ; 64-bit conforming code segment, execute only, not accessed. + dw 09c00h | (%1 << 0dh), 000afh + +;; @todo expand down segments. + dw 00000h, 00000h, 00000h, 00000h ; Entry 188h - unused. + dw 00000h, 00000h, 00000h, 00000h ; Entry 190h - unused. + dw 00000h, 00000h, 00000h, 00000h ; Entry 198h - unused. + dw 00000h, 00000h, 00000h, 00000h ; Entry 1a0h - unused. + dw 00000h, 00000h, 00000h, 00000h ; Entry 1a8h - unused. + dw 00000h, 00000h, 00000h, 00000h ; Entry 1b0h - unused. + dw 00000h, 00000h, 00000h, 00000h ; Entry 1b8h - unused. + dw 00000h, 00000h, 00000h, 00000h ; Entry 1c0h - unused. + dw 00000h, 00000h, 00000h, 00000h ; Entry 1c8h - unused. + dw 00000h, 00000h, 00000h, 00000h ; Entry 1d0h - unused. + dw 00000h, 00000h, 00000h, 00000h ; Entry 1d8h - unused. + dw 00000h, 00000h, 00000h, 00000h ; Entry 1e0h - unused. + dw 00000h, 00000h, 00000h, 00000h ; Entry 1e8h - unused. + dw 00000h, 00000h, 00000h, 00000h ; Entry 1f0h - unused. + dw 00000h, 00000h, 00000h, 00000h ; Entry 1f8h - unused. +%endmacro + + ; + ; 100h..1f8h - Ring-0 selectors. + ; + BS3_GDT_RING_X_SELECTORS 0 + + ; + ; 200h..2f8h - Ring-1 selectors. + ; + BS3_GDT_RING_X_SELECTORS 1 + + ; + ; 300h..3f8h - Ring-2 selectors. + ; + BS3_GDT_RING_X_SELECTORS 2 + + ; + ; 400h..4f8h - Ring-3 selectors. + ; + BS3_GDT_RING_X_SELECTORS 3 + + ; + ; 500..5f8h - Named spare GDT entries. + ; +BS3GdtAssertOffset 0500h +BS3_GLOBAL_DATA Bs3GdteSpare00, 8 ; Entry 500h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare01, 8 ; Entry 508h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare02, 8 ; Entry 510h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare03, 8 ; Entry 518h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare04, 8 ; Entry 520h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare05, 8 ; Entry 528h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare06, 8 ; Entry 530h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare07, 8 ; Entry 538h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare08, 8 ; Entry 540h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare09, 8 ; Entry 548h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare0a, 8 ; Entry 550h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare0b, 8 ; Entry 558h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare0c, 8 ; Entry 560h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare0d, 8 ; Entry 568h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare0e, 8 ; Entry 570h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare0f, 8 ; Entry 578h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare10, 8 ; Entry 580h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare11, 8 ; Entry 588h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare12, 8 ; Entry 590h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare13, 8 ; Entry 598h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare14, 8 ; Entry 5a0h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare15, 8 ; Entry 5a8h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare16, 8 ; Entry 5b0h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare17, 8 ; Entry 5b8h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare18, 8 ; Entry 5c0h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare19, 8 ; Entry 5c8h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare1a, 8 ; Entry 5d0h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare1b, 8 ; Entry 5d8h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare1c, 8 ; Entry 5e0h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare1d, 8 ; Entry 5e8h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare1e, 8 ; Entry 5f0h + dq 0 +BS3_GLOBAL_DATA Bs3GdteSpare1f, 8 ; Entry 5f8h + dq 0 + + ; + ; 600..df8h - 16-bit DPL=3 data segments covering the first 16MB of memory. + ; +BS3_GLOBAL_DATA Bs3GdteTiled, 8 ; Entry 600h +%assign u8HighBase 0 +%rep 256 + dw 0ffffh, 00000h, 0f300h | u8HighBase, 00000h +%assign u8HighBase u8HighBase + 1 +%endrep + ; + ; e00..ff8h - Free GDTEs. + ; +BS3GdtAssertOffset 0e00h +BS3_GLOBAL_DATA Bs3GdteFreePart1, 200h + times 200h db 0 + + ; + ; 1000h - the real mode segment number for BS3TEXT16. DPL=0, BASE=0x10000h, conforming, exec, read. + ; +BS3GdtAssertOffset 01000h +BS3_GLOBAL_DATA Bs3Gdte_CODE16, 8h + dw 0ffffh, 00000h, 09f01h, 00000h + + ; + ; 1008..17f8h - Free GDTEs. + ; +BS3GdtAssertOffset 01008h +BS3_GLOBAL_DATA Bs3GdteFreePart2, 07f8h + times 07f8h db 0 + + ; + ; 1800..1ff8h - 16-bit DPL=0 data/stack segments covering the first 16MB of memory. + ; +BS3GdtAssertOffset 01800h +BS3_GLOBAL_DATA Bs3GdteTiledR0, 8 ; Entry 1800h +%assign u8HighBase 0 +%rep 256 + dw 0ffffh, 00000h, 09300h | u8HighBase, 00000h +%assign u8HighBase u8HighBase + 1 +%endrep + + ; + ; 2000h - the real mode segment number for BS3SYSTEM. DPL=3. BASE=0x20000h + ; +BS3GdtAssertOffset 02000h +BS3_GLOBAL_DATA Bs3Gdte_SYSTEM16, 8h + dw 0ffffh, 00000h, 0f302h, 00000h + + ; + ; 2008..28f8h - Free GDTEs. + ; +BS3_GLOBAL_DATA Bs3GdteFreePart3, 08f8h + times 08f8h db 0 + + ; + ; 2900h - the real mode segment number for BS3KIT_GRPNM_DATA16. DPL=3. BASE=0x29000h + ; +BS3GdtAssertOffset 02900h +BS3_GLOBAL_DATA Bs3Gdte_DATA16, 8h + dw 0ffffh, 09000h, 0f302h, 00000h + + ; + ; 2908..2f98h - Free GDTEs. + ; +BS3GdtAssertOffset 02908h +BS3_GLOBAL_DATA Bs3GdteFreePart4, 698h + times 698h db 0 + + ; + ; 2be0..2fe0h - 8 spare entries preceeding the test page which we're free + ; to mess with page table protection. + ; +BS3GdtAssertOffset 02fa0h +BS3_GLOBAL_DATA Bs3GdtePreTestPage08, 8 + dq 0 +BS3_GLOBAL_DATA Bs3GdtePreTestPage07, 8 + dq 0 +BS3_GLOBAL_DATA Bs3GdtePreTestPage06, 8 + dq 0 +BS3_GLOBAL_DATA Bs3GdtePreTestPage05, 8 + dq 0 +BS3_GLOBAL_DATA Bs3GdtePreTestPage04, 8 + dq 0 +BS3_GLOBAL_DATA Bs3GdtePreTestPage03, 8 + dq 0 +BS3_GLOBAL_DATA Bs3GdtePreTestPage02, 8 + dq 0 +BS3_GLOBAL_DATA Bs3GdtePreTestPage01, 8 + dq 0 + + ; + ; 2fe0..3fd8h - 16 Test entries at the start of the page where we're free + ; to mess with page table protection. + ; +BS3GdtAssertOffset 02fe0h +AssertCompile(($ - $$) == 0x3000) +BS3_GLOBAL_DATA Bs3GdteTestPage, 0 +BS3_GLOBAL_DATA Bs3GdteTestPage00, 8 + dq 0 +BS3_GLOBAL_DATA Bs3GdteTestPage01, 8 + dq 0 +BS3_GLOBAL_DATA Bs3GdteTestPage02, 8 + dq 0 +BS3_GLOBAL_DATA Bs3GdteTestPage03, 8 + dq 0 +BS3_GLOBAL_DATA Bs3GdteTestPage04, 8 + dq 0 +BS3_GLOBAL_DATA Bs3GdteTestPage05, 8 + dq 0 +BS3_GLOBAL_DATA Bs3GdteTestPage06, 8 + dq 0 +BS3_GLOBAL_DATA Bs3GdteTestPage07, 8 + dq 0 +BS3GdtAssertOffset 3020h + times 0fb8h db 0 +BS3GdtAssertOffset 3fd8h +BS3_GLOBAL_DATA Bs3GdtEnd, 0 + db 10, 13, 'GDTE', 10, 13 ; alignment padding (next address on 16 byte boundrary). +BS3GdtAssertOffset 4000h - 20h ; We're at a page boundrary here! Only GDT and eyecatchers on page starting at 3000h! +AssertCompile(($ - $$) == 0x4000) + + + +;; +; The 16-bit TSS. +; +BS3_GLOBAL_DATA Bs3Tss16, X86TSS16_size +istruc X86TSS16 + at X86TSS16.selPrev, dw 0 + at X86TSS16.sp0, dw BS3_ADDR_STACK_R0 + at X86TSS16.ss0, dw BS3_SEL_R0_SS16 + at X86TSS16.sp1, dw BS3_ADDR_STACK_R1 + at X86TSS16.ss1, dw BS3_SEL_R1_SS16 + at X86TSS16.sp2, dw BS3_ADDR_STACK_R2 + at X86TSS16.ss2, dw BS3_SEL_R2_SS16 + at X86TSS16.ip, dw 0 + at X86TSS16.flags, dw 0 + at X86TSS16.ax, dw 0 + at X86TSS16.cx, dw 0 + at X86TSS16.dx, dw 0 + at X86TSS16.bx, dw 0 + at X86TSS16.sp, dw 0 + at X86TSS16.bp, dw 0 + at X86TSS16.si, dw 0 + at X86TSS16.di, dw 0 + at X86TSS16.es, dw 0 + at X86TSS16.cs, dw 0 + at X86TSS16.ss, dw 0 + at X86TSS16.ds, dw 0 + at X86TSS16.selLdt, dw 0 +iend + +;; +; 16-bit TSS for (trying to) handle double faults. +BS3_GLOBAL_DATA Bs3Tss16DoubleFault, X86TSS16_size +istruc X86TSS16 + at X86TSS16.selPrev, dw 0 + at X86TSS16.sp0, dw BS3_ADDR_STACK_R0 + at X86TSS16.ss0, dw BS3_SEL_R0_SS16 + at X86TSS16.sp1, dw BS3_ADDR_STACK_R1 + at X86TSS16.ss1, dw BS3_SEL_R1_SS16 + at X86TSS16.sp2, dw BS3_ADDR_STACK_R2 + at X86TSS16.ss2, dw BS3_SEL_R2_SS16 + at X86TSS16.ip, dw 0 ; Will be filled in by routine setting up 16-bit mode w/ traps++. + at X86TSS16.flags, dw X86_EFL_1 + at X86TSS16.ax, dw 0 + at X86TSS16.cx, dw 0 + at X86TSS16.dx, dw 0 + at X86TSS16.bx, dw 0 + at X86TSS16.sp, dw BS3_ADDR_STACK_R0_IST1 + at X86TSS16.bp, dw 0 + at X86TSS16.si, dw 0 + at X86TSS16.di, dw 0 + at X86TSS16.es, dw BS3_SEL_R0_DS16 + at X86TSS16.cs, dw BS3_SEL_R0_CS16 + at X86TSS16.ss, dw BS3_SEL_R0_SS16 + at X86TSS16.ds, dw BS3_SEL_R0_DS16 + at X86TSS16.selLdt, dw 0 +iend + +;; +; A spare 16-bit TSS for testcases to play around with. +BS3_GLOBAL_DATA Bs3Tss16Spare0, X86TSS16_size +istruc X86TSS16 + at X86TSS16.selPrev, dw 0 + at X86TSS16.sp0, dw BS3_ADDR_STACK_R0 + at X86TSS16.ss0, dw BS3_SEL_R0_SS16 + at X86TSS16.sp1, dw BS3_ADDR_STACK_R1 + at X86TSS16.ss1, dw BS3_SEL_R1_SS16 + at X86TSS16.sp2, dw BS3_ADDR_STACK_R2 + at X86TSS16.ss2, dw BS3_SEL_R2_SS16 + at X86TSS16.ip, dw 0 ; Will be filled in by routine setting up 16-bit mode w/ traps++. + at X86TSS16.flags, dw X86_EFL_1 + at X86TSS16.ax, dw 0 + at X86TSS16.cx, dw 0 + at X86TSS16.dx, dw 0 + at X86TSS16.bx, dw 0 + at X86TSS16.sp, dw BS3_ADDR_STACK_R0_IST2 + at X86TSS16.bp, dw 0 + at X86TSS16.si, dw 0 + at X86TSS16.di, dw 0 + at X86TSS16.es, dw BS3_SEL_R0_DS16 + at X86TSS16.cs, dw BS3_SEL_R0_CS16 + at X86TSS16.ss, dw BS3_SEL_R0_SS16 + at X86TSS16.ds, dw BS3_SEL_R0_DS16 + at X86TSS16.selLdt, dw 0 +iend + +;; +; A spare 16-bit TSS for testcases to play around with. +BS3_GLOBAL_DATA Bs3Tss16Spare1, X86TSS16_size +istruc X86TSS16 + at X86TSS16.selPrev, dw 0 + at X86TSS16.sp0, dw BS3_ADDR_STACK_R0 + at X86TSS16.ss0, dw BS3_SEL_R0_SS16 + at X86TSS16.sp1, dw BS3_ADDR_STACK_R1 + at X86TSS16.ss1, dw BS3_SEL_R1_SS16 + at X86TSS16.sp2, dw BS3_ADDR_STACK_R2 + at X86TSS16.ss2, dw BS3_SEL_R2_SS16 + at X86TSS16.ip, dw 0 ; Will be filled in by routine setting up 16-bit mode w/ traps++. + at X86TSS16.flags, dw X86_EFL_1 + at X86TSS16.ax, dw 0 + at X86TSS16.cx, dw 0 + at X86TSS16.dx, dw 0 + at X86TSS16.bx, dw 0 + at X86TSS16.sp, dw BS3_ADDR_STACK_R0_IST4 + at X86TSS16.bp, dw 0 + at X86TSS16.si, dw 0 + at X86TSS16.di, dw 0 + at X86TSS16.es, dw BS3_SEL_R0_DS16 + at X86TSS16.cs, dw BS3_SEL_R0_CS16 + at X86TSS16.ss, dw BS3_SEL_R0_SS16 + at X86TSS16.ds, dw BS3_SEL_R0_DS16 + at X86TSS16.selLdt, dw 0 +iend + + +;; +; The 32-bit TSS. +; +BS3_GLOBAL_DATA Bs3Tss32, X86TSS32_size +istruc X86TSS32 + at X86TSS32.selPrev, dw 0 + at X86TSS32.padding1, dw 0 + at X86TSS32.esp0, dd BS3_ADDR_STACK_R0 + at X86TSS32.ss0, dw BS3_SEL_R0_SS32 + at X86TSS32.padding_ss0, dw 1 + at X86TSS32.esp1, dd 1 + at X86TSS32.ss1, dw BS3_SEL_R1_SS32 + at X86TSS32.padding_ss1, dw 1 + at X86TSS32.esp2, dd 1 + at X86TSS32.ss2, dw BS3_SEL_R2_SS32 + at X86TSS32.padding_ss2, dw 1 + at X86TSS32.cr3, dd 0 + at X86TSS32.eip, dd 0 + at X86TSS32.eflags, dd X86_EFL_1 + at X86TSS32.eax, dd 0 + at X86TSS32.ecx, dd 0 + at X86TSS32.edx, dd 0 + at X86TSS32.ebx, dd 0 + at X86TSS32.esp, dd 0 + at X86TSS32.ebp, dd 0 + at X86TSS32.esi, dd 0 + at X86TSS32.edi, dd 0 + at X86TSS32.es, dw 0 + at X86TSS32.padding_es, dw 0 + at X86TSS32.cs, dw 0 + at X86TSS32.padding_cs, dw 0 + at X86TSS32.ss, dw 0 + at X86TSS32.padding_ss, dw 0 + at X86TSS32.ds, dw 0 + at X86TSS32.padding_ds, dw 0 + at X86TSS32.fs, dw 0 + at X86TSS32.padding_fs, dw 0 + at X86TSS32.gs, dw 0 + at X86TSS32.padding_gs, dw 0 + at X86TSS32.selLdt, dw 0 + at X86TSS32.padding_ldt, dw 0 + at X86TSS32.fDebugTrap, dw 0 + at X86TSS32.offIoBitmap, dw (BS3_DATA_NM(Bs3SharedIobp) - BS3_DATA_NM(Bs3Tss32WithIopb)) +iend + +;; +; The 32-bit TSS for handling double faults. +BS3_GLOBAL_DATA Bs3Tss32DoubleFault, X86TSS32_size +istruc X86TSS32 + at X86TSS32.selPrev, dw 0 + at X86TSS32.padding1, dw 0 + at X86TSS32.esp0, dd BS3_ADDR_STACK_R0 + at X86TSS32.ss0, dw BS3_SEL_R0_SS32 + at X86TSS32.padding_ss0, dw 1 + at X86TSS32.esp1, dd 1 + at X86TSS32.ss1, dw BS3_SEL_R1_SS32 + at X86TSS32.padding_ss1, dw 1 + at X86TSS32.esp2, dd 1 + at X86TSS32.ss2, dw BS3_SEL_R2_SS32 + at X86TSS32.padding_ss2, dw 1 + at X86TSS32.cr3, dd 0 ; Will be filled in by routine setting up paged 32-bit mode w/ traps++. + at X86TSS32.eip, dd 0 ; Will be filled in by routine setting up 32-bit mode w/ traps++. + at X86TSS32.eflags, dd X86_EFL_1 + at X86TSS32.eax, dd 0 + at X86TSS32.ecx, dd 0 + at X86TSS32.edx, dd 0 + at X86TSS32.ebx, dd 0 + at X86TSS32.esp, dd BS3_ADDR_STACK_R0_IST1 + at X86TSS32.ebp, dd 0 + at X86TSS32.esi, dd 0 + at X86TSS32.edi, dd 0 + at X86TSS32.es, dw BS3_SEL_R0_DS32 + at X86TSS32.padding_es, dw 0 + at X86TSS32.cs, dw BS3_SEL_R0_CS32 + at X86TSS32.padding_cs, dw 0 + at X86TSS32.ss, dw BS3_SEL_R0_SS32 + at X86TSS32.padding_ss, dw 0 + at X86TSS32.ds, dw BS3_SEL_R0_DS32 + at X86TSS32.padding_ds, dw 0 + at X86TSS32.fs, dw BS3_SEL_R0_DS32 + at X86TSS32.padding_fs, dw 0 + at X86TSS32.gs, dw BS3_SEL_R0_DS32 + at X86TSS32.padding_gs, dw 0 + at X86TSS32.selLdt, dw 0 + at X86TSS32.padding_ldt, dw 0 + at X86TSS32.fDebugTrap, dw 0 + at X86TSS32.offIoBitmap, dw 0 +iend + +;; +; A spare 32-bit TSS testcases to play around with. +BS3_GLOBAL_DATA Bs3Tss32Spare0, X86TSS32_size +istruc X86TSS32 + at X86TSS32.selPrev, dw 0 + at X86TSS32.padding1, dw 0 + at X86TSS32.esp0, dd BS3_ADDR_STACK_R0 + at X86TSS32.ss0, dw BS3_SEL_R0_SS32 + at X86TSS32.padding_ss0, dw 1 + at X86TSS32.esp1, dd 1 + at X86TSS32.ss1, dw BS3_SEL_R1_SS32 + at X86TSS32.padding_ss1, dw 1 + at X86TSS32.esp2, dd 1 + at X86TSS32.ss2, dw BS3_SEL_R2_SS32 + at X86TSS32.padding_ss2, dw 1 + at X86TSS32.cr3, dd 0 ; Will be filled in by routine setting up paged 32-bit mode w/ traps++. + at X86TSS32.eip, dd 0 ; Will be filled in by routine setting up 32-bit mode w/ traps++. + at X86TSS32.eflags, dd X86_EFL_1 + at X86TSS32.eax, dd 0 + at X86TSS32.ecx, dd 0 + at X86TSS32.edx, dd 0 + at X86TSS32.ebx, dd 0 + at X86TSS32.esp, dd BS3_ADDR_STACK_R0_IST2 + at X86TSS32.ebp, dd 0 + at X86TSS32.esi, dd 0 + at X86TSS32.edi, dd 0 + at X86TSS32.es, dw BS3_SEL_R0_DS32 + at X86TSS32.padding_es, dw 0 + at X86TSS32.cs, dw BS3_SEL_R0_CS32 + at X86TSS32.padding_cs, dw 0 + at X86TSS32.ss, dw BS3_SEL_R0_SS32 + at X86TSS32.padding_ss, dw 0 + at X86TSS32.ds, dw BS3_SEL_R0_DS32 + at X86TSS32.padding_ds, dw 0 + at X86TSS32.fs, dw BS3_SEL_R0_DS32 + at X86TSS32.padding_fs, dw 0 + at X86TSS32.gs, dw BS3_SEL_R0_DS32 + at X86TSS32.padding_gs, dw 0 + at X86TSS32.selLdt, dw 0 + at X86TSS32.padding_ldt, dw 0 + at X86TSS32.fDebugTrap, dw 0 + at X86TSS32.offIoBitmap, dw 0 +iend + +;; +; A spare 32-bit TSS testcases to play around with. +BS3_GLOBAL_DATA Bs3Tss32Spare1, X86TSS32_size +istruc X86TSS32 + at X86TSS32.selPrev, dw 0 + at X86TSS32.padding1, dw 0 + at X86TSS32.esp0, dd BS3_ADDR_STACK_R0 + at X86TSS32.ss0, dw BS3_SEL_R0_SS32 + at X86TSS32.padding_ss0, dw 1 + at X86TSS32.esp1, dd 1 + at X86TSS32.ss1, dw BS3_SEL_R1_SS32 + at X86TSS32.padding_ss1, dw 1 + at X86TSS32.esp2, dd 1 + at X86TSS32.ss2, dw BS3_SEL_R2_SS32 + at X86TSS32.padding_ss2, dw 1 + at X86TSS32.cr3, dd 0 ; Will be filled in by routine setting up paged 32-bit mode w/ traps++. + at X86TSS32.eip, dd 0 ; Will be filled in by routine setting up 32-bit mode w/ traps++. + at X86TSS32.eflags, dd X86_EFL_1 + at X86TSS32.eax, dd 0 + at X86TSS32.ecx, dd 0 + at X86TSS32.edx, dd 0 + at X86TSS32.ebx, dd 0 + at X86TSS32.esp, dd BS3_ADDR_STACK_R0_IST4 + at X86TSS32.ebp, dd 0 + at X86TSS32.esi, dd 0 + at X86TSS32.edi, dd 0 + at X86TSS32.es, dw BS3_SEL_R0_DS32 + at X86TSS32.padding_es, dw 0 + at X86TSS32.cs, dw BS3_SEL_R0_CS32 + at X86TSS32.padding_cs, dw 0 + at X86TSS32.ss, dw BS3_SEL_R0_SS32 + at X86TSS32.padding_ss, dw 0 + at X86TSS32.ds, dw BS3_SEL_R0_DS32 + at X86TSS32.padding_ds, dw 0 + at X86TSS32.fs, dw BS3_SEL_R0_DS32 + at X86TSS32.padding_fs, dw 0 + at X86TSS32.gs, dw BS3_SEL_R0_DS32 + at X86TSS32.padding_gs, dw 0 + at X86TSS32.selLdt, dw 0 + at X86TSS32.padding_ldt, dw 0 + at X86TSS32.fDebugTrap, dw 0 + at X86TSS32.offIoBitmap, dw 0 +iend + + + +;; +; 64-bit TSS +BS3_GLOBAL_DATA Bs3Tss64, X86TSS64_size +istruc X86TSS64 + at X86TSS64.u32Reserved, dd 0 + at X86TSS64.rsp0, dq BS3_ADDR_STACK_R0 + at X86TSS64.rsp1, dq BS3_ADDR_STACK_R1 + at X86TSS64.rsp2, dq BS3_ADDR_STACK_R2 + at X86TSS64.u32Reserved2, dd 0 + at X86TSS64.ist1, dq BS3_ADDR_STACK_R0_IST1 + at X86TSS64.ist2, dq BS3_ADDR_STACK_R0_IST2 + at X86TSS64.ist3, dq BS3_ADDR_STACK_R0_IST3 + at X86TSS64.ist4, dq BS3_ADDR_STACK_R0_IST4 + at X86TSS64.ist5, dq BS3_ADDR_STACK_R0_IST5 + at X86TSS64.ist6, dq BS3_ADDR_STACK_R0_IST6 + at X86TSS64.ist7, dq BS3_ADDR_STACK_R0_IST7 + at X86TSS64.u16Reserved, dw 0 + at X86TSS64.offIoBitmap, dw 0 +iend + +;; +; A spare TSS for testcases to play around with. +BS3_GLOBAL_DATA Bs3Tss64Spare0, X86TSS64_size +istruc X86TSS64 + at X86TSS64.u32Reserved, dd 0 + at X86TSS64.rsp0, dq BS3_ADDR_STACK_R0 + at X86TSS64.rsp1, dq BS3_ADDR_STACK_R1 + at X86TSS64.rsp2, dq BS3_ADDR_STACK_R2 + at X86TSS64.u32Reserved2, dd 0 + at X86TSS64.ist1, dq BS3_ADDR_STACK_R0_IST1 + at X86TSS64.ist2, dq BS3_ADDR_STACK_R0_IST2 + at X86TSS64.ist3, dq BS3_ADDR_STACK_R0_IST3 + at X86TSS64.ist4, dq BS3_ADDR_STACK_R0_IST4 + at X86TSS64.ist5, dq BS3_ADDR_STACK_R0_IST5 + at X86TSS64.ist6, dq BS3_ADDR_STACK_R0_IST6 + at X86TSS64.ist7, dq BS3_ADDR_STACK_R0_IST7 + at X86TSS64.u16Reserved, dw 0 + at X86TSS64.offIoBitmap, dw 0 +iend + +;; +; A spare TSS for testcases to play around with. +BS3_GLOBAL_DATA Bs3Tss64Spare1, X86TSS64_size +istruc X86TSS64 + at X86TSS64.u32Reserved, dd 0 + at X86TSS64.rsp0, dq BS3_ADDR_STACK_R0 + at X86TSS64.rsp1, dq BS3_ADDR_STACK_R1 + at X86TSS64.rsp2, dq BS3_ADDR_STACK_R2 + at X86TSS64.u32Reserved2, dd 0 + at X86TSS64.ist1, dq BS3_ADDR_STACK_R0_IST1 + at X86TSS64.ist2, dq BS3_ADDR_STACK_R0_IST2 + at X86TSS64.ist3, dq BS3_ADDR_STACK_R0_IST3 + at X86TSS64.ist4, dq BS3_ADDR_STACK_R0_IST4 + at X86TSS64.ist5, dq BS3_ADDR_STACK_R0_IST5 + at X86TSS64.ist6, dq BS3_ADDR_STACK_R0_IST6 + at X86TSS64.ist7, dq BS3_ADDR_STACK_R0_IST7 + at X86TSS64.u16Reserved, dw 0 + at X86TSS64.offIoBitmap, dw 0 +iend + + + +;; +; 64-bit TSS sharing an I/O permission bitmap (Bs3SharedIobp) with a 32-bit TSS. +; +BS3_GLOBAL_DATA Bs3Tss64WithIopb, X86TSS64_size +istruc X86TSS64 + at X86TSS64.u32Reserved, dd 0 + at X86TSS64.rsp0, dq BS3_ADDR_STACK_R0 + at X86TSS64.rsp1, dq BS3_ADDR_STACK_R1 + at X86TSS64.rsp2, dq BS3_ADDR_STACK_R2 + at X86TSS64.u32Reserved2, dd 0 + at X86TSS64.ist1, dq BS3_ADDR_STACK_R0_IST1 + at X86TSS64.ist2, dq BS3_ADDR_STACK_R0_IST2 + at X86TSS64.ist3, dq BS3_ADDR_STACK_R0_IST3 + at X86TSS64.ist4, dq BS3_ADDR_STACK_R0_IST4 + at X86TSS64.ist5, dq BS3_ADDR_STACK_R0_IST5 + at X86TSS64.ist6, dq BS3_ADDR_STACK_R0_IST6 + at X86TSS64.ist7, dq BS3_ADDR_STACK_R0_IST7 + at X86TSS64.u16Reserved, dw 0 + at X86TSS64.offIoBitmap, dw (BS3_DATA_NM(Bs3SharedIobp) - BS3_DATA_NM(Bs3Tss64WithIopb)) +iend + +;; +; 32-bit TSS sharing an I/O permission bitmap (Bs3SharedIobp) with a 64-bit TSS, +; and sporting an interrupt redirection bitmap (Bs3SharedIntRedirBm). +BS3_GLOBAL_DATA Bs3Tss32WithIopb, X86TSS32_size +istruc X86TSS32 + at X86TSS32.selPrev, dw 0 + at X86TSS32.padding1, dw 0 + at X86TSS32.esp0, dd BS3_ADDR_STACK_R0 + at X86TSS32.ss0, dw BS3_SEL_R0_SS32 + at X86TSS32.padding_ss0, dw 1 + at X86TSS32.esp1, dd 1 + at X86TSS32.ss1, dw BS3_SEL_R1_SS32 + at X86TSS32.padding_ss1, dw 1 + at X86TSS32.esp2, dd 1 + at X86TSS32.ss2, dw BS3_SEL_R2_SS32 + at X86TSS32.padding_ss2, dw 1 + at X86TSS32.cr3, dd 0 ; Will be filled in by routine setting up paged 32-bit mode w/ traps++. + at X86TSS32.eip, dd 0 ; Will be filled in by routine setting up 32-bit mode w/ traps++. + at X86TSS32.eflags, dd X86_EFL_1 + at X86TSS32.eax, dd 0 + at X86TSS32.ecx, dd 0 + at X86TSS32.edx, dd 0 + at X86TSS32.ebx, dd 0 + at X86TSS32.esp, dd 0 + at X86TSS32.ebp, dd 0 + at X86TSS32.esi, dd 0 + at X86TSS32.edi, dd 0 + at X86TSS32.es, dw 0 + at X86TSS32.padding_es, dw 0 + at X86TSS32.cs, dw 0 + at X86TSS32.padding_cs, dw 0 + at X86TSS32.ss, dw 0 + at X86TSS32.padding_ss, dw 0 + at X86TSS32.ds, dw 0 + at X86TSS32.padding_ds, dw 0 + at X86TSS32.fs, dw 0 + at X86TSS32.padding_fs, dw 0 + at X86TSS32.gs, dw 0 + at X86TSS32.padding_gs, dw 0 + at X86TSS32.selLdt, dw 0 + at X86TSS32.padding_ldt, dw 0 + at X86TSS32.fDebugTrap, dw 0 + at X86TSS32.offIoBitmap, dw (BS3_DATA_NM(Bs3SharedIobp) - BS3_DATA_NM(Bs3Tss32WithIopb)) +iend + +; +; We insert 6 bytes before the interrupt redirection bitmap just to make sure +; we've all got the same idea about where it starts (i.e. 32 bytes before IOBP). +; + times 6 db 0ffh + +;; +; Interrupt redirection bitmap (used by 32-bit TSS). +BS3_GLOBAL_DATA Bs3SharedIntRedirBm, 32 + times 32 db 00h + +;; +; Shared I/O permission bitmap used both by Bs3Tss64WithIopb and Bs3Tss32WithIopb. +BS3_GLOBAL_DATA Bs3SharedIobp, 8192+2 + times 8192+2 db 0ffh +BS3_GLOBAL_DATA Bs3SharedIobpEnd, 0 + + +align 128 + +;; +; 16-bit IDT. +; This requires manual setup by code fielding traps, so we'll just reserve the +; memory here. +; +BS3_GLOBAL_DATA Bs3Idt16, 256*8 + times 256 dq 0 + +;; +; 32-bit IDT. +; This requires manual setup by code fielding traps, so we'll just reserve the +; memory here. +; +BS3_GLOBAL_DATA Bs3Idt32, 256*8 + times 256 dq 0 + +;; +; 64-bit IDT. +; This requires manual setup by code fielding traps, so we'll just reserve the +; memory here. +; +BS3_GLOBAL_DATA Bs3Idt64, 256*16 + times 256 dq 0, 0 + + + times 6 db 0 ; Pad the first LIDT correctly. + +;; +; LIDT structure for the 16-bit IDT (8-byte aligned on offset). +BS3_GLOBAL_DATA Bs3Lidt_Idt16, 2+8 + dw 256*8 - 1 ; limit + dw BS3_SYSTEM16_BASE_LOW(Bs3Idt16) ; low offset + dw (BS3_ADDR_BS3SYSTEM16 >> 16) ; high offset + dd 0 ; top32 offset + + times 4 db 0 ; padding the start of the next + +;; +; LIDT structure for the 32-bit IDT (8-byte aligned on offset). +BS3_GLOBAL_DATA Bs3Lidt_Idt32, 2+8 + dw 256*8 - 1 ; limit + dw BS3_SYSTEM16_BASE_LOW(Bs3Idt32) ; low offset + dw (BS3_ADDR_BS3SYSTEM16 >> 16) ; high offset + dd 0 ; top32 offset + + times 4 db 0 ; padding the start of the next + +;; +; LIDT structure for the 64-bit IDT (8-byte aligned on offset). +BS3_GLOBAL_DATA Bs3Lidt_Idt64, 2+8 + dw 256*16 - 1 ; limit + dw BS3_SYSTEM16_BASE_LOW(Bs3Idt64) ; low offset + dw (BS3_ADDR_BS3SYSTEM16 >> 16) ; high offset + dd 0 ; top32 offset + + times 4 db 0 ; padding the start of the next + +;; +; LIDT structure for the real mode IVT at address 0x00000000 (8-byte aligned on offset). +BS3_GLOBAL_DATA Bs3Lidt_Ivt, 2+8 + dw 0ffffh ; limit + dw 0 ; low offset + dw 0 ; high offset + dd 0 ; top32 offset + + times 4 db 0 ; padding the start of the next + +;; +; LGDT structure for the current GDT (8-byte aligned on offset). +BS3_GLOBAL_DATA Bs3Lgdt_Gdt, 2+8 + dw BS3_DATA_NM(Bs3GdtEnd) - BS3_DATA_NM(Bs3Gdt) - 1 ; limit + dw BS3_SYSTEM16_BASE_LOW(Bs3Gdt) ; low offset + dw (BS3_ADDR_BS3SYSTEM16 >> 16) ; high offset + dd 0 ; top32 offset + +;; +; LGDT structure for the default GDT (8-byte aligned on offset). +; This must not be modified, whereas Bs3Lgdt_Gdt can be modified by the user. +BS3_GLOBAL_DATA Bs3LgdtDef_Gdt, 2+8 + dw BS3_DATA_NM(Bs3GdtEnd) - BS3_DATA_NM(Bs3Gdt) - 1 ; limit + dw BS3_SYSTEM16_BASE_LOW(Bs3Gdt) ; low offset + dw (BS3_ADDR_BS3SYSTEM16 >> 16) ; high offset + dd 0 ; top32 offset + + + +align 16 +;; +; LDT filling up the rest of the segment. +; +; Currently this starts at 0x84e0, which leaves us with 0xb20 bytes. We'll use +; the last 32 of those for an eye catcher. +; +BS3_GLOBAL_DATA Bs3Ldt, 0b20h - 32 + times (0b20h - 32) db 0 +BS3_GLOBAL_DATA Bs3LdtEnd, 0 + db 10, 13, 'eye-catcher: SYSTEM16 END', 10, 13, 0, 0, 0 ; 32 bytes long + +; +; Check the segment size. +; +%ifndef KBUILD_GENERATING_MAKEFILE_DEPENDENCIES + %if ($ - $$) != 09000h + %assign offActual ($ - $$) + %error "Bad BS3SYSTEM16 segment size: " %+ offActual %+ ", expected 0x9000 (36864)" + %endif +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-I4D.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-I4D.asm new file mode 100644 index 00000000..2fd75d90 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-I4D.asm @@ -0,0 +1,80 @@ +; $Id: bs3-wc16-I4D.asm $ +;; @file +; BS3Kit - 16-bit Watcom C/C++, 32-bit signed integer division. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; 32-bit signed integer division. +; +; @returns DX:AX quotient, CX:BX remainder. +; @param DX:AX Dividend. +; @param CX:BX Divisor +; +; @uses Nothing. +; +global $_?I4D +$_?I4D: +;; @todo no idea if we're getting the negative division stuff right here according to what watcom expectes... +extern TODO_NEGATIVE_SIGNED_DIVISION + ; Move dividend into EDX:EAX + shl eax, 10h + mov ax, dx + sar dx, 0fh + movsx edx, dx + + ; Move divisor into ebx. + shl ebx, 10h + mov bx, cx + + ; Do it! + idiv ebx + + ; Reminder in to CX:BX + mov bx, dx + shr edx, 10h + mov cx, dx + + ; Quotient into DX:AX + mov edx, eax + shr edx, 10h + +%ifdef ASM_MODEL_FAR_CODE + retf +%else + ret +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-I8DQ.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-I8DQ.asm new file mode 100644 index 00000000..0087647c --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-I8DQ.asm @@ -0,0 +1,121 @@ +; $Id: bs3-wc16-I8DQ.asm $ +;; @file +; BS3Kit - 16-bit Watcom C/C++, 64-bit unsigned integer division. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +BS3_EXTERN_CMN Bs3Int64Div + + +;; +; 64-bit unsigned integer division, SS variant. +; +; @returns ax:bx:cx:dx quotient. (AX is the most significant, DX the least) +; @param ax:bx:cx:dx Dividend. +; @param [ss:si] Divisor +; +; @uses Nothing. +; +global $_?I8DQ +$_?I8DQ: + push es + push ss + pop es +%ifdef ASM_MODEL_FAR_CODE + push cs +%endif + call $_?I8DQE + pop es +%ifdef ASM_MODEL_FAR_CODE + retf +%else + ret +%endif + +;; +; 64-bit unsigned integer division, ES variant. +; +; @returns ax:bx:cx:dx quotient. (AX is the most significant, DX the least) +; @param ax:bx:cx:dx Dividend. +; @param [es:si] Divisor +; +; @uses Nothing. +; +global $_?I8DQE +$_?I8DQE: + push ds + push es + + ; + ; Convert to a C __cdecl call - not doing this in assembly. + ; + + ; Set up a frame of sorts, allocating 16 bytes for the result buffer. + push bp + sub sp, 10h + mov bp, sp + + ; Pointer to the return buffer. + push ss + push bp + add bp, 10h ; Correct bp. + + ; The divisor. + push dword [es:si + 4] + push dword [es:si] + + ; The dividend. + push ax + push bx + push cx + push dx + + call Bs3Int64Div + + ; Load the quotient. + mov ax, [bp - 10h + 8 + 6] + mov bx, [bp - 10h + 8 + 4] + mov cx, [bp - 10h + 8 + 2] + mov dx, [bp - 10h + 8] + + leave + pop es + pop ds +%ifdef ASM_MODEL_FAR_CODE + retf +%else + ret +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-I8DR.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-I8DR.asm new file mode 100644 index 00000000..b90581d8 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-I8DR.asm @@ -0,0 +1,121 @@ +; $Id: bs3-wc16-I8DR.asm $ +;; @file +; BS3Kit - 16-bit Watcom C/C++, 64-bit unsigned integer modulo. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +BS3_EXTERN_CMN Bs3Int64Div + + +;; +; 64-bit unsigned integer modulo, SS variant. +; +; @returns ax:bx:cx:dx reminder. (AX is the most significant, DX the least) +; @param ax:bx:cx:dx Dividend. +; @param [ss:si] Divisor +; +; @uses Nothing. +; +global $_?I8DR +$_?I8DR: + push es + push ss + pop es +%ifdef ASM_MODEL_FAR_CODE + push cs +%endif + call $_?I8DRE + pop es +%ifdef ASM_MODEL_FAR_CODE + retf +%else + ret +%endif + +;; +; 64-bit unsigned integer modulo, ES variant. +; +; @returns ax:bx:cx:dx reminder. +; @param ax:bx:cx:dx Dividend. +; @param [es:si] Divisor +; +; @uses Nothing. +; +global $_?I8DRE +$_?I8DRE: + push ds + push es + + ; + ; Convert to a C __cdecl call - not doing this in assembly. + ; + + ; Set up a frame of sorts, allocating 16 bytes for the result buffer. + push bp + sub sp, 10h + mov bp, sp + + ; Pointer to the return buffer. + push ss + push bp + add bp, 10h ; Correct bp. + + ; The divisor. + push dword [es:si + 4] + push dword [es:si] + + ; The dividend. + push ax + push bx + push cx + push dx + + call Bs3Int64Div + + ; Load the reminder. + mov ax, [bp - 10h + 8 + 6] + mov bx, [bp - 10h + 8 + 4] + mov cx, [bp - 10h + 8 + 2] + mov dx, [bp - 10h + 8] + + leave + pop es + pop ds +%ifdef ASM_MODEL_FAR_CODE + retf +%else + ret +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-I8RS.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-I8RS.asm new file mode 100644 index 00000000..f90201dd --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-I8RS.asm @@ -0,0 +1,78 @@ +; $Id: bs3-wc16-I8RS.asm $ +;; @file +; BS3Kit - 16-bit Watcom C/C++, 64-bit signed integer right shift. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; 64-bit signed integer left shift. +; +; @returns AX:BX:CX:DX (AX is the most significant, DX the least) +; @param AX:BX:CX:DX Value to shift. +; @param SI Shift count. +; +global $_?I8RS +$_?I8RS: + push si + + ; + ; The 16-bit watcom code differs from the 32-bit one in the way it + ; handles the shift count. All 16-bit bits are used in the 16-bit + ; code, we do the same as the 32-bit one as we don't want to wast + ; time in the below loop. + ; + ; Using 8086 comatible approach here as it's less hazzle to write + ; and smaller. + ; + and si, 3fh + jz .return + +.next_shift: + sar ax, 1 + rcr bx, 1 + rcr cx, 1 + rcr dx, 1 + dec si + jnz .next_shift + +.return: + pop si +%ifdef ASM_MODEL_FAR_CODE + retf +%else + ret +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U4D.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U4D.asm new file mode 100644 index 00000000..989ff869 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U4D.asm @@ -0,0 +1,124 @@ +; $Id: bs3-wc16-U4D.asm $ +;; @file +; BS3Kit - 16-bit Watcom C/C++, 32-bit unsigned integer division. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + + +;; +; 32-bit unsigned integer division. +; +; @returns DX:AX quotient, CX:BX remainder. +; @param DX:AX Dividend. +; @param CX:BX Divisor +; +; @uses Nothing. +; +%ifdef BS3KIT_WITH_REAL_WATCOM_INTRINSIC_NAMES +global __U4D +__U4D: +%endif +global $_?U4D +$_?U4D: +%if TMPL_BITS >= 32 + ; Move dividend into EDX:EAX + shl eax, 10h + mov ax, dx + xor edx, edx + + ; Move divisor into ebx. + shl ebx, 10h + mov bx, cx + + ; Do it! + div ebx + + ; Reminder in to CX:BX + mov bx, dx + shr edx, 10h + mov cx, dx + + ; Quotient into DX:AX + mov edx, eax + shr edx, 10h +%else + push ds + push es + + ; + ; Convert to a C __cdecl call - too lazy to do this in assembly. + ; + + ; Set up a frame of sorts, allocating 8 bytes for the result buffer. + push bp + sub sp, 08h + mov bp, sp + + ; Pointer to the return buffer. + push ss + push bp + add bp, 08h ; Correct bp. + + ; The divisor. + push cx + push bx + + ; The dividend. + push dx + push ax + + BS3_EXTERN_CMN Bs3UInt32Div + call Bs3UInt32Div + + ; Load the reminder. + mov cx, [bp - 08h + 6] + mov bx, [bp - 08h + 4] + ; Load the quotient. + mov dx, [bp - 08h + 2] + mov ax, [bp - 08h] + + mov sp, bp + pop bp + pop es + pop ds + +%endif +%ifdef ASM_MODEL_FAR_CODE + retf +%else + ret +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U8DQ.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U8DQ.asm new file mode 100644 index 00000000..c6fbf0e7 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U8DQ.asm @@ -0,0 +1,124 @@ +; $Id: bs3-wc16-U8DQ.asm $ +;; @file +; BS3Kit - 16-bit Watcom C/C++, 64-bit unsigned integer division. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +BS3_EXTERN_CMN Bs3UInt64Div + + +;; +; 64-bit unsigned integer division, SS variant. +; +; @returns ax:bx:cx:dx quotient. (AX is the most significant, DX the least) +; @param ax:bx:cx:dx Dividend. +; @param [ss:si] Divisor +; +; @uses Nothing. +; +global $_?U8DQ +$_?U8DQ: + push es + push ss + pop es +%ifdef ASM_MODEL_FAR_CODE + push cs +%endif + call $_?U8DQE + pop es +%ifdef ASM_MODEL_FAR_CODE + retf +%else + ret +%endif + +;; +; 64-bit unsigned integer division, ES variant. +; +; @returns ax:bx:cx:dx quotient. (AX is the most significant, DX the least) +; @param ax:bx:cx:dx Dividend. +; @param [es:si] Divisor +; +; @uses Nothing. +; +global $_?U8DQE +$_?U8DQE: + push ds + push es + + ; + ; Convert to a C __cdecl call - not doing this in assembly. + ; + + ; Set up a frame of sorts, allocating 16 bytes for the result buffer. + push bp + sub sp, 10h + mov bp, sp + + ; Pointer to the return buffer. + push ss + push bp + add bp, 10h ; Correct bp. + + ; The divisor. + push word [es:si + 6] + push word [es:si + 4] + push word [es:si + 2] + push word [es:si] + + ; The dividend. + push ax + push bx + push cx + push dx + + call Bs3UInt64Div + + ; Load the quotient. + mov ax, [bp - 10h + 6] + mov bx, [bp - 10h + 4] + mov cx, [bp - 10h + 2] + mov dx, [bp - 10h] + + mov sp, bp + pop bp + pop es + pop ds +%ifdef ASM_MODEL_FAR_CODE + retf +%else + ret +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U8DR.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U8DR.asm new file mode 100644 index 00000000..18381119 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U8DR.asm @@ -0,0 +1,124 @@ +; $Id: bs3-wc16-U8DR.asm $ +;; @file +; BS3Kit - 16-bit Watcom C/C++, 64-bit unsigned integer modulo. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +BS3_EXTERN_CMN Bs3UInt64Div + + +;; +; 64-bit unsigned integer modulo, SS variant. +; +; @returns ax:bx:cx:dx reminder. (AX is the most significant, DX the least) +; @param ax:bx:cx:dx Dividend. +; @param [ss:si] Divisor +; +; @uses Nothing. +; +global $_?U8DR +$_?U8DR: + push es + push ss + pop es +%ifdef ASM_MODEL_FAR_CODE + push cs +%endif + call $_?U8DRE + pop es +%ifdef ASM_MODEL_FAR_CODE + retf +%else + ret +%endif + +;; +; 64-bit unsigned integer modulo, ES variant. +; +; @returns ax:bx:cx:dx reminder. (AX is the most significant, DX the least) +; @param ax:bx:cx:dx Dividend. +; @param [es:si] Divisor +; +; @uses Nothing. +; +global $_?U8DRE +$_?U8DRE: + push ds + push es + + ; + ; Convert to a C __cdecl call - not doing this in assembly. + ; + + ; Set up a frame of sorts, allocating 16 bytes for the result buffer. + push bp + sub sp, 10h + mov bp, sp + + ; Pointer to the return buffer. + push ss + push bp + add bp, 10h ; Correct bp. + + ; The divisor. + push word [es:si + 6] + push word [es:si + 4] + push word [es:si + 2] + push word [es:si] + + ; The dividend. + push ax + push bx + push cx + push dx + + call Bs3UInt64Div + + ; Load the reminder. + mov ax, [bp - 10h + 8 + 6] + mov bx, [bp - 10h + 8 + 4] + mov cx, [bp - 10h + 8 + 2] + mov dx, [bp - 10h + 8] + + mov sp, bp + pop bp + pop es + pop ds +%ifdef ASM_MODEL_FAR_CODE + retf +%else + ret +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U8LS.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U8LS.asm new file mode 100644 index 00000000..879e4f9c --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U8LS.asm @@ -0,0 +1,80 @@ +; $Id: bs3-wc16-U8LS.asm $ +;; @file +; BS3Kit - 16-bit Watcom C/C++, 64-bit integer left shift. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; 64-bit integer left shift. +; +; @returns AX:BX:CX:DX (AX is the most significant, DX the least) +; @param AX:BX:CX:DX Value to shift. +; @param SI Shift count. +; +global $_?U8LS +$_?U8LS: +global $_?I8LS +$_?I8LS: + push si + + ; + ; The 16-bit watcom code differs from the 32-bit one in the way it + ; handles the shift count. All 16-bit bits are used in the 16-bit + ; code, we do the same as the 32-bit one as we don't want to wast + ; time in the below loop. + ; + ; Using 8086 compatible approach here as it's less hazzle to write + ; and smaller. + ; + and si, 3fh + + jz .return +.next_shift: + shl dx, 1 + rcl cx, 1 + rcl bx, 1 + rcl ax, 1 + dec si + jnz .next_shift + +.return: + pop si +%ifdef ASM_MODEL_FAR_CODE + retf +%else + ret +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U8RS.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U8RS.asm new file mode 100644 index 00000000..4da920d7 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U8RS.asm @@ -0,0 +1,82 @@ +; $Id: bs3-wc16-U8RS.asm $ +;; @file +; BS3Kit - 16-bit Watcom C/C++, 64-bit unsigned integer right shift. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; 64-bit unsigned integer left shift. +; +; @returns AX:BX:CX:DX (AX is the most significant, DX the least) +; @param AX:BX:CX:DX Value to shift. +; @param SI Shift count. +; +%ifdef BS3KIT_WITH_REAL_WATCOM_INTRINSIC_NAMES +global __U8RS +__U8RS: +%endif +global $_?U8RS +$_?U8RS: + push si + + ; + ; The 16-bit watcom code differs from the 32-bit one in the way it + ; handles the shift count. All 16-bit bits are used in the 16-bit + ; code, we do the same as the 32-bit one as we don't want to wast + ; time in the below loop. + ; + ; Using 8086 comatible approach here as it's less hazzle to write + ; and smaller. + ; + and si, 3fh + jz .return + +.next_shift: + shr ax, 1 + rcr bx, 1 + rcr cx, 1 + rcr dx, 1 + dec si + jnz .next_shift + +.return: + pop si +%ifdef ASM_MODEL_FAR_CODE + retf +%else + ret +%endif + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-I8D.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-I8D.asm new file mode 100644 index 00000000..2c608ffb --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-I8D.asm @@ -0,0 +1,81 @@ +; $Id: bs3-wc32-I8D.asm $ +;; @file +; BS3Kit - 32-bit Watcom C/C++, 64-bit signed integer division. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +BS3_EXTERN_CMN Bs3Int64Div + + +;; +; 64-bit signed integer division. +; +; @returns EDX:EAX Quotient, ECX:EBX Remainder. +; @param EDX:EAX Dividend. +; @param ECX:EBX Divisor +; +global $??I8D +$??I8D: + ; + ; Convert to a C __cdecl call - not doing this in assembly. + ; + + ; Set up a frame, allocating 16 bytes for the result buffer. + push ebp + mov ebp, esp + sub esp, 10h + + ; Pointer to the return buffer. + push esp + + ; The dividend. + push ecx + push ebx + + ; The dividend. + push edx + push eax + + call Bs3Int64Div + + ; Load the result. + mov ecx, [ebp - 10h + 12] + mov ebx, [ebp - 10h + 8] + mov edx, [ebp - 10h + 4] + mov eax, [ebp - 10h] + + leave + ret + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-I8RS.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-I8RS.asm new file mode 100644 index 00000000..4840a7f7 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-I8RS.asm @@ -0,0 +1,70 @@ +; $Id: bs3-wc32-I8RS.asm $ +;; @file +; BS3Kit - 32-bit Watcom C/C++, 64-bit signed integer right shift. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; 64-bit signed integer left shift. +; +; @returns EDX:EAX +; @param EDX:EAX Value to shift. +; @param BL Shift count (it's specified as ECX:EBX, but we only use BL). +; +global $??I8RS +$??I8RS: + push ecx ; We're allowed to trash ECX, but why bother. + + mov cl, bl + and cl, 3fh + test cl, 20h + jnz .big_shift + + ; Shifting less than 32. + shrd eax, edx, cl + sar edx, cl + +.return: + pop ecx + ret + +.big_shift: + ; Shifting 32 or more. + mov eax, edx + sar eax, cl ; Only uses lower 5 bits. + sar edx, 1fh ; Sign extend it. + jmp .return + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-U8D.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-U8D.asm new file mode 100644 index 00000000..5f14c32b --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-U8D.asm @@ -0,0 +1,81 @@ +; $Id: bs3-wc32-U8D.asm $ +;; @file +; BS3Kit - 32-bit Watcom C/C++, 64-bit unsigned integer division. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + +BS3_EXTERN_CMN Bs3UInt64Div + + +;; +; 64-bit unsigned integer division. +; +; @returns EDX:EAX Quotient, ECX:EBX Remainder. +; @param EDX:EAX Dividend. +; @param ECX:EBX Divisor +; +global $??U8D +$??U8D: + ; + ; Convert to a C __cdecl call - not doing this in assembly. + ; + + ; Set up a frame, allocating 16 bytes for the result buffer. + push ebp + mov ebp, esp + sub esp, 10h + + ; Pointer to the return buffer. + push esp + + ; The divisor. + push ecx + push ebx + + ; The dividend. + push edx + push eax + + call Bs3UInt64Div + + ; Load the result. + mov ecx, [ebp - 10h + 12] + mov ebx, [ebp - 10h + 8] + mov edx, [ebp - 10h + 4] + mov eax, [ebp - 10h] + + leave + ret + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-U8LS.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-U8LS.asm new file mode 100644 index 00000000..ffd30a48 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-U8LS.asm @@ -0,0 +1,72 @@ +; $Id: bs3-wc32-U8LS.asm $ +;; @file +; BS3Kit - 32-bit Watcom C/C++, 64-bit integer left shift. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; 64-bit integer left shift. +; +; @returns EDX:EAX +; @param EDX:EAX Value to shift. +; @param BL Shift count (it's specified as ECX:EBX, but we only use BL). +; +global $??U8LS +$??U8LS: +global $??I8LS +$??I8LS: + push ecx ; We're allowed to trash ECX, but why bother. + + mov cl, bl + and cl, 3fh + test cl, 20h + jnz .big_shift + + ; Shifting less than 32. + shld edx, eax, cl + shl eax, cl + +.return: + pop ecx + ret + +.big_shift: + ; Shifting 32 or more. + mov edx, eax + shl edx, cl ; Only uses lower 5 bits. + xor eax, eax + jmp .return + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-U8M.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-U8M.asm new file mode 100644 index 00000000..57a1e583 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-U8M.asm @@ -0,0 +1,93 @@ +; $Id: bs3-wc32-U8M.asm $ +;; @file +; BS3Kit - 32-bit Watcom C/C++, 64-bit integer multiplication. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; 64-bit unsigned & signed integer multiplication. +; +; @returns EDX:EAX as the product. +; @param EDX:EAX Factor 1 - edx=F1H, eax=F1L. +; @param ECX:EBX Factor 2 - ecx=F2H, ebx=F2L. +; +global $??I8M +$??I8M: +global $??U8M +$??U8M: + ; + ; If both the high dwords are zero, we can get away with + ; a simple 32-bit multiplication. + ; + test ecx, ecx + jnz .big + test edx, edx + jnz .big + mul ebx + ret + +.big: + ; + ; Imagine we use 4294967296-base (2^32), so each factor has two + ; digits H and L, thus we have: F1H:F1L * F2H:F1L which we can + ; multipy like we learned in primary school. Since the result + ; is limited to 64-bit, we can skip F1H*F2H and discard the + ; high 32-bit in F1L*F2H and F1H*F2L. + ; result = ((F1L*F2H) << 32) + ; + ((F1H*F2L) << 32) + ; + (F1L*F2L); + ; + push ecx ; Preserve ECX just to be nice. + push eax ; Stash F1L for later. + push edx ; Stash F1H for later. + + ; ECX = F1L*F2H + mul ecx + mov ecx, eax + + ; ECX += F1H * F2L + pop eax + mul ebx + add ecx, eax + + ; EDX:EAX = F1L * F2L + pop eax + mul ebx + add edx, ecx + + pop ecx + ret + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-U8RS.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-U8RS.asm new file mode 100644 index 00000000..82b20169 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-U8RS.asm @@ -0,0 +1,70 @@ +; $Id: bs3-wc32-U8RS.asm $ +;; @file +; BS3Kit - 32-bit Watcom C/C++, 64-bit unsigned integer right shift. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit-template-header.mac" + + +;; +; 64-bit unsigned integer right shift. +; +; @returns EDX:EAX +; @param EDX:EAX Value to shift. +; @param BL Shift count (it's specified as ECX:EBX, but we only use BL). +; +global $??U8RS +$??U8RS: + push ecx ; We're allowed to trash ECX, but why bother. + + mov cl, bl + and cl, 3fh + test cl, 20h + jnz .big_shift + + ; Shifting less than 32. + shrd eax, edx, cl + shr edx, cl + +.return: + pop ecx + ret + +.big_shift: + ; Shifting 32 or more. + mov eax, edx + shr eax, cl ; Only uses lower 5 bits. + xor edx, edx + jmp .return + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3cpudt.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3cpudt.c new file mode 100644 index 00000000..b4210da7 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3cpudt.c @@ -0,0 +1,71 @@ +/* $Id: bs3cpudt.c $ */ +/** @file + * BS3Kit - Tests Bs3CpuDetect_rm. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ + +#include "bs3kit.h" +#include <stdio.h> +#include <stdint.h> + + +unsigned StoreMsw(void); +#pragma aux StoreMsw = \ + ".286" \ + "smsw ax" \ + value [ax]; + +void LoadMsw(unsigned); +#pragma aux LoadMsw = \ + ".286p" \ + "lmsw ax" \ + parm [ax]; + +int main() +{ + uint16_t volatile usCpu = Bs3CpuDetect_rm(); + printf("usCpu=%#x\n", usCpu); + if ((usCpu & BS3CPU_TYPE_MASK) >= BS3CPU_80286) + { + printf("(42=%d) msw=%#x (42=%d)\n", 42, StoreMsw(), 42); + LoadMsw(0); + printf("lmsw 0 => msw=%#x (42=%d)\n", StoreMsw(), 42); + } + return 0; +} + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-autostubs.kmk b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-autostubs.kmk new file mode 100644 index 00000000..2445e182 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-autostubs.kmk @@ -0,0 +1,194 @@ +# $Id: bs3kit-autostubs.kmk $ +## @file +# BS3Kit - Automatic near/far stubs - generated by the bs3kit-autostubs.kmk makefile rule. +# + +# +# Copyright (C) 2007-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <https://www.gnu.org/licenses>. +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,Bs3SelFlatDataToProtFar16,4) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,Bs3SelFlatDataToRealMode,4) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,Bs3SelLnkPtrToFlat,4) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,Bs3SelProtFar16DataToFlat,4) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,Bs3SelProtFar16DataToRealMode,4) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,Bs3SelRealModeCodeToFlat,4) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,Bs3SelRealModeDataToFlat,4) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,Bs3SelRealModeDataToProtFar16,4) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,Bs3ExtCtxRestoreEx,4) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,Bs3ExtCtxRestore,4) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,Bs3ExtCtxSaveEx,4) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,Bs3ExtCtxSave,4) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,Bs3SelLnkPtrToCurPtr,4) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,Bs3SelFar32ToFlat32NoClobber,6) +$(call BS3KIT_FN_GEN_CMN_FARSTUB,bs3kit-common-16,Bs3RegCtxSaveEx,8) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxSetAbridgedFtw) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxSetMm) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxSetMxCsrMask) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxSetMxCsr) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxSetXmm) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxSetYmm) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3RegCtxSetGpr) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestCheckExtCtx) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestCheckRegCtxEx) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestFailed) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestFailedF) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestFailedV) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestQueryCfgBool) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3GetCpuVendor) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3StrCpy) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3GetModeNameShortLower) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3GetModeName) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3PagingAlias) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3PagingInitRootForLM) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3PagingInitRootForPAE) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3PagingInitRootForPP) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3PagingMapRamAbove4GForLM) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3PagingProtectPtr) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3PagingProtect) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3PagingQueryAddressInfo) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3PagingUnalias) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3SwitchFromV86To16BitAndCallC) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxAlloc) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxCopy) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxInit) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TrapSetHandler) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxGetXmm) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxGetYmm) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3Printf) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3PrintfV) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3StrFormatV) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3StrLen) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3StrNLen) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3StrPrintf) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3StrPrintfV) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxGetAbridgedFtw) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxGetFcw) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxGetFsw) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxGetSize) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3PicUpdateMask) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3SlabFree) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestSubErrorCount) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxGetMxCsrMask) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxGetMxCsr) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3SelFar32ToFlat32) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3SelProtFar32ToFlat32) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestQueryCfgU32) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxGetMm) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestNow) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestQueryCfgU8) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TrapSetDpl) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxFree) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxSetFcw) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3ExtCtxSetFsw) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3MemAlloc) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3MemAllocZ) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3MemCpy) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3MemGuardedTestPageAlloc) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3MemGuardedTestPageAllocEx) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3MemMove) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3MemPCpy) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3PagingGetPte) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3PagingSetupCanonicalTraps) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3RegCtxGetRspSsAsCurPtr) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3SlabAllocEx) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3SlabAlloc) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3SlabListAllocEx) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3SlabListAlloc) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3MemFree) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3MemGuardedTestPageFree) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3MemPrintInfo) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3PicMaskAll) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3PicSetup) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3PitDisable) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3PitSetupAndEnablePeriodTimer) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3PrintStr) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3RegCtxConvertToRingX) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3RegCtxConvertV86ToRm) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3RegCtxPrint) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3RegCtxSaveForMode) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3RegCtxSetGrpDsFromCurPtr) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3RegCtxSetGrpSegFromCurPtr) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3RegCtxSetGrpSegFromFlat) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3RegCtxSetRipCsFromCurPtr) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3RegCtxSetRipCsFromFlat) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3RegCtxSetRipCsFromLnkPtr) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3SelSetup16BitCode) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3SelSetup16BitData) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3SelSetup32BitCode) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3SelSetupGate64) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3SelSetupGate) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3SlabInit) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3SlabListAdd) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3SlabListFree) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3SlabListInit) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestHostPrintf) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestHostPrintfV) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestInit) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestPrintf) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestPrintfV) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestSkipped) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestSkippedF) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestSkippedV) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestSub) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestSubDone) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestSubF) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestSubV) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestTerm) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TestValue) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3Trap16InitEx) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3Trap16Init) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3Trap16SetGate) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3Trap32Init) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3Trap32SetGate) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3Trap64InitEx) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3Trap64Init) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3Trap64SetGate) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TrapDefaultHandler) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TrapPrintFrame) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TrapReInit) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TrapRmV86InitEx) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TrapRmV86Init) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TrapRmV86SetGate) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TrapSetHandlerEx) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TrapSetJmpAndRestoreInRm) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TrapSetJmpAndRestore) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TrapSetJmpAndRestoreWithExtCtxAndRm) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TrapSetJmpAndRestoreWithExtCtx) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TrapSetJmpAndRestoreWithRm) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3TrapUnsetJmp) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3UInt32Div) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,Bs3UInt64Div) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,bs3PagingGetLegacyPte) +$(call BS3KIT_FN_GEN_CMN_NEARSTUB,bs3kit-common-16,bs3PagingGetPaePte) +$(call BS3KIT_FN_GEN_MODE_NEARSTUB,bs3kit-common-16,Bs3BiosInt15hE820) +$(call BS3KIT_FN_GEN_MODE_NEARSTUB,bs3kit-common-16,Bs3SwitchTo32BitAndCallC) +$(call BS3KIT_FN_GEN_MODE_NEARSTUB,bs3kit-common-16,Bs3BiosInt15h88) +$(call BS3KIT_FN_GEN_MODE_NEARSTUB,bs3kit-common-16,Bs3TrapInit) diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-docs.c b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-docs.c new file mode 100644 index 00000000..ef798d35 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-docs.c @@ -0,0 +1,170 @@ +/* $Id: bs3kit-docs.c $ */ +/** @file + * BS3Kit - Documentation. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + + +/** @page pg_bs3kit BS3Kit - Boot Sector Kit \#3 + * + * The BS3Kit is a framework for bare metal floppy/usb image tests. + * + * The 3rd iteration of the framework includes support for 16-bit and 32-bit + * C/C++ code, with provisions for 64-bit C code to possibly be added later. + * The C code have to do without a runtime library, otherwhat what we can share + * possibly with IPRT. + * + * This iteration also adds a real linker into the picture, which is an + * improvment over early when all had to done in a single assembler run with + * lots of includes and macros controlling what we needed. The functions are no + * in separate files and compiled/assembled into libraries, so the linker will + * only include exactly what is needed. The current linker is the OpenWatcom + * one, wlink, that we're already using when building the BIOSes. If it wasn't + * for the segment/selector fixups in 16-bit code (mostly), maybe we could + * convince the ELF linker from GNU binutils to do the job too (with help from + * the ). + * + * + * @sa grp_bs3kit, grp_bs3kit_tmpl, grp_bs3kit_cmn, grp_bs3kit_mode, + * grp_bs3kit_system + * + * @section sec_calling_convention Calling convention + * + * Because we're not mixing with C code, we will use __cdecl for 16-bit and + * 32-bit code, where as 64-bit code will use the microsoft calling AMD64 + * convention. To avoid unnecessary %ifdef'ing in assembly code, we will use a + * macro to load the RCX, RDX, R8 and R9 registers off the stack in 64-bit + * assembly code. + * + * Register treatment in 16-bit __cdecl, 32-bit __cdecl and 64-bit msabi: + * + * | Register | 16-bit | 32-bit | 64-bit | ASM template | + * | ------------ | ----------- | ---------- | --------------- | ------------ | + * | EAX, RAX | volatile | volatile | volatile | volatile | + * | EBX, RBX | volatile | preserved | preserved | both | + * | ECX, RCX | volatile | volatile | volatile, arg 0 | volatile | + * | EDX, RDX | volatile | volatile | volatile, arg 1 | volatile | + * | ESP, RSP | preserved | preserved | preserved | preserved | + * | EBP, RBP | preserved | preserved | preserved | preserved | + * | EDI, RDI | preserved | preserved | preserved | preserved | + * | ESI, RSI | preserved | preserved | preserved | preserved | + * | R8 | volatile | volatile | volatile, arg 2 | volatile | + * | R9 | volatile | volatile | volatile, arg 3 | volatile | + * | R10 | volatile | volatile | volatile | volatile | + * | R11 | volatile | volatile | volatile | volatile | + * | R12 | volatile | volatile | preserved | preserved(*) | + * | R13 | volatile | volatile | preserved | preserved(*) | + * | R14 | volatile | volatile | preserved | preserved(*) | + * | R15 | volatile | volatile | preserved | preserved(*) | + * | RFLAGS.DF | =0 | =0 | =0 | =0 | + * | CS | preserved | preserved | preserved | preserved | + * | DS | preserved! | preserved? | preserved | both | + * | ES | volatile | volatile | preserved | volatile | + * | FS | preserved | preserved | preserved | preserved | + * | GS | preserved | volatile | preserved | both | + * | SS | preserved | preserved | preserved | preserved | + * + * The 'both' here means that we preserve it wrt to our caller, while at the + * same time assuming anything we call will clobber it. + * + * The 'preserved(*)' marking of R12-R15 indicates that they'll be preserved in + * 64-bit mode, but may be changed in certain cases when running 32-bit or + * 16-bit code. This is especially true if switching CPU mode, e.g. from 32-bit + * protected mode to 32-bit long mode. + * + * Return values are returned in the xAX register, but with the following + * caveats for values larger than ARCH_BITS: + * - 16-bit code: + * - 32-bit values are returned in AX:DX, where AX holds bits 15:0 and + * DX bits 31:16. + * - 64-bit values are returned in DX:CX:BX:AX, where DX holds bits + * 15:0, CX bits 31:16, BX bits 47:32, and AX bits 63:48. + * - 32-bit code: + * - 64-bit values are returned in EAX:EDX, where eax holds the least + * significant bits. + * + * The DS segment register is pegged to BS3DATA16_GROUP in 16-bit code so that + * we don't need to reload it all the time. This allows us to modify it in + * ring-0 and mode switching code without ending up in any serious RPL or DPL + * trouble. In 32-bit and 64-bit mode the DS register is a flat, unlimited, + * writable selector. + * + * In 16-bit and 32-bit code we do not assume anything about ES, FS, and GS. + * + * + * For an in depth coverage of x86 and AMD64 calling convensions, see + * http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/function-calling-conventions.html + * + * + * + * @section sec_modes Execution Modes + * + * BS3Kit defines a number of execution modes in order to be able to test the + * full CPU capabilities (that VirtualBox care about anyways). It currently + * omits system management mode, hardware virtualization modes, and security + * modes as those aren't supported by VirtualBox or are difficult to handle. + * + * The modes are categorized into normal and weird ones. + * + * The normal ones are: + * + RM - Real mode. + * + PE16 - Protected mode running 16-bit code, 16-bit TSS and 16-bit handlers. + * + PE32 - Protected mode running 32-bit code, 32-bit TSS and 32-bit handlers. + * + PEV86 - Protected mode running v8086 code, 32-bit TSS and 32-bit handlers. + * + PP16 - 386 paged mode running 16-bit code, 16-bit TSS and 16-bit handlers. + * + PP32 - 386 paged mode running 32-bit code, 32-bit TSS and 32-bit handlers. + * + PPV86 - 386 paged mode running v8086 code, 32-bit TSS and 32-bit handlers. + * + PAE16 - PAE paged mode running 16-bit code, 16-bit TSS and 16-bit handlers. + * + PAE32 - PAE paged mode running 32-bit code, 32-bit TSS and 32-bit handlers. + * + PAEV86 - PAE paged mode running v8086 code, 32-bit TSS and 32-bit handlers. + * + LM16 - AMD64 long mode running 16-bit code, 64-bit TSS and 64-bit handlers. + * + LM32 - AMD64 long mode running 32-bit code, 64-bit TSS and 64-bit handlers. + * + LM64 - AMD64 long mode running 64-bit code, 64-bit TSS and 64-bit handlers. + * + * The weird ones: + * + PE16_32 - Protected mode running 16-bit code, 16-bit TSS and 16-bit handlers. + * + PE16_V86 - Protected mode running 16-bit code, 16-bit TSS and 16-bit handlers. + * + PE32_16 - Protected mode running 32-bit code, 32-bit TSS and 32-bit handlers. + * + PP16_32 - 386 paged mode running 16-bit code, 16-bit TSS and 16-bit handlers. + * + PP16_V86 - 386 paged mode running 16-bit code, 16-bit TSS and 16-bit handlers. + * + PP32_16 - 386 paged mode running 32-bit code, 32-bit TSS and 32-bit handlers. + * + PAE16_32 - PAE paged mode running 16-bit code, 16-bit TSS and 16-bit handlers. + * + PAE16_V86 - PAE paged mode running 16-bit code, 16-bit TSS and 16-bit handlers. + * + PAE32_16 - PAE paged mode running 32-bit code, 32-bit TSS and 32-bit handlers. + * + * Actually, the PE32_16, PP32_16 and PAE32_16 modes aren't all that weird and fits in + * right next to LM16 and LM32, but this is the way it ended up. :-) + * + */ + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-mangling-code-define.h b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-mangling-code-define.h new file mode 100644 index 00000000..96946e25 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-mangling-code-define.h @@ -0,0 +1,256 @@ +/* $Id: bs3kit-mangling-code-define.h $ */ +/** @file + * BS3Kit - Function needing mangling - generated by the bs3kit-mangling-code-define.h makefile rule. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#define Bs3A20Disable BS3_CMN_MANGLER(Bs3A20Disable) +#define Bs3A20DisableViaKbd BS3_CMN_MANGLER(Bs3A20DisableViaKbd) +#define Bs3A20DisableViaPortA BS3_CMN_MANGLER(Bs3A20DisableViaPortA) +#define Bs3A20Enable BS3_CMN_MANGLER(Bs3A20Enable) +#define Bs3A20EnableViaKbd BS3_CMN_MANGLER(Bs3A20EnableViaKbd) +#define Bs3A20EnableViaPortA BS3_CMN_MANGLER(Bs3A20EnableViaPortA) +#define Bs3ExtCtxAlloc BS3_CMN_MANGLER(Bs3ExtCtxAlloc) +#define Bs3ExtCtxCopy BS3_CMN_MANGLER(Bs3ExtCtxCopy) +#define Bs3ExtCtxFree BS3_CMN_MANGLER(Bs3ExtCtxFree) +#define Bs3ExtCtxGetAbridgedFtw BS3_CMN_MANGLER(Bs3ExtCtxGetAbridgedFtw) +#define Bs3ExtCtxGetFcw BS3_CMN_MANGLER(Bs3ExtCtxGetFcw) +#define Bs3ExtCtxGetFsw BS3_CMN_MANGLER(Bs3ExtCtxGetFsw) +#define Bs3ExtCtxGetMm BS3_CMN_MANGLER(Bs3ExtCtxGetMm) +#define Bs3ExtCtxGetMxCsr BS3_CMN_MANGLER(Bs3ExtCtxGetMxCsr) +#define Bs3ExtCtxGetMxCsrMask BS3_CMN_MANGLER(Bs3ExtCtxGetMxCsrMask) +#define Bs3ExtCtxGetSize BS3_CMN_MANGLER(Bs3ExtCtxGetSize) +#define Bs3ExtCtxGetXmm BS3_CMN_MANGLER(Bs3ExtCtxGetXmm) +#define Bs3ExtCtxGetYmm BS3_CMN_MANGLER(Bs3ExtCtxGetYmm) +#define Bs3ExtCtxInit BS3_CMN_MANGLER(Bs3ExtCtxInit) +#define Bs3ExtCtxRestore BS3_CMN_MANGLER(Bs3ExtCtxRestore) +#define Bs3ExtCtxRestoreEx BS3_CMN_MANGLER(Bs3ExtCtxRestoreEx) +#define Bs3ExtCtxSave BS3_CMN_MANGLER(Bs3ExtCtxSave) +#define Bs3ExtCtxSaveEx BS3_CMN_MANGLER(Bs3ExtCtxSaveEx) +#define Bs3ExtCtxSetAbridgedFtw BS3_CMN_MANGLER(Bs3ExtCtxSetAbridgedFtw) +#define Bs3ExtCtxSetFcw BS3_CMN_MANGLER(Bs3ExtCtxSetFcw) +#define Bs3ExtCtxSetFsw BS3_CMN_MANGLER(Bs3ExtCtxSetFsw) +#define Bs3ExtCtxSetMm BS3_CMN_MANGLER(Bs3ExtCtxSetMm) +#define Bs3ExtCtxSetMxCsr BS3_CMN_MANGLER(Bs3ExtCtxSetMxCsr) +#define Bs3ExtCtxSetMxCsrMask BS3_CMN_MANGLER(Bs3ExtCtxSetMxCsrMask) +#define Bs3ExtCtxSetXmm BS3_CMN_MANGLER(Bs3ExtCtxSetXmm) +#define Bs3ExtCtxSetYmm BS3_CMN_MANGLER(Bs3ExtCtxSetYmm) +#define Bs3GetCpuVendor BS3_CMN_MANGLER(Bs3GetCpuVendor) +#define Bs3GetModeName BS3_CMN_MANGLER(Bs3GetModeName) +#define Bs3GetModeNameShortLower BS3_CMN_MANGLER(Bs3GetModeNameShortLower) +#define Bs3KbdRead BS3_CMN_MANGLER(Bs3KbdRead) +#define Bs3KbdWait BS3_CMN_MANGLER(Bs3KbdWait) +#define Bs3KbdWrite BS3_CMN_MANGLER(Bs3KbdWrite) +#define Bs3MemAlloc BS3_CMN_MANGLER(Bs3MemAlloc) +#define Bs3MemAllocZ BS3_CMN_MANGLER(Bs3MemAllocZ) +#define Bs3MemChr BS3_CMN_MANGLER(Bs3MemChr) +#define Bs3MemCmp BS3_CMN_MANGLER(Bs3MemCmp) +#define Bs3MemCpy BS3_CMN_MANGLER(Bs3MemCpy) +#define Bs3MemFree BS3_CMN_MANGLER(Bs3MemFree) +#define Bs3MemGuardedTestPageAlloc BS3_CMN_MANGLER(Bs3MemGuardedTestPageAlloc) +#define Bs3MemGuardedTestPageAllocEx BS3_CMN_MANGLER(Bs3MemGuardedTestPageAllocEx) +#define Bs3MemGuardedTestPageFree BS3_CMN_MANGLER(Bs3MemGuardedTestPageFree) +#define Bs3MemMove BS3_CMN_MANGLER(Bs3MemMove) +#define Bs3MemPCpy BS3_CMN_MANGLER(Bs3MemPCpy) +#define Bs3MemPrintInfo BS3_CMN_MANGLER(Bs3MemPrintInfo) +#define Bs3MemSet BS3_CMN_MANGLER(Bs3MemSet) +#define Bs3MemZero BS3_CMN_MANGLER(Bs3MemZero) +#define Bs3PagingAlias BS3_CMN_MANGLER(Bs3PagingAlias) +#define bs3PagingGetLegacyPte BS3_CMN_MANGLER(bs3PagingGetLegacyPte) +#define bs3PagingGetPaePte BS3_CMN_MANGLER(bs3PagingGetPaePte) +#define Bs3PagingGetPte BS3_CMN_MANGLER(Bs3PagingGetPte) +#define Bs3PagingInitRootForLM BS3_CMN_MANGLER(Bs3PagingInitRootForLM) +#define Bs3PagingInitRootForPAE BS3_CMN_MANGLER(Bs3PagingInitRootForPAE) +#define Bs3PagingInitRootForPP BS3_CMN_MANGLER(Bs3PagingInitRootForPP) +#define Bs3PagingMapRamAbove4GForLM BS3_CMN_MANGLER(Bs3PagingMapRamAbove4GForLM) +#define Bs3PagingProtect BS3_CMN_MANGLER(Bs3PagingProtect) +#define Bs3PagingProtectPtr BS3_CMN_MANGLER(Bs3PagingProtectPtr) +#define Bs3PagingQueryAddressInfo BS3_CMN_MANGLER(Bs3PagingQueryAddressInfo) +#define Bs3PagingSetupCanonicalTraps BS3_CMN_MANGLER(Bs3PagingSetupCanonicalTraps) +#define Bs3PagingUnalias BS3_CMN_MANGLER(Bs3PagingUnalias) +#define Bs3Panic BS3_CMN_MANGLER(Bs3Panic) +#define Bs3PicMaskAll BS3_CMN_MANGLER(Bs3PicMaskAll) +#define Bs3PicSetup BS3_CMN_MANGLER(Bs3PicSetup) +#define Bs3PicUpdateMask BS3_CMN_MANGLER(Bs3PicUpdateMask) +#define Bs3PitDisable BS3_CMN_MANGLER(Bs3PitDisable) +#define Bs3PitSetupAndEnablePeriodTimer BS3_CMN_MANGLER(Bs3PitSetupAndEnablePeriodTimer) +#define Bs3PrintChr BS3_CMN_MANGLER(Bs3PrintChr) +#define Bs3Printf BS3_CMN_MANGLER(Bs3Printf) +#define Bs3PrintfV BS3_CMN_MANGLER(Bs3PrintfV) +#define Bs3PrintStr BS3_CMN_MANGLER(Bs3PrintStr) +#define Bs3PrintStrN BS3_CMN_MANGLER(Bs3PrintStrN) +#define Bs3PrintU32 BS3_CMN_MANGLER(Bs3PrintU32) +#define Bs3PrintX32 BS3_CMN_MANGLER(Bs3PrintX32) +#define Bs3RegCtxConvertToRingX BS3_CMN_MANGLER(Bs3RegCtxConvertToRingX) +#define Bs3RegCtxConvertV86ToRm BS3_CMN_MANGLER(Bs3RegCtxConvertV86ToRm) +#define Bs3RegCtxGetRspSsAsCurPtr BS3_CMN_MANGLER(Bs3RegCtxGetRspSsAsCurPtr) +#define Bs3RegCtxPrint BS3_CMN_MANGLER(Bs3RegCtxPrint) +#define Bs3RegCtxRestore BS3_CMN_MANGLER(Bs3RegCtxRestore) +#define Bs3RegCtxSave BS3_CMN_MANGLER(Bs3RegCtxSave) +#define Bs3RegCtxSaveEx BS3_CMN_MANGLER(Bs3RegCtxSaveEx) +#define Bs3RegCtxSaveForMode BS3_CMN_MANGLER(Bs3RegCtxSaveForMode) +#define Bs3RegCtxSetGpr BS3_CMN_MANGLER(Bs3RegCtxSetGpr) +#define Bs3RegCtxSetGrpDsFromCurPtr BS3_CMN_MANGLER(Bs3RegCtxSetGrpDsFromCurPtr) +#define Bs3RegCtxSetGrpSegFromCurPtr BS3_CMN_MANGLER(Bs3RegCtxSetGrpSegFromCurPtr) +#define Bs3RegCtxSetGrpSegFromFlat BS3_CMN_MANGLER(Bs3RegCtxSetGrpSegFromFlat) +#define Bs3RegCtxSetRipCsFromCurPtr BS3_CMN_MANGLER(Bs3RegCtxSetRipCsFromCurPtr) +#define Bs3RegCtxSetRipCsFromFlat BS3_CMN_MANGLER(Bs3RegCtxSetRipCsFromFlat) +#define Bs3RegCtxSetRipCsFromLnkPtr BS3_CMN_MANGLER(Bs3RegCtxSetRipCsFromLnkPtr) +#define Bs3RegGetCr0 BS3_CMN_MANGLER(Bs3RegGetCr0) +#define Bs3RegGetCr2 BS3_CMN_MANGLER(Bs3RegGetCr2) +#define Bs3RegGetCr3 BS3_CMN_MANGLER(Bs3RegGetCr3) +#define Bs3RegGetCr4 BS3_CMN_MANGLER(Bs3RegGetCr4) +#define Bs3RegGetDr0 BS3_CMN_MANGLER(Bs3RegGetDr0) +#define Bs3RegGetDr1 BS3_CMN_MANGLER(Bs3RegGetDr1) +#define Bs3RegGetDr2 BS3_CMN_MANGLER(Bs3RegGetDr2) +#define Bs3RegGetDr3 BS3_CMN_MANGLER(Bs3RegGetDr3) +#define Bs3RegGetDr6 BS3_CMN_MANGLER(Bs3RegGetDr6) +#define Bs3RegGetDr7 BS3_CMN_MANGLER(Bs3RegGetDr7) +#define Bs3RegGetDrX BS3_CMN_MANGLER(Bs3RegGetDrX) +#define Bs3RegGetLdtr BS3_CMN_MANGLER(Bs3RegGetLdtr) +#define Bs3RegGetTr BS3_CMN_MANGLER(Bs3RegGetTr) +#define Bs3RegGetXcr0 BS3_CMN_MANGLER(Bs3RegGetXcr0) +#define Bs3RegSetCr0 BS3_CMN_MANGLER(Bs3RegSetCr0) +#define Bs3RegSetCr2 BS3_CMN_MANGLER(Bs3RegSetCr2) +#define Bs3RegSetCr3 BS3_CMN_MANGLER(Bs3RegSetCr3) +#define Bs3RegSetCr4 BS3_CMN_MANGLER(Bs3RegSetCr4) +#define Bs3RegSetDr0 BS3_CMN_MANGLER(Bs3RegSetDr0) +#define Bs3RegSetDr1 BS3_CMN_MANGLER(Bs3RegSetDr1) +#define Bs3RegSetDr2 BS3_CMN_MANGLER(Bs3RegSetDr2) +#define Bs3RegSetDr3 BS3_CMN_MANGLER(Bs3RegSetDr3) +#define Bs3RegSetDr6 BS3_CMN_MANGLER(Bs3RegSetDr6) +#define Bs3RegSetDr7 BS3_CMN_MANGLER(Bs3RegSetDr7) +#define Bs3RegSetDrX BS3_CMN_MANGLER(Bs3RegSetDrX) +#define Bs3RegSetLdtr BS3_CMN_MANGLER(Bs3RegSetLdtr) +#define Bs3RegSetTr BS3_CMN_MANGLER(Bs3RegSetTr) +#define Bs3RegSetXcr0 BS3_CMN_MANGLER(Bs3RegSetXcr0) +#define Bs3SelFar32ToFlat32 BS3_CMN_MANGLER(Bs3SelFar32ToFlat32) +#define Bs3SelFar32ToFlat32NoClobber BS3_CMN_MANGLER(Bs3SelFar32ToFlat32NoClobber) +#define Bs3SelFlatCodeToProtFar16 BS3_CMN_MANGLER(Bs3SelFlatCodeToProtFar16) +#define Bs3SelFlatCodeToRealMode BS3_CMN_MANGLER(Bs3SelFlatCodeToRealMode) +#define Bs3SelFlatDataToProtFar16 BS3_CMN_MANGLER(Bs3SelFlatDataToProtFar16) +#define Bs3SelFlatDataToRealMode BS3_CMN_MANGLER(Bs3SelFlatDataToRealMode) +#define Bs3SelLnkPtrToCurPtr BS3_CMN_MANGLER(Bs3SelLnkPtrToCurPtr) +#define Bs3SelLnkPtrToFlat BS3_CMN_MANGLER(Bs3SelLnkPtrToFlat) +#define Bs3SelProtFar16DataToFlat BS3_CMN_MANGLER(Bs3SelProtFar16DataToFlat) +#define Bs3SelProtFar16DataToRealMode BS3_CMN_MANGLER(Bs3SelProtFar16DataToRealMode) +#define Bs3SelProtFar32ToFlat32 BS3_CMN_MANGLER(Bs3SelProtFar32ToFlat32) +#define Bs3SelProtModeCodeToRealMode BS3_CMN_MANGLER(Bs3SelProtModeCodeToRealMode) +#define Bs3SelRealModeCodeToFlat BS3_CMN_MANGLER(Bs3SelRealModeCodeToFlat) +#define Bs3SelRealModeCodeToProtMode BS3_CMN_MANGLER(Bs3SelRealModeCodeToProtMode) +#define Bs3SelRealModeDataToFlat BS3_CMN_MANGLER(Bs3SelRealModeDataToFlat) +#define Bs3SelRealModeDataToProtFar16 BS3_CMN_MANGLER(Bs3SelRealModeDataToProtFar16) +#define Bs3SelSetup16BitCode BS3_CMN_MANGLER(Bs3SelSetup16BitCode) +#define Bs3SelSetup16BitData BS3_CMN_MANGLER(Bs3SelSetup16BitData) +#define Bs3SelSetup32BitCode BS3_CMN_MANGLER(Bs3SelSetup32BitCode) +#define Bs3SelSetupGate64 BS3_CMN_MANGLER(Bs3SelSetupGate64) +#define Bs3SelSetupGate BS3_CMN_MANGLER(Bs3SelSetupGate) +#define Bs3Shutdown BS3_CMN_MANGLER(Bs3Shutdown) +#define Bs3SlabAlloc BS3_CMN_MANGLER(Bs3SlabAlloc) +#define Bs3SlabAllocEx BS3_CMN_MANGLER(Bs3SlabAllocEx) +#define Bs3SlabFree BS3_CMN_MANGLER(Bs3SlabFree) +#define Bs3SlabInit BS3_CMN_MANGLER(Bs3SlabInit) +#define Bs3SlabListAdd BS3_CMN_MANGLER(Bs3SlabListAdd) +#define Bs3SlabListAlloc BS3_CMN_MANGLER(Bs3SlabListAlloc) +#define Bs3SlabListAllocEx BS3_CMN_MANGLER(Bs3SlabListAllocEx) +#define Bs3SlabListFree BS3_CMN_MANGLER(Bs3SlabListFree) +#define Bs3SlabListInit BS3_CMN_MANGLER(Bs3SlabListInit) +#define Bs3StrCpy BS3_CMN_MANGLER(Bs3StrCpy) +#define Bs3StrFormatV BS3_CMN_MANGLER(Bs3StrFormatV) +#define Bs3StrLen BS3_CMN_MANGLER(Bs3StrLen) +#define Bs3StrNLen BS3_CMN_MANGLER(Bs3StrNLen) +#define Bs3StrPrintf BS3_CMN_MANGLER(Bs3StrPrintf) +#define Bs3StrPrintfV BS3_CMN_MANGLER(Bs3StrPrintfV) +#define Bs3SwitchFromV86To16BitAndCallC BS3_CMN_MANGLER(Bs3SwitchFromV86To16BitAndCallC) +#define Bs3TestCheckExtCtx BS3_CMN_MANGLER(Bs3TestCheckExtCtx) +#define Bs3TestCheckRegCtxEx BS3_CMN_MANGLER(Bs3TestCheckRegCtxEx) +#define Bs3TestFailed BS3_CMN_MANGLER(Bs3TestFailed) +#define Bs3TestFailedF BS3_CMN_MANGLER(Bs3TestFailedF) +#define Bs3TestFailedV BS3_CMN_MANGLER(Bs3TestFailedV) +#define Bs3TestHostPrintf BS3_CMN_MANGLER(Bs3TestHostPrintf) +#define Bs3TestHostPrintfV BS3_CMN_MANGLER(Bs3TestHostPrintfV) +#define Bs3TestInit BS3_CMN_MANGLER(Bs3TestInit) +#define Bs3TestNow BS3_CMN_MANGLER(Bs3TestNow) +#define Bs3TestPrintf BS3_CMN_MANGLER(Bs3TestPrintf) +#define Bs3TestPrintfV BS3_CMN_MANGLER(Bs3TestPrintfV) +#define Bs3TestQueryCfgBool BS3_CMN_MANGLER(Bs3TestQueryCfgBool) +#define Bs3TestQueryCfgU32 BS3_CMN_MANGLER(Bs3TestQueryCfgU32) +#define Bs3TestQueryCfgU8 BS3_CMN_MANGLER(Bs3TestQueryCfgU8) +#define Bs3TestSkipped BS3_CMN_MANGLER(Bs3TestSkipped) +#define Bs3TestSkippedF BS3_CMN_MANGLER(Bs3TestSkippedF) +#define Bs3TestSkippedV BS3_CMN_MANGLER(Bs3TestSkippedV) +#define Bs3TestSub BS3_CMN_MANGLER(Bs3TestSub) +#define Bs3TestSubDone BS3_CMN_MANGLER(Bs3TestSubDone) +#define Bs3TestSubErrorCount BS3_CMN_MANGLER(Bs3TestSubErrorCount) +#define Bs3TestSubF BS3_CMN_MANGLER(Bs3TestSubF) +#define Bs3TestSubV BS3_CMN_MANGLER(Bs3TestSubV) +#define Bs3TestTerm BS3_CMN_MANGLER(Bs3TestTerm) +#define Bs3TestValue BS3_CMN_MANGLER(Bs3TestValue) +#define Bs3Trap16Init BS3_CMN_MANGLER(Bs3Trap16Init) +#define Bs3Trap16InitEx BS3_CMN_MANGLER(Bs3Trap16InitEx) +#define Bs3Trap16SetGate BS3_CMN_MANGLER(Bs3Trap16SetGate) +#define Bs3Trap32Init BS3_CMN_MANGLER(Bs3Trap32Init) +#define Bs3Trap32SetGate BS3_CMN_MANGLER(Bs3Trap32SetGate) +#define Bs3Trap64Init BS3_CMN_MANGLER(Bs3Trap64Init) +#define Bs3Trap64InitEx BS3_CMN_MANGLER(Bs3Trap64InitEx) +#define Bs3Trap64SetGate BS3_CMN_MANGLER(Bs3Trap64SetGate) +#define Bs3TrapDefaultHandler BS3_CMN_MANGLER(Bs3TrapDefaultHandler) +#define Bs3TrapPrintFrame BS3_CMN_MANGLER(Bs3TrapPrintFrame) +#define Bs3TrapReInit BS3_CMN_MANGLER(Bs3TrapReInit) +#define Bs3TrapRmV86Init BS3_CMN_MANGLER(Bs3TrapRmV86Init) +#define Bs3TrapRmV86InitEx BS3_CMN_MANGLER(Bs3TrapRmV86InitEx) +#define Bs3TrapRmV86SetGate BS3_CMN_MANGLER(Bs3TrapRmV86SetGate) +#define Bs3TrapSetDpl BS3_CMN_MANGLER(Bs3TrapSetDpl) +#define Bs3TrapSetHandler BS3_CMN_MANGLER(Bs3TrapSetHandler) +#define Bs3TrapSetHandlerEx BS3_CMN_MANGLER(Bs3TrapSetHandlerEx) +#define Bs3TrapSetJmpAndRestore BS3_CMN_MANGLER(Bs3TrapSetJmpAndRestore) +#define Bs3TrapSetJmpAndRestoreInRm BS3_CMN_MANGLER(Bs3TrapSetJmpAndRestoreInRm) +#define Bs3TrapSetJmpAndRestoreWithExtCtxAndRm BS3_CMN_MANGLER(Bs3TrapSetJmpAndRestoreWithExtCtxAndRm) +#define Bs3TrapSetJmpAndRestoreWithExtCtx BS3_CMN_MANGLER(Bs3TrapSetJmpAndRestoreWithExtCtx) +#define Bs3TrapSetJmpAndRestoreWithRm BS3_CMN_MANGLER(Bs3TrapSetJmpAndRestoreWithRm) +#define Bs3TrapSetJmp BS3_CMN_MANGLER(Bs3TrapSetJmp) +#define Bs3TrapUnsetJmp BS3_CMN_MANGLER(Bs3TrapUnsetJmp) +#define Bs3UInt32Div BS3_CMN_MANGLER(Bs3UInt32Div) +#define Bs3UInt64Div BS3_CMN_MANGLER(Bs3UInt64Div) +#define Bs3UtilSetFullGdtr BS3_CMN_MANGLER(Bs3UtilSetFullGdtr) +#define Bs3UtilSetFullIdtr BS3_CMN_MANGLER(Bs3UtilSetFullIdtr) +#ifndef BS3_CMN_ONLY +# define Bs3BiosInt15h88 BS3_MODE_MANGLER(Bs3BiosInt15h88) +# define Bs3BiosInt15hE820 BS3_MODE_MANGLER(Bs3BiosInt15hE820) +# define Bs3CpuDetect BS3_MODE_MANGLER(Bs3CpuDetect) +# define Bs3SwitchTo32BitAndCallC BS3_MODE_MANGLER(Bs3SwitchTo32BitAndCallC) +# define Bs3TestDoModes BS3_MODE_MANGLER(Bs3TestDoModes) +# define Bs3TestDoModesByMax BS3_MODE_MANGLER(Bs3TestDoModesByMax) +# define Bs3TestDoModesByOne BS3_MODE_MANGLER(Bs3TestDoModesByOne) +# define Bs3TrapInit BS3_MODE_MANGLER(Bs3TrapInit) +#endif /* !BS3_CMN_ONLY */ diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-mangling-code-undef.h b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-mangling-code-undef.h new file mode 100644 index 00000000..1347d303 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-mangling-code-undef.h @@ -0,0 +1,256 @@ +/* $Id: bs3kit-mangling-code-undef.h $ */ +/** @file + * BS3Kit - Undefining function mangling - automatically generated by the bs3kit-mangling-code-undef.h makefile rule. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#undef Bs3A20Disable +#undef Bs3A20DisableViaKbd +#undef Bs3A20DisableViaPortA +#undef Bs3A20Enable +#undef Bs3A20EnableViaKbd +#undef Bs3A20EnableViaPortA +#undef Bs3ExtCtxAlloc +#undef Bs3ExtCtxCopy +#undef Bs3ExtCtxFree +#undef Bs3ExtCtxGetAbridgedFtw +#undef Bs3ExtCtxGetFcw +#undef Bs3ExtCtxGetFsw +#undef Bs3ExtCtxGetMm +#undef Bs3ExtCtxGetMxCsr +#undef Bs3ExtCtxGetMxCsrMask +#undef Bs3ExtCtxGetSize +#undef Bs3ExtCtxGetXmm +#undef Bs3ExtCtxGetYmm +#undef Bs3ExtCtxInit +#undef Bs3ExtCtxRestore +#undef Bs3ExtCtxRestoreEx +#undef Bs3ExtCtxSave +#undef Bs3ExtCtxSaveEx +#undef Bs3ExtCtxSetAbridgedFtw +#undef Bs3ExtCtxSetFcw +#undef Bs3ExtCtxSetFsw +#undef Bs3ExtCtxSetMm +#undef Bs3ExtCtxSetMxCsr +#undef Bs3ExtCtxSetMxCsrMask +#undef Bs3ExtCtxSetXmm +#undef Bs3ExtCtxSetYmm +#undef Bs3GetCpuVendor +#undef Bs3GetModeName +#undef Bs3GetModeNameShortLower +#undef Bs3KbdRead +#undef Bs3KbdWait +#undef Bs3KbdWrite +#undef Bs3MemAlloc +#undef Bs3MemAllocZ +#undef Bs3MemChr +#undef Bs3MemCmp +#undef Bs3MemCpy +#undef Bs3MemFree +#undef Bs3MemGuardedTestPageAlloc +#undef Bs3MemGuardedTestPageAllocEx +#undef Bs3MemGuardedTestPageFree +#undef Bs3MemMove +#undef Bs3MemPCpy +#undef Bs3MemPrintInfo +#undef Bs3MemSet +#undef Bs3MemZero +#undef Bs3PagingAlias +#undef bs3PagingGetLegacyPte +#undef bs3PagingGetPaePte +#undef Bs3PagingGetPte +#undef Bs3PagingInitRootForLM +#undef Bs3PagingInitRootForPAE +#undef Bs3PagingInitRootForPP +#undef Bs3PagingMapRamAbove4GForLM +#undef Bs3PagingProtect +#undef Bs3PagingProtectPtr +#undef Bs3PagingQueryAddressInfo +#undef Bs3PagingSetupCanonicalTraps +#undef Bs3PagingUnalias +#undef Bs3Panic +#undef Bs3PicMaskAll +#undef Bs3PicSetup +#undef Bs3PicUpdateMask +#undef Bs3PitDisable +#undef Bs3PitSetupAndEnablePeriodTimer +#undef Bs3PrintChr +#undef Bs3Printf +#undef Bs3PrintfV +#undef Bs3PrintStr +#undef Bs3PrintStrN +#undef Bs3PrintU32 +#undef Bs3PrintX32 +#undef Bs3RegCtxConvertToRingX +#undef Bs3RegCtxConvertV86ToRm +#undef Bs3RegCtxGetRspSsAsCurPtr +#undef Bs3RegCtxPrint +#undef Bs3RegCtxRestore +#undef Bs3RegCtxSave +#undef Bs3RegCtxSaveEx +#undef Bs3RegCtxSaveForMode +#undef Bs3RegCtxSetGpr +#undef Bs3RegCtxSetGrpDsFromCurPtr +#undef Bs3RegCtxSetGrpSegFromCurPtr +#undef Bs3RegCtxSetGrpSegFromFlat +#undef Bs3RegCtxSetRipCsFromCurPtr +#undef Bs3RegCtxSetRipCsFromFlat +#undef Bs3RegCtxSetRipCsFromLnkPtr +#undef Bs3RegGetCr0 +#undef Bs3RegGetCr2 +#undef Bs3RegGetCr3 +#undef Bs3RegGetCr4 +#undef Bs3RegGetDr0 +#undef Bs3RegGetDr1 +#undef Bs3RegGetDr2 +#undef Bs3RegGetDr3 +#undef Bs3RegGetDr6 +#undef Bs3RegGetDr7 +#undef Bs3RegGetDrX +#undef Bs3RegGetLdtr +#undef Bs3RegGetTr +#undef Bs3RegGetXcr0 +#undef Bs3RegSetCr0 +#undef Bs3RegSetCr2 +#undef Bs3RegSetCr3 +#undef Bs3RegSetCr4 +#undef Bs3RegSetDr0 +#undef Bs3RegSetDr1 +#undef Bs3RegSetDr2 +#undef Bs3RegSetDr3 +#undef Bs3RegSetDr6 +#undef Bs3RegSetDr7 +#undef Bs3RegSetDrX +#undef Bs3RegSetLdtr +#undef Bs3RegSetTr +#undef Bs3RegSetXcr0 +#undef Bs3SelFar32ToFlat32 +#undef Bs3SelFar32ToFlat32NoClobber +#undef Bs3SelFlatCodeToProtFar16 +#undef Bs3SelFlatCodeToRealMode +#undef Bs3SelFlatDataToProtFar16 +#undef Bs3SelFlatDataToRealMode +#undef Bs3SelLnkPtrToCurPtr +#undef Bs3SelLnkPtrToFlat +#undef Bs3SelProtFar16DataToFlat +#undef Bs3SelProtFar16DataToRealMode +#undef Bs3SelProtFar32ToFlat32 +#undef Bs3SelProtModeCodeToRealMode +#undef Bs3SelRealModeCodeToFlat +#undef Bs3SelRealModeCodeToProtMode +#undef Bs3SelRealModeDataToFlat +#undef Bs3SelRealModeDataToProtFar16 +#undef Bs3SelSetup16BitCode +#undef Bs3SelSetup16BitData +#undef Bs3SelSetup32BitCode +#undef Bs3SelSetupGate64 +#undef Bs3SelSetupGate +#undef Bs3Shutdown +#undef Bs3SlabAlloc +#undef Bs3SlabAllocEx +#undef Bs3SlabFree +#undef Bs3SlabInit +#undef Bs3SlabListAdd +#undef Bs3SlabListAlloc +#undef Bs3SlabListAllocEx +#undef Bs3SlabListFree +#undef Bs3SlabListInit +#undef Bs3StrCpy +#undef Bs3StrFormatV +#undef Bs3StrLen +#undef Bs3StrNLen +#undef Bs3StrPrintf +#undef Bs3StrPrintfV +#undef Bs3SwitchFromV86To16BitAndCallC +#undef Bs3TestCheckExtCtx +#undef Bs3TestCheckRegCtxEx +#undef Bs3TestFailed +#undef Bs3TestFailedF +#undef Bs3TestFailedV +#undef Bs3TestHostPrintf +#undef Bs3TestHostPrintfV +#undef Bs3TestInit +#undef Bs3TestNow +#undef Bs3TestPrintf +#undef Bs3TestPrintfV +#undef Bs3TestQueryCfgBool +#undef Bs3TestQueryCfgU32 +#undef Bs3TestQueryCfgU8 +#undef Bs3TestSkipped +#undef Bs3TestSkippedF +#undef Bs3TestSkippedV +#undef Bs3TestSub +#undef Bs3TestSubDone +#undef Bs3TestSubErrorCount +#undef Bs3TestSubF +#undef Bs3TestSubV +#undef Bs3TestTerm +#undef Bs3TestValue +#undef Bs3Trap16Init +#undef Bs3Trap16InitEx +#undef Bs3Trap16SetGate +#undef Bs3Trap32Init +#undef Bs3Trap32SetGate +#undef Bs3Trap64Init +#undef Bs3Trap64InitEx +#undef Bs3Trap64SetGate +#undef Bs3TrapDefaultHandler +#undef Bs3TrapPrintFrame +#undef Bs3TrapReInit +#undef Bs3TrapRmV86Init +#undef Bs3TrapRmV86InitEx +#undef Bs3TrapRmV86SetGate +#undef Bs3TrapSetDpl +#undef Bs3TrapSetHandler +#undef Bs3TrapSetHandlerEx +#undef Bs3TrapSetJmpAndRestore +#undef Bs3TrapSetJmpAndRestoreInRm +#undef Bs3TrapSetJmpAndRestoreWithExtCtxAndRm +#undef Bs3TrapSetJmpAndRestoreWithExtCtx +#undef Bs3TrapSetJmpAndRestoreWithRm +#undef Bs3TrapSetJmp +#undef Bs3TrapUnsetJmp +#undef Bs3UInt32Div +#undef Bs3UInt64Div +#undef Bs3UtilSetFullGdtr +#undef Bs3UtilSetFullIdtr +#ifndef BS3_CMN_ONLY +# undef Bs3BiosInt15h88 +# undef Bs3BiosInt15hE820 +# undef Bs3CpuDetect +# undef Bs3SwitchTo32BitAndCallC +# undef Bs3TestDoModes +# undef Bs3TestDoModesByMax +# undef Bs3TestDoModesByOne +# undef Bs3TrapInit +#endif /* !BS3_CMN_ONLY */ diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-mangling-code.h b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-mangling-code.h new file mode 100644 index 00000000..9650c44b --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-mangling-code.h @@ -0,0 +1,52 @@ +/* $Id: bs3kit-mangling-code.h $ */ +/** @file + * BS3Kit - Symbol mangling, code. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/* + * Do function mangling. This can be redone at compile time (templates). + */ +#undef BS3_CMN_MANGLER +#undef BS3_MODE_MANGLER +#if ARCH_BITS != 16 || !defined(BS3_USE_ALT_16BIT_TEXT_SEG) +# define BS3_CMN_MANGLER(a_Function) BS3_CMN_NM(a_Function) +# define BS3_MODE_MANGLER(a_Function) TMPL_NM(a_Function) +#else +# define BS3_CMN_MANGLER(a_Function) BS3_CMN_FAR_NM(a_Function) +# define BS3_MODE_MANGLER(a_Function) TMPL_FAR_NM(a_Function) +#endif +#include "bs3kit-mangling-code-undef.h" +#include "bs3kit-mangling-code-define.h" + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-mangling-data.h b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-mangling-data.h new file mode 100644 index 00000000..e6a30afe --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-mangling-data.h @@ -0,0 +1,295 @@ +/* $Id: bs3kit-mangling-data.h $ */ +/** @file + * BS3Kit - Symbol mangling. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/* + * First part is only applied once. It concerns itself with data symbols. + */ + +#ifndef BS3KIT_INCLUDED_bs3kit_mangling_data_h +#define BS3KIT_INCLUDED_bs3kit_mangling_data_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#if 0 /* the object converter deals with this now */ +#if ARCH_BITS == 64 + +# define Bs3Gdt BS3_DATA_NM(Bs3Gdt) +# define Bs3Gdt_Ldt BS3_DATA_NM(Bs3Gdt_Ldt) +# define Bs3Gdte_Tss16 BS3_DATA_NM(Bs3Gdte_Tss16) +# define Bs3Gdte_Tss16DoubleFault BS3_DATA_NM(Bs3Gdte_Tss16DoubleFault) +# define Bs3Gdte_Tss16Spare0 BS3_DATA_NM(Bs3Gdte_Tss16Spare0) +# define Bs3Gdte_Tss16Spare1 BS3_DATA_NM(Bs3Gdte_Tss16Spare1) +# define Bs3Gdte_Tss32 BS3_DATA_NM(Bs3Gdte_Tss32) +# define Bs3Gdte_Tss32DoubleFault BS3_DATA_NM(Bs3Gdte_Tss32DoubleFault) +# define Bs3Gdte_Tss32Spare0 BS3_DATA_NM(Bs3Gdte_Tss32Spare0) +# define Bs3Gdte_Tss32Spare1 BS3_DATA_NM(Bs3Gdte_Tss32Spare1) +# define Bs3Gdte_Tss32IobpIntRedirBm BS3_DATA_NM(Bs3Gdte_Tss32IobpIntRedirBm) +# define Bs3Gdte_Tss32IntRedirBm BS3_DATA_NM(Bs3Gdte_Tss32IntRedirBm) +# define Bs3Gdte_Tss64 BS3_DATA_NM(Bs3Gdte_Tss64) +# define Bs3Gdte_Tss64Spare0 BS3_DATA_NM(Bs3Gdte_Tss64Spare0) +# define Bs3Gdte_Tss64Spare1 BS3_DATA_NM(Bs3Gdte_Tss64Spare1) +# define Bs3Gdte_Tss64Iobp BS3_DATA_NM(Bs3Gdte_Tss64Iobp) +# define Bs3Gdte_RMTEXT16_CS BS3_DATA_NM(Bs3Gdte_RMTEXT16_CS) +# define Bs3Gdte_X0TEXT16_CS BS3_DATA_NM(Bs3Gdte_X0TEXT16_CS) +# define Bs3Gdte_X1TEXT16_CS BS3_DATA_NM(Bs3Gdte_X1TEXT16_CS) +# define Bs3Gdte_R0_MMIO16 BS3_DATA_NM(Bs3Gdte_R0_MMIO16) + +# define Bs3Gdte_R0_First BS3_DATA_NM(Bs3Gdte_R0_First) +# define Bs3Gdte_R0_CS16 BS3_DATA_NM(Bs3Gdte_R0_CS16) +# define Bs3Gdte_R0_DS16 BS3_DATA_NM(Bs3Gdte_R0_DS16) +# define Bs3Gdte_R0_SS16 BS3_DATA_NM(Bs3Gdte_R0_SS16) +# define Bs3Gdte_R0_CS32 BS3_DATA_NM(Bs3Gdte_R0_CS32) +# define Bs3Gdte_R0_DS32 BS3_DATA_NM(Bs3Gdte_R0_DS32) +# define Bs3Gdte_R0_SS32 BS3_DATA_NM(Bs3Gdte_R0_SS32) +# define Bs3Gdte_R0_CS64 BS3_DATA_NM(Bs3Gdte_R0_CS64) +# define Bs3Gdte_R0_DS64 BS3_DATA_NM(Bs3Gdte_R0_DS64) +# define Bs3Gdte_R0_CS16_EO BS3_DATA_NM(Bs3Gdte_R0_CS16_EO) +# define Bs3Gdte_R0_CS16_CNF BS3_DATA_NM(Bs3Gdte_R0_CS16_CNF) +# define Bs3Gdte_R0_CS16_CND_EO BS3_DATA_NM(Bs3Gdte_R0_CS16_CND_EO) +# define Bs3Gdte_R0_CS32_EO BS3_DATA_NM(Bs3Gdte_R0_CS32_EO) +# define Bs3Gdte_R0_CS32_CNF BS3_DATA_NM(Bs3Gdte_R0_CS32_CNF) +# define Bs3Gdte_R0_CS32_CNF_EO BS3_DATA_NM(Bs3Gdte_R0_CS32_CNF_EO) +# define Bs3Gdte_R0_CS64_EO BS3_DATA_NM(Bs3Gdte_R0_CS64_EO) +# define Bs3Gdte_R0_CS64_CNF BS3_DATA_NM(Bs3Gdte_R0_CS64_CNF) +# define Bs3Gdte_R0_CS64_CNF_EO BS3_DATA_NM(Bs3Gdte_R0_CS64_CNF_EO) + +# define Bs3Gdte_R1_First BS3_DATA_NM(Bs3Gdte_R1_First) +# define Bs3Gdte_R1_CS16 BS3_DATA_NM(Bs3Gdte_R1_CS16) +# define Bs3Gdte_R1_DS16 BS3_DATA_NM(Bs3Gdte_R1_DS16) +# define Bs3Gdte_R1_SS16 BS3_DATA_NM(Bs3Gdte_R1_SS16) +# define Bs3Gdte_R1_CS32 BS3_DATA_NM(Bs3Gdte_R1_CS32) +# define Bs3Gdte_R1_DS32 BS3_DATA_NM(Bs3Gdte_R1_DS32) +# define Bs3Gdte_R1_SS32 BS3_DATA_NM(Bs3Gdte_R1_SS32) +# define Bs3Gdte_R1_CS64 BS3_DATA_NM(Bs3Gdte_R1_CS64) +# define Bs3Gdte_R1_DS64 BS3_DATA_NM(Bs3Gdte_R1_DS64) +# define Bs3Gdte_R1_CS16_EO BS3_DATA_NM(Bs3Gdte_R1_CS16_EO) +# define Bs3Gdte_R1_CS16_CNF BS3_DATA_NM(Bs3Gdte_R1_CS16_CNF) +# define Bs3Gdte_R1_CS16_CND_EO BS3_DATA_NM(Bs3Gdte_R1_CS16_CND_EO) +# define Bs3Gdte_R1_CS32_EO BS3_DATA_NM(Bs3Gdte_R1_CS32_EO) +# define Bs3Gdte_R1_CS32_CNF BS3_DATA_NM(Bs3Gdte_R1_CS32_CNF) +# define Bs3Gdte_R1_CS32_CNF_EO BS3_DATA_NM(Bs3Gdte_R1_CS32_CNF_EO) +# define Bs3Gdte_R1_CS64_EO BS3_DATA_NM(Bs3Gdte_R1_CS64_EO) +# define Bs3Gdte_R1_CS64_CNF BS3_DATA_NM(Bs3Gdte_R1_CS64_CNF) +# define Bs3Gdte_R1_CS64_CNF_EO BS3_DATA_NM(Bs3Gdte_R1_CS64_CNF_EO) + +# define Bs3Gdte_R2_First BS3_DATA_NM(Bs3Gdte_R2_First) +# define Bs3Gdte_R2_CS16 BS3_DATA_NM(Bs3Gdte_R2_CS16) +# define Bs3Gdte_R2_DS16 BS3_DATA_NM(Bs3Gdte_R2_DS16) +# define Bs3Gdte_R2_SS16 BS3_DATA_NM(Bs3Gdte_R2_SS16) +# define Bs3Gdte_R2_CS32 BS3_DATA_NM(Bs3Gdte_R2_CS32) +# define Bs3Gdte_R2_DS32 BS3_DATA_NM(Bs3Gdte_R2_DS32) +# define Bs3Gdte_R2_SS32 BS3_DATA_NM(Bs3Gdte_R2_SS32) +# define Bs3Gdte_R2_CS64 BS3_DATA_NM(Bs3Gdte_R2_CS64) +# define Bs3Gdte_R2_DS64 BS3_DATA_NM(Bs3Gdte_R2_DS64) +# define Bs3Gdte_R2_CS16_EO BS3_DATA_NM(Bs3Gdte_R2_CS16_EO) +# define Bs3Gdte_R2_CS16_CNF BS3_DATA_NM(Bs3Gdte_R2_CS16_CNF) +# define Bs3Gdte_R2_CS16_CND_EO BS3_DATA_NM(Bs3Gdte_R2_CS16_CND_EO) +# define Bs3Gdte_R2_CS32_EO BS3_DATA_NM(Bs3Gdte_R2_CS32_EO) +# define Bs3Gdte_R2_CS32_CNF BS3_DATA_NM(Bs3Gdte_R2_CS32_CNF) +# define Bs3Gdte_R2_CS32_CNF_EO BS3_DATA_NM(Bs3Gdte_R2_CS32_CNF_EO) +# define Bs3Gdte_R2_CS64_EO BS3_DATA_NM(Bs3Gdte_R2_CS64_EO) +# define Bs3Gdte_R2_CS64_CNF BS3_DATA_NM(Bs3Gdte_R2_CS64_CNF) +# define Bs3Gdte_R2_CS64_CNF_EO BS3_DATA_NM(Bs3Gdte_R2_CS64_CNF_EO) + +# define Bs3Gdte_R3_First BS3_DATA_NM(Bs3Gdte_R3_First) +# define Bs3Gdte_R3_CS16 BS3_DATA_NM(Bs3Gdte_R3_CS16) +# define Bs3Gdte_R3_DS16 BS3_DATA_NM(Bs3Gdte_R3_DS16) +# define Bs3Gdte_R3_SS16 BS3_DATA_NM(Bs3Gdte_R3_SS16) +# define Bs3Gdte_R3_CS32 BS3_DATA_NM(Bs3Gdte_R3_CS32) +# define Bs3Gdte_R3_DS32 BS3_DATA_NM(Bs3Gdte_R3_DS32) +# define Bs3Gdte_R3_SS32 BS3_DATA_NM(Bs3Gdte_R3_SS32) +# define Bs3Gdte_R3_CS64 BS3_DATA_NM(Bs3Gdte_R3_CS64) +# define Bs3Gdte_R3_DS64 BS3_DATA_NM(Bs3Gdte_R3_DS64) +# define Bs3Gdte_R3_CS16_EO BS3_DATA_NM(Bs3Gdte_R3_CS16_EO) +# define Bs3Gdte_R3_CS16_CNF BS3_DATA_NM(Bs3Gdte_R3_CS16_CNF) +# define Bs3Gdte_R3_CS16_CND_EO BS3_DATA_NM(Bs3Gdte_R3_CS16_CND_EO) +# define Bs3Gdte_R3_CS32_EO BS3_DATA_NM(Bs3Gdte_R3_CS32_EO) +# define Bs3Gdte_R3_CS32_CNF BS3_DATA_NM(Bs3Gdte_R3_CS32_CNF) +# define Bs3Gdte_R3_CS32_CNF_EO BS3_DATA_NM(Bs3Gdte_R3_CS32_CNF_EO) +# define Bs3Gdte_R3_CS64_EO BS3_DATA_NM(Bs3Gdte_R3_CS64_EO) +# define Bs3Gdte_R3_CS64_CNF BS3_DATA_NM(Bs3Gdte_R3_CS64_CNF) +# define Bs3Gdte_R3_CS64_CNF_EO BS3_DATA_NM(Bs3Gdte_R3_CS64_CNF_EO) + +# define Bs3GdteSpare00 BS3_DATA_NM(Bs3GdteSpare00) +# define Bs3GdteSpare01 BS3_DATA_NM(Bs3GdteSpare01) +# define Bs3GdteSpare02 BS3_DATA_NM(Bs3GdteSpare02) +# define Bs3GdteSpare03 BS3_DATA_NM(Bs3GdteSpare03) +# define Bs3GdteSpare04 BS3_DATA_NM(Bs3GdteSpare04) +# define Bs3GdteSpare05 BS3_DATA_NM(Bs3GdteSpare05) +# define Bs3GdteSpare06 BS3_DATA_NM(Bs3GdteSpare06) +# define Bs3GdteSpare07 BS3_DATA_NM(Bs3GdteSpare07) +# define Bs3GdteSpare08 BS3_DATA_NM(Bs3GdteSpare08) +# define Bs3GdteSpare09 BS3_DATA_NM(Bs3GdteSpare09) +# define Bs3GdteSpare0a BS3_DATA_NM(Bs3GdteSpare0a) +# define Bs3GdteSpare0b BS3_DATA_NM(Bs3GdteSpare0b) +# define Bs3GdteSpare0c BS3_DATA_NM(Bs3GdteSpare0c) +# define Bs3GdteSpare0d BS3_DATA_NM(Bs3GdteSpare0d) +# define Bs3GdteSpare0e BS3_DATA_NM(Bs3GdteSpare0e) +# define Bs3GdteSpare0f BS3_DATA_NM(Bs3GdteSpare0f) +# define Bs3GdteSpare10 BS3_DATA_NM(Bs3GdteSpare10) +# define Bs3GdteSpare11 BS3_DATA_NM(Bs3GdteSpare11) +# define Bs3GdteSpare12 BS3_DATA_NM(Bs3GdteSpare12) +# define Bs3GdteSpare13 BS3_DATA_NM(Bs3GdteSpare13) +# define Bs3GdteSpare14 BS3_DATA_NM(Bs3GdteSpare14) +# define Bs3GdteSpare15 BS3_DATA_NM(Bs3GdteSpare15) +# define Bs3GdteSpare16 BS3_DATA_NM(Bs3GdteSpare16) +# define Bs3GdteSpare17 BS3_DATA_NM(Bs3GdteSpare17) +# define Bs3GdteSpare18 BS3_DATA_NM(Bs3GdteSpare18) +# define Bs3GdteSpare19 BS3_DATA_NM(Bs3GdteSpare19) +# define Bs3GdteSpare1a BS3_DATA_NM(Bs3GdteSpare1a) +# define Bs3GdteSpare1b BS3_DATA_NM(Bs3GdteSpare1b) +# define Bs3GdteSpare1c BS3_DATA_NM(Bs3GdteSpare1c) +# define Bs3GdteSpare1d BS3_DATA_NM(Bs3GdteSpare1d) +# define Bs3GdteSpare1e BS3_DATA_NM(Bs3GdteSpare1e) +# define Bs3GdteSpare1f BS3_DATA_NM(Bs3GdteSpare1f) + +# define Bs3GdteTiled BS3_DATA_NM(Bs3GdteTiled) +# define Bs3GdteFreePart1 BS3_DATA_NM(Bs3GdteFreePart1) +# define Bs3Gdte_CODE16 BS3_DATA_NM(Bs3Gdte_CODE16) +# define Bs3GdteFreePart2 BS3_DATA_NM(Bs3GdteFreePart2) +# define Bs3Gdte_SYSTEM16 BS3_DATA_NM(Bs3Gdte_SYSTEM16) +# define Bs3GdteFreePart3 BS3_DATA_NM(Bs3GdteFreePart3) +# define Bs3Gdte_DATA16 BS3_DATA_NM(Bs3Gdte_DATA16) + +# define Bs3GdteFreePart4 BS3_DATA_NM(Bs3GdteFreePart4) +# define Bs3GdtePreTestPage08 BS3_DATA_NM(Bs3GdtePreTestPage08) +# define Bs3GdtePreTestPage07 BS3_DATA_NM(Bs3GdtePreTestPage07) +# define Bs3GdtePreTestPage06 BS3_DATA_NM(Bs3GdtePreTestPage06) +# define Bs3GdtePreTestPage05 BS3_DATA_NM(Bs3GdtePreTestPage05) +# define Bs3GdtePreTestPage04 BS3_DATA_NM(Bs3GdtePreTestPage04) +# define Bs3GdtePreTestPage03 BS3_DATA_NM(Bs3GdtePreTestPage03) +# define Bs3GdtePreTestPage02 BS3_DATA_NM(Bs3GdtePreTestPage02) +# define Bs3GdtePreTestPage01 BS3_DATA_NM(Bs3GdtePreTestPage01) +# define Bs3GdteTestPage BS3_DATA_NM(Bs3GdteTestPage) +# define Bs3GdteTestPage00 BS3_DATA_NM(Bs3GdteTestPage00) +# define Bs3GdteTestPage01 BS3_DATA_NM(Bs3GdteTestPage01) +# define Bs3GdteTestPage02 BS3_DATA_NM(Bs3GdteTestPage02) +# define Bs3GdteTestPage03 BS3_DATA_NM(Bs3GdteTestPage03) +# define Bs3GdteTestPage04 BS3_DATA_NM(Bs3GdteTestPage04) +# define Bs3GdteTestPage05 BS3_DATA_NM(Bs3GdteTestPage05) +# define Bs3GdteTestPage06 BS3_DATA_NM(Bs3GdteTestPage06) +# define Bs3GdteTestPage07 BS3_DATA_NM(Bs3GdteTestPage07) + +# define Bs3GdtEnd BS3_DATA_NM(Bs3GdtEnd) + +# define Bs3Tss16 BS3_DATA_NM(Bs3Tss16) +# define Bs3Tss16DoubleFault BS3_DATA_NM(Bs3Tss16DoubleFault) +# define Bs3Tss16Spare0 BS3_DATA_NM(Bs3Tss16Spare0) +# define Bs3Tss16Spare1 BS3_DATA_NM(Bs3Tss16Spare1) +# define Bs3Tss32 BS3_DATA_NM(Bs3Tss32) +# define Bs3Tss32DoubleFault BS3_DATA_NM(Bs3Tss32DoubleFault) +# define Bs3Tss32Spare0 BS3_DATA_NM(Bs3Tss32Spare0) +# define Bs3Tss32Spare1 BS3_DATA_NM(Bs3Tss32Spare1) +# define Bs3Tss64 BS3_DATA_NM(Bs3Tss64) +# define Bs3Tss64Spare0 BS3_DATA_NM(Bs3Tss64Spare0) +# define Bs3Tss64Spare1 BS3_DATA_NM(Bs3Tss64Spare1) +# define Bs3Tss64WithIopb BS3_DATA_NM(Bs3Tss64WithIopb) +# define Bs3Tss32WithIopb BS3_DATA_NM(Bs3Tss32WithIopb) +# define Bs3SharedIntRedirBm BS3_DATA_NM(Bs3SharedIntRedirBm) +# define Bs3SharedIobp BS3_DATA_NM(Bs3SharedIobp) +# define Bs3SharedIobpEnd BS3_DATA_NM(Bs3SharedIobpEnd) +# define Bs3Idt16 BS3_DATA_NM(Bs3Idt16) +# define Bs3Idt32 BS3_DATA_NM(Bs3Idt32) +# define Bs3Idt64 BS3_DATA_NM(Bs3Idt64) +# define Bs3Lidt_Idt16 BS3_DATA_NM(Bs3Lidt_Idt16) +# define Bs3Lidt_Idt32 BS3_DATA_NM(Bs3Lidt_Idt32) +# define Bs3Lidt_Idt64 BS3_DATA_NM(Bs3Lidt_Idt64) +# define Bs3Lidt_Ivt BS3_DATA_NM(Bs3Lidt_Ivt) +# define Bs3Lgdt_Gdt BS3_DATA_NM(Bs3Lgdt_Gdt) +# define Bs3Ldt BS3_DATA_NM(Bs3Ldt) +# define Bs3LdtEnd BS3_DATA_NM(Bs3LdtEnd) + +# define Bs3Text16_StartOfSegment BS3_DATA_NM(Bs3Text16_StartOfSegment) +# define Bs3Text16_EndOfSegment BS3_DATA_NM(Bs3Text16_EndOfSegment) +# define Bs3Text16_Size BS3_DATA_NM(Bs3Text16_Size) + +# define Bs3System16_StartOfSegment BS3_DATA_NM(Bs3System16_StartOfSegment) +# define Bs3System16_EndOfSegment BS3_DATA_NM(Bs3System16_EndOfSegment) + +# define Bs3Data16_StartOfSegment BS3_DATA_NM(Bs3Data16_StartOfSegment) +# define Bs3Data16_EndOfSegment BS3_DATA_NM(Bs3Data16_EndOfSegment) + +# define Bs3RmText16_StartOfSegment BS3_DATA_NM(Bs3RmText16_StartOfSegment) +# define Bs3RmText16_EndOfSegment BS3_DATA_NM(Bs3RmText16_EndOfSegment) +# define Bs3RmText16_Size BS3_DATA_NM(Bs3RmText16_Size) +# define Bs3RmText16_FlatAddr BS3_DATA_NM(Bs3RmText16_FlatAddr) + +# define Bs3X0Text16_StartOfSegment BS3_DATA_NM(Bs3X0Text16_StartOfSegment) +# define Bs3X0Text16_EndOfSegment BS3_DATA_NM(Bs3X0Text16_EndOfSegment) +# define Bs3X0Text16_Size BS3_DATA_NM(Bs3X0Text16_Size) +# define Bs3X0Text16_FlatAddr BS3_DATA_NM(Bs3X0Text16_FlatAddr) + +# define Bs3X1Text16_StartOfSegment BS3_DATA_NM(Bs3X1Text16_StartOfSegment) +# define Bs3X1Text16_EndOfSegment BS3_DATA_NM(Bs3X1Text16_EndOfSegment) +# define Bs3X1Text16_Size BS3_DATA_NM(Bs3X1Text16_Size) +# define Bs3X1Text16_FlatAddr BS3_DATA_NM(Bs3X1Text16_FlatAddr) + +# define Bs3Text32_StartOfSegment BS3_DATA_NM(Bs3Text32_StartOfSegment) +# define Bs3Text32_EndOfSegment BS3_DATA_NM(Bs3Text32_EndOfSegment) + +# define Bs3Data32_StartOfSegment BS3_DATA_NM(Bs3Data32_StartOfSegment) +# define Bs3Data32_EndOfSegment BS3_DATA_NM(Bs3Data32_EndOfSegment) + +# define Bs3Text64_StartOfSegment BS3_DATA_NM(Bs3Text64_StartOfSegment) +# define Bs3Text64_EndOfSegment BS3_DATA_NM(Bs3Text64_EndOfSegment) + +# define Bs3Data64_StartOfSegment BS3_DATA_NM(Bs3Data64_StartOfSegment) +# define Bs3Data64_EndOfSegment BS3_DATA_NM(Bs3Data64_EndOfSegment) + +# define Bs3Data16Thru64Text32And64_TotalSize BS3_DATA_NM(Bs3Data16Thru64Text32And64_TotalSize) +# define Bs3TotalImageSize BS3_DATA_NM(Bs3TotalImageSize) + +# define g_achBs3HexDigits BS3_DATA_NM(g_achBs3HexDigits) +# define g_achBs3HexDigitsUpper BS3_DATA_NM(g_achBs3HexDigitsUpper) +# define g_bBs3CurrentMode BS3_DATA_NM(g_bBs3CurrentMode) +# define g_uBs3TrapEipHint BS3_DATA_NM(g_uBs3TrapEipHint) +# define g_aBs3RmIvtOriginal BS3_DATA_NM(g_aBs3RmIvtOriginal) + +# define g_usBs3TestStep BS3_DATA_NM(g_usBs3TestStep) +# define g_usBs3TestStep BS3_DATA_NM(g_usBs3TestStep) +# define g_Bs3Trap16GenericEntriesFlatAddr BS3_DATA_NM(g_Bs3Trap16GenericEntriesFlatAddr) +# define g_Bs3Trap32GenericEntriesFlatAddr BS3_DATA_NM(g_Bs3Trap32GenericEntriesFlatAddr) +# define g_Bs3Trap64GenericEntriesFlatAddr BS3_DATA_NM(g_Bs3Trap64GenericEntriesFlatAddr) + +# define g_uBs3CpuDetected BS3_DATA_NM(g_uBs3CpuDetected) + +#endif /* ARCH_BITS == 64 */ +#endif /* not needed */ + +#endif /* !BS3KIT_INCLUDED_bs3kit_mangling_data_h */ + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-template-footer.h b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-template-footer.h new file mode 100644 index 00000000..b80ee399 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-template-footer.h @@ -0,0 +1,93 @@ +/* $Id: bs3kit-template-footer.h $ */ +/** @file + * BS3Kit footer for multi-mode code templates. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + + +/* + * Undefine macros defined by the header. + * This is a subset of what bs3kit-template-footer.mac does. + */ +#undef TMPL_RM +#undef TMPL_PE16 +#undef TMPL_PE16_32 +#undef TMPL_PE16_V86 +#undef TMPL_PE32 +#undef TMPL_PE32_16 +#undef TMPL_PEV86 +#undef TMPL_PP16 +#undef TMPL_PP16_32 +#undef TMPL_PP16_V86 +#undef TMPL_PP32 +#undef TMPL_PP32_16 +#undef TMPL_PPV86 +#undef TMPL_PAE16 +#undef TMPL_PAE16_32 +#undef TMPL_PAE16_V86 +#undef TMPL_PAE32 +#undef TMPL_PAE32_16 +#undef TMPL_PAEV86 +#undef TMPL_LM16 +#undef TMPL_LM32 +#undef TMPL_LM64 + +#undef TMPL_CMN_PE +#undef TMPL_SYS_PE16 +#undef TMPL_SYS_PE32 +#undef TMPL_CMN_PP +#undef TMPL_SYS_PP16 +#undef TMPL_SYS_PP32 +#undef TMPL_CMN_PAE +#undef TMPL_SYS_PAE16 +#undef TMPL_SYS_PAE32 +#undef TMPL_CMN_LM +#undef TMPL_CMN_V86 +#undef TMPL_CMN_R86 +#undef TMPL_CMN_PAGING +#undef TMPL_CMN_WEIRD +#undef TMPL_CMN_WEIRD_V86 + +#undef TMPL_CMN_R86 + +#undef TMPL_NM +#undef TMPL_FAR_NM +#undef TMPL_MODE +#undef TMPL_MODE_STR +#undef TMPL_MODE_LNAME +#undef TMPL_MODE_UNAME +#undef TMPL_16BIT +#undef TMPL_32BIT +#undef TMPL_64BIT +#undef TMPL_BITS + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-template-footer.mac b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-template-footer.mac new file mode 100644 index 00000000..42325ac8 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-template-footer.mac @@ -0,0 +1,142 @@ +; $Id: bs3kit-template-footer.mac $ +;; @file +; BS3Kit footer for multi-mode code templates. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +; +; Undefine macros defined by the header. +; +; Note! The following is useful for verifying that all macros are included here: +; +; for i in `grep "%define" bootsector2-template-header.mac \ +; | sed -e 's/^ *%define *//' -e 's/^\([^() ]*\).*$/\1/' \ +; | sort -u` +; do +; if ! grep -wF "%undef $i" bootsector2-template-footer.mac; then +; echo $i +; fi +; done +; +%undef TMPL_RM +%undef TMPL_PE16 +%undef TMPL_PE16_32 +%undef TMPL_PE16_V86 +%undef TMPL_PE32 +%undef TMPL_PE32_16 +%undef TMPL_PEV86 +%undef TMPL_PP16 +%undef TMPL_PP16_32 +%undef TMPL_PP16_V86 +%undef TMPL_PP32 +%undef TMPL_PP32_16 +%undef TMPL_PPV86 +%undef TMPL_PAE16 +%undef TMPL_PAE16_32 +%undef TMPL_PAE16_V86 +%undef TMPL_PAE32 +%undef TMPL_PAE32_16 +%undef TMPL_PAEV86 +%undef TMPL_LM16 +%undef TMPL_LM32 +%undef TMPL_LM64 + +%undef TMPL_CMN_PE +%undef TMPL_SYS_PE16 +%undef TMPL_SYS_PE32 +%undef TMPL_CMN_PP +%undef TMPL_SYS_PP16 +%undef TMPL_SYS_PP32 +%undef TMPL_CMN_PAE +%undef TMPL_SYS_PAE16 +%undef TMPL_SYS_PAE32 +%undef TMPL_CMN_LM +%undef TMPL_CMN_V86 +%undef TMPL_CMN_R86 +%undef TMPL_CMN_PAGING +%undef TMPL_CMN_WEIRD +%undef TMPL_CMN_WEIRD_V86 + +%undef TMPL_CMN_R86 + +%undef TMPL_NM +%undef TMPL_NM_U +%undef TMPL_FAR_NM +%undef BS3_CMN_NM +%undef TMPL_UNDESCORE +%undef TMPL_MODE_UNAME +%undef TMPL_MODE_LNAME +%undef TMPL_MODE_STR +%undef TMPL_16BIT +%undef TMPL_32BIT +%undef TMPL_64BIT +%undef TMPL_BITS +%undef TMPL_PTR_DEF +%undef TMPL_HAVE_BIOS +%undef TMPL_BEGINCODE + +%undef xCB +%undef xDEF +%undef xRES +%undef xPRE +%undef xSP +%undef xBP +%undef xAX +%undef xBX +%undef xCX +%undef xDX +%undef xDI +%undef xSI +%undef xWrtRIP + +%undef sCB +%undef sDEF +%undef sRES +%undef sPRE +%undef sSP +%undef sBP +%undef sAX +%undef sBX +%undef sCX +%undef sDX +%undef sDI +%undef sSI + +%unmacro TONLY16 1+ +%unmacro TONLY32 1+ +%unmacro TONLY64 1+ +%unmacro TNOT16 1+ +%unmacro TNOT32 1+ +%unmacro TNOT64 1+ + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-template-header.h b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-template-header.h new file mode 100644 index 00000000..fa326ab0 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-template-header.h @@ -0,0 +1,532 @@ +/* $Id: bs3kit-template-header.h $ */ +/** @file + * BS3Kit header for multi-mode code templates. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#include "bs3kit.h" + +/** @defgroup grp_bs3kit_tmpl Multi-Mode Code Templates + * @ingroup grp_bs3kit + * + * Multi-mode code templates avoid duplicating code for each of the CPU modes. + * Instead the code is compiled multiple times, either via multiple inclusions + * into a source files with different mode selectors defined or by multiple + * compiler invocations. + * + * In C/C++ code we're restricted to the compiler target bit count, whereas in + * assembly we can do everything in assembler run (with some 64-bit + * restrictions, that is). + * + * Before \#defining the next mode selector and including + * bs3kit-template-header.h again, include bs3kit-template-footer.h to undefine + * all the previous mode selectors and the macros defined by the header. + * + * @{ + */ + +#ifdef DOXYGEN_RUNNING +/** @name Template mode selectors. + * + * Exactly one of these are defined by the file including the + * bs3kit-template-header.h header file. When building the code libraries, the + * kBuild target defines this. + * + * @{ */ +# define TMPL_RM /**< real mode. */ + +# define TMPL_PE16 /**< 16-bit protected mode kernel+tss, running 16-bit code, unpaged. */ +# define TMPL_PE16_32 /**< 16-bit protected mode kernel+tss, running 32-bit code, unpaged. */ +# define TMPL_PE16_V86 /**< 16-bit protected mode kernel+tss, running virtual 8086 mode code, unpaged. */ +# define TMPL_PE32 /**< 32-bit protected mode kernel+tss, running 32-bit code, unpaged. */ +# define TMPL_PE32_16 /**< 32-bit protected mode kernel+tss, running 16-bit code, unpaged. */ +# define TMPL_PEV86 /**< 32-bit protected mode kernel+tss, running virtual 8086 mode code, unpaged. */ + +# define TMPL_PP16 /**< 16-bit protected mode kernel+tss, running 16-bit code, paged. */ +# define TMPL_PP16_32 /**< 16-bit protected mode kernel+tss, running 32-bit code, paged. */ +# define TMPL_PP16_V86 /**< 16-bit protected mode kernel+tss, running virtual 8086 mode code, paged. */ +# define TMPL_PP32 /**< 32-bit protected mode kernel+tss, running 32-bit code, paged. */ +# define TMPL_PP32_16 /**< 32-bit protected mode kernel+tss, running 16-bit code, paged. */ +# define TMPL_PPV86 /**< 32-bit protected mode kernel+tss, running virtual 8086 mode code, paged. */ + +# define TMPL_PAE16 /**< 16-bit protected mode kernel+tss, running 16-bit code, PAE paging. */ +# define TMPL_PAE16_32 /**< 16-bit protected mode kernel+tss, running 32-bit code, PAE paging. */ +# define TMPL_PAE16_V86 /**< 16-bit protected mode kernel+tss, running virtual 8086 mode code, PAE paging. */ +# define TMPL_PAE32 /**< 32-bit protected mode kernel+tss, running 32-bit code, PAE paging. */ +# define TMPL_PAE32_16 /**< 32-bit protected mode kernel+tss, running 16-bit code, PAE paging. */ +# define TMPL_PAEV86 /**< 32-bit protected mode kernel+tss, running virtual 8086 mode code, PAE paging. */ + +# define TMPL_LM16 /**< 16-bit long mode (paged), kernel+tss always 64-bit. */ +# define TMPL_LM32 /**< 32-bit long mode (paged), kernel+tss always 64-bit. */ +# define TMPL_LM64 /**< 64-bit long mode (paged), kernel+tss always 64-bit. */ +/** @} */ + +/** @name Derived Indicators + * @{ */ +# define TMPL_CMN_PE /**< TMPL_PE16 | TMPL_PE16_32 | TMPL_PE16_V86 | TMPL_PE32 | TMPL_PE32_16 | TMPL_PEV86 */ +# define TMPL_SYS_PE16 /**< TMPL_PE16 | TMPL_PE16_32 | TMPL_PE16_V86 */ +# define TMPL_SYS_PE32 /**< TMPL_PE32 | TMPL_PE32_16 | TMPL_PEV86 */ +# define TMPL_CMN_PP /**< TMPL_PP16 | TMPL_PP16_32 | TMPL_PP16_V86 | TMPL_PP32 | TMPL_PP32_16 | TMPL_PPV86 */ +# define TMPL_SYS_PP16 /**< TMPL_PP16 | TMPL_PP16_32 | TMPL_PP16_V86 */ +# define TMPL_SYS_PP32 /**< TMPL_PP32 | TMPL_PP32_16 | TMPL_PPV86 */ +# define TMPL_CMN_PAE /**< TMPL_PAE16 | TMPL_PAE16_32 | TMPL_PAE16_V86 | TMPL_PAE32 | TMPL_PAE32_16 | TMPL_PAEV86 */ +# define TMPL_SYS_PAE16 /**< TMPL_PAE16 | TMPL_PAE16_32 | TMPL_PAE16_V86 */ +# define TMPL_SYS_PAE32 /**< TMPL_PAE32 | TMPL_PAE32_16 | TMPL_PAEV86 */ +# define TMPL_CMN_LM /**< TMPL_LM16 | TMPL_LM32 | TMPL_LM64 */ +# define TMPL_CMN_V86 /**< TMPL_PEV86 | TMPL_PE16_V86 | TMPL_PPV86 | TMPL_PP16_V86 | TMPL_PAEV86 | TMPL_PAE16_V86 */ +# define TMPL_CMN_R86 /**< TMPL_CMN_V86 | TMPL_RM */ +# define TMPL_CMN_PAGING /**< TMPL_CMN_PP | TMPL_CMN_PAE | TMPL_CMN_LM */ +# define TMPL_CMN_WEIRD /**< TMPL_PE16_32 | TMPL_PE32_16 | TMPL_PP16_32 | TMPL_PP32_16 | TMPL_PAE16_32 | TMPL_PAE32_16 | TMPL_CMN_WEIRD_V86 */ +# define TMPL_CMN_WEIRD_V86 /**< TMPL_PE16_V86 | TMPL_PP16_V86 | TMPL_PAE16_V86 */ +/** @} */ + +/** @def TMPL_NM + * Name mangling macro for the current mode. + * + * Example: TMPL_NM(PrintChr) + * + * @param Name The function or variable name to mangle. + * @sa #TMPL_FAR_NM, #BS3_CMN_NM, #BS3_CMN_FAR_NM + */ +# define TMPL_NM(Name) RT_CONCAT(Name,_mode) + +/** @def TMPL_FAR_NM + * Name mangling macro for the current mode into a far function name. + * + * In 32-bit and 64-bit code this does not differ from #TMPL_NM. + * + * Example: TMPL_FAR_NM(PrintChr) + * + * @param Name The function or variable name to mangle. + * @sa #TMPL_NM, #BS3_CMN_FAR_NM, #BS3_CMN_NM + */ +# define TMPL_FAR_NM(Name) RT_CONCAT3(Name,_mode,_far) + +/** @def TMPL_MODE_STR + * Short mode description. */ +# define TMPL_MODE_STR + +/** @def TMPL_HAVE_BIOS + * Indicates that we have direct access to the BIOS (only in real mode). */ +# define TMPL_HAVE_BIOS + + +/** @name For ASM compatability + * @{ */ +/** @def TMPL_16BIT + * For ASM compatibility - please use ARCH_BITS == 16. */ +# define TMPL_16BIT +/** @def TMPL_32BIT + * For ASM compatibility - please use ARCH_BITS == 32. */ +# define TMPL_32BIT +/** @def TMPL_64BIT + * For ASM compatibility - please use ARCH_BITS == 64. */ +# define TMPL_64BIT + +/** @def TMPL_BITS + * For ASM compatibility - please use ARCH_BITS instead. */ +# define TMPL_BITS ARCH_BITS +/** @} */ + +#else /* !DOXYGEN_RUNNING */ + +//#undef BS3_CMN_NM +//#undef BS3_CMN_FAR_NM + + +/* + * Convert TMPL_XXX to TMPL_MODE. + */ +#ifndef TMPL_MODE +# ifdef TMPL_RM +# define TMPL_MODE BS3_MODE_RM +# elif defined(TMPL_PE16) +# define TMPL_MODE BS3_MODE_PE16 +# elif defined(TMPL_PE16_32) +# define TMPL_MODE BS3_MODE_PE16_32 +# elif defined(TMPL_PE16_V86) +# define TMPL_MODE BS3_MODE_PE16_V86 +# elif defined(TMPL_PE32) +# define TMPL_MODE BS3_MODE_PE32 +# elif defined(TMPL_PE32_16) +# define TMPL_MODE BS3_MODE_PE32_16 +# elif defined(TMPL_PEV86) +# define TMPL_MODE BS3_MODE_PEV86 +# elif defined(TMPL_PP16) +# define TMPL_MODE BS3_MODE_PP16 +# elif defined(TMPL_PP16_32) +# define TMPL_MODE BS3_MODE_PP16_32 +# elif defined(TMPL_PP16_V86) +# define TMPL_MODE BS3_MODE_PP16_V86 +# elif defined(TMPL_PP32) +# define TMPL_MODE BS3_MODE_PP32 +# elif defined(TMPL_PP32_16) +# define TMPL_MODE BS3_MODE_PP32_16 +# elif defined(TMPL_PPV86) +# define TMPL_MODE BS3_MODE_PPV86 +# elif defined(TMPL_PAE16) +# define TMPL_MODE BS3_MODE_PAE16 +# elif defined(TMPL_PAE16_32) +# define TMPL_MODE BS3_MODE_PAE16_32 +# elif defined(TMPL_PAE16_V86) +# define TMPL_MODE BS3_MODE_PAE16_V86 +# elif defined(TMPL_PAE32) +# define TMPL_MODE BS3_MODE_PAE32 +# elif defined(TMPL_PAE32_16) +# define TMPL_MODE BS3_MODE_PAE32_16 +# elif defined(TMPL_PAEV86) +# define TMPL_MODE BS3_MODE_PAEV86 +# elif defined(TMPL_LM16) +# define TMPL_MODE BS3_MODE_LM16 +# elif defined(TMPL_LM32) +# define TMPL_MODE BS3_MODE_LM32 +# elif defined(TMPL_LM64) +# define TMPL_MODE BS3_MODE_LM64 +# else +# error "Unable to to figure out the template mode." +# endif +#endif + + +/* + * Check the code bitness and set derived defines. + */ +#if (TMPL_MODE & BS3_MODE_CODE_MASK) == BS3_MODE_CODE_16 +# if ARCH_BITS != 16 +# error "BS3_MODE_CODE_16 requires ARCH_BITS to be 16." +# endif +# define TMPL_16BIT +# define TMPL_BITS 16 +# define TMPL_UNDERSCORE _ +//# define BS3_CMN_NM(Name) RT_CONCAT(Name,_c16) +//# define BS3_CMN_FAR_NM(Name) RT_CONCAT(Name,_f16) + + +#elif (TMPL_MODE & BS3_MODE_CODE_MASK) == BS3_MODE_CODE_32 +# if ARCH_BITS != 32 +# error "BS3_MODE_CODE_32 requires ARCH_BITS to be 32." +# endif +# define TMPL_32BIT +# define TMPL_BITS 32 +# define TMPL_UNDERSCORE _ +//# define BS3_CMN_NM(Name) RT_CONCAT(Name,_c32) +//# define BS3_CMN_FAR_NM(a_Name) RT_CONCAT(Name,_c32) + +#elif (TMPL_MODE & BS3_MODE_CODE_MASK) == BS3_MODE_CODE_V86 +# if ARCH_BITS != 16 +# error "BS3_MODE_CODE_V86 requires ARCH_BITS to be 16." +# endif +# define TMPL_16BIT +# define TMPL_BITS 16 +# define TMPL_UNDERSCORE _ +//# define BS3_CMN_NM(Name) RT_CONCAT(Name,_c16) +//# define BS3_CMN_FAR_NM(Name) RT_CONCAT(Name,_f16) +# define TMPL_CMN_R86 +# define TMPL_CMN_V86 + +#elif (TMPL_MODE & BS3_MODE_CODE_MASK) == BS3_MODE_CODE_64 +# if ARCH_BITS != 64 +# error "BS3_MODE_CODE_64 requires ARCH_BITS to be 64." +# endif +# define TMPL_64BIT +# define TMPL_BITS 64 +# define TMPL_UNDERSCORE +//# define BS3_CMN_NM(Name) RT_CONCAT(Name,_c64) +//# define BS3_CMN_FAR_NM(a_Name) RT_CONCAT(Name,_c64) + +#else +# error "Invalid TMPL_MODE value!" +#endif + + +/* + * Check the system specific mask and set derived values. + */ +#if (TMPL_MODE & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_RM +# define TMPL_HAVE_BIOS +# define TMPL_CMN_R86 + +#elif (TMPL_MODE & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PE16 +# define TMPL_SYS_PE16 +# define TMPL_CMN_PE + +#elif (TMPL_MODE & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PE32 +# define TMPL_SYS_PE32 +# define TMPL_CMN_PE + +#elif (TMPL_MODE & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PP16 +# define TMPL_SYS_PP16 +# define TMPL_CMN_PP +# define TMPL_CMN_PAGING + +#elif (TMPL_MODE & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PP32 +# define TMPL_SYS_PP32 +# define TMPL_CMN_PP +# define TMPL_CMN_PAGING + +#elif (TMPL_MODE & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PAE16 +# define TMPL_SYS_PAE16 +# define TMPL_CMN_PAE +# define TMPL_CMN_PAGING + +#elif (TMPL_MODE & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PAE32 +# define TMPL_SYS_PAE32 +# define TMPL_CMN_PAE +# define TMPL_CMN_PAGING + +#elif (TMPL_MODE & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_LM +# define TMPL_SYS_LM +# define TMPL_CMN_LM +# define TMPL_CMN_PAGING + +#else +# error "Invalid TMPL_MODE value!" +#endif + + +/* + * Mode specific stuff. + */ +#if TMPL_MODE == BS3_MODE_RM +# define TMPL_RM 1 +# define TMPL_MODE_STR "real mode" +# define TMPL_NM(Name) RT_CONCAT(Name,_rm) +# define TMPL_MODE_LNAME rm +# define TMPL_MODE_UNAME RM + + +#elif TMPL_MODE == BS3_MODE_PE16 +# define TMPL_PE16 1 +# define TMPL_MODE_STR "16-bit prot, 16-bit" +# define TMPL_NM(Name) RT_CONCAT(Name,_pe16) +# define TMPL_MODE_LNAME pe16 +# define TMPL_MODE_UNAME PE16 + +#elif TMPL_MODE == BS3_MODE_PE16_32 +# define TMPL_PE16_32 1 +# define TMPL_MODE_STR "16-bit prot, 32-bit" +# define TMPL_NM(Name) RT_CONCAT(Name,_pe16_32) +# define TMPL_MODE_LNAME pe16_32 +# define TMPL_MODE_UNAME PE16_32 +# define TMPL_CMN_WEIRD + +#elif TMPL_MODE == BS3_MODE_PE16_V86 +# define TMPL_PE16_V86 1 +# define TMPL_MODE_STR "16-bit prot, v8086" +# define TMPL_NM(Name) RT_CONCAT(Name,_pe16_v86) +# define TMPL_MODE_LNAME pe16_v86 +# define TMPL_MODE_UNAME PE16_v86 +# define TMPL_CMN_WEIRD +# define TMPL_CMN_WEIRD_V86 + + +#elif TMPL_MODE == BS3_MODE_PE32 +# define TMPL_PE32 1 +# define TMPL_MODE_STR "32-bit prot, 32-bit" +# define TMPL_NM(Name) RT_CONCAT(Name,_pe32) +# define TMPL_MODE_LNAME pe32 +# define TMPL_MODE_UNAME PE32 + +#elif TMPL_MODE == BS3_MODE_PE32_16 +# define TMPL_PE32_16 1 +# define TMPL_MODE_STR "32-bit prot, 16-bit" +# define TMPL_NM(Name) RT_CONCAT(Name,_pe32_16) +# define TMPL_MODE_LNAME pe32_16 +# define TMPL_MODE_UNAME PE32_16 +# define TMPL_CMN_WEIRD + +#elif TMPL_MODE == BS3_MODE_PEV86 +# define TMPL_PEV86 1 +# define TMPL_MODE_STR "32-bit prot, v8086" +# define TMPL_NM(Name) RT_CONCAT(Name,_pev86) +# define TMPL_MODE_LNAME pev86 +# define TMPL_MODE_UNAME PEV86 + + +#elif TMPL_MODE == BS3_MODE_PP16 +# define TMPL_PP16 1 +# define TMPL_MODE_STR "16-bit paged, 16-bit" +# define TMPL_NM(Name) RT_CONCAT(Name,_pp16) +# define TMPL_MODE_LNAME pp16 +# define TMPL_MODE_UNAME PP16 + +#elif TMPL_MODE == BS3_MODE_PP16_32 +# define TMPL_PP16_32 1 +# define TMPL_MODE_STR "16-bit paged, 32-bit" +# define TMPL_NM(Name) RT_CONCAT(Name,_pp16_32) +# define TMPL_MODE_LNAME pp16_32 +# define TMPL_MODE_UNAME PP16_32 +# define TMPL_CMN_WEIRD + +#elif TMPL_MODE == BS3_MODE_PP16_V86 +# define TMPL_PP16_V86 1 +# define TMPL_MODE_STR "16-bit paged, v8086" +# define TMPL_NM(Name) RT_CONCAT(Name,_pp16_v86) +# define TMPL_MODE_LNAME pp16_v86 +# define TMPL_MODE_UNAME PP16_v86 +# define TMPL_CMN_WEIRD +# define TMPL_CMN_WEIRD_V86 + + +#elif TMPL_MODE == BS3_MODE_PP32 +# define TMPL_PP32 1 +# define TMPL_MODE_STR "32-bit paged, 32-bit" +# define TMPL_NM(Name) RT_CONCAT(Name,_pp32) +# define TMPL_MODE_LNAME pp32 +# define TMPL_MODE_UNAME PP32 + +#elif TMPL_MODE == BS3_MODE_PP32_16 +# define TMPL_PP32_16 1 +# define TMPL_MODE_STR "32-bit paged, 16-bit" +# define TMPL_NM(Name) RT_CONCAT(Name,_pp32_16) +# define TMPL_MODE_LNAME pp32_16 +# define TMPL_MODE_UNAME PP32_16 +# define TMPL_CMN_WEIRD + +#elif TMPL_MODE == BS3_MODE_PPV86 +# define TMPL_PPV86 1 +# define TMPL_MODE_STR "32-bit paged, v8086" +# define TMPL_NM(Name) RT_CONCAT(Name,_ppv86) +# define TMPL_MODE_LNAME ppv86 +# define TMPL_MODE_UNAME PPV86 + + +#elif TMPL_MODE == BS3_MODE_PAE16 +# define TMPL_PAE16 1 +# define TMPL_MODE_STR "16-bit pae, 16-bit" +# define TMPL_NM(Name) RT_CONCAT(Name,_pae16) +# define TMPL_MODE_LNAME pae16 +# define TMPL_MODE_UNAME PAE16 + +#elif TMPL_MODE == BS3_MODE_PAE16_32 +# define TMPL_PAE16_32 1 +# define TMPL_MODE_STR "16-bit pae, 32-bit" +# define TMPL_NM(Name) RT_CONCAT(Name,_pae16_32) +# define TMPL_MODE_LNAME pae16_32 +# define TMPL_MODE_UNAME PAE16_32 +# define TMPL_CMN_WEIRD + +#elif TMPL_MODE == BS3_MODE_PAE16_V86 +# define TMPL_PAE16_V86 1 +# define TMPL_MODE_STR "16-bit pae, v8086" +# define TMPL_NM(Name) RT_CONCAT(Name,_pae16_v86) +# define TMPL_MODE_LNAME pae16_v86 +# define TMPL_MODE_UNAME PAE16_v86 +# define TMPL_CMN_WEIRD +# define TMPL_CMN_WEIRD_V86 + + +#elif TMPL_MODE == BS3_MODE_PAE32 +# define TMPL_PAE32 1 +# define TMPL_MODE_STR "32-bit pae, 32-bit" +# define TMPL_NM(Name) RT_CONCAT(Name,_pae32) +# define TMPL_MODE_LNAME pae32 +# define TMPL_MODE_UNAME PAE32 + +#elif TMPL_MODE == BS3_MODE_PAE32_16 +# define TMPL_PAE32_16 1 +# define TMPL_MODE_STR "32-bit pae, 32-bit" +# define TMPL_NM(Name) RT_CONCAT(Name,_pae32_16) +# define TMPL_MODE_LNAME pae32_16 +# define TMPL_MODE_UNAME PAE32_16 +# define TMPL_CMN_WEIRD + +#elif TMPL_MODE == BS3_MODE_PAEV86 +# define TMPL_PAEV86 1 +# define TMPL_MODE_STR "32-bit pae, v8086 pae" +# define TMPL_NM(Name) RT_CONCAT(Name,_paev86) +# define TMPL_MODE_LNAME paev86 +# define TMPL_MODE_UNAME PAEV86 + + +#elif TMPL_MODE == BS3_MODE_LM16 +# define TMPL_LM16 1 +# define TMPL_MODE_STR "long, 16-bit" +# define TMPL_NM(Name) RT_CONCAT(Name,_lm16) +# define TMPL_MODE_LNAME lm16 +# define TMPL_MODE_UNAME LM16 + +#elif TMPL_MODE == BS3_MODE_LM32 +# define TMPL_LM32 1 +# define TMPL_MODE_STR "long, 32-bit" +# define TMPL_NM(Name) RT_CONCAT(Name,_lm32) +# define TMPL_MODE_LNAME lm32 +# define TMPL_MODE_UNAME LM32 + +#elif TMPL_MODE == BS3_MODE_LM64 +# define TMPL_LM64 1 +# define TMPL_MODE_STR "long, 64-bit" +# define TMPL_NM(Name) RT_CONCAT(Name,_lm64) +# define TMPL_MODE_LNAME lm64 +# define TMPL_MODE_UNAME LM64 + +#else +# error "Invalid TMPL_MODE value!!" +#endif + + +#if TMPL_MODE & (BS3_MODE_CODE_16 | BS3_MODE_CODE_V86) +# define TMPL_FAR_NM(Name) RT_CONCAT3(TMPL_NM(Name),_f,ar) /* _far and far may be #defined already. */ +#else +# define TMPL_FAR_NM(Name) TMPL_NM(Name) +#endif + + +/** @def BS3_MODE_DEF + * Macro for defining a mode specific function. + * + * This makes 16-bit mode functions far, while 32-bit and 64-bit are near. + * You need to update the make file to generate near->far wrappers in most + * cases. + * + * @param a_RetType The return type. + * @param a_Name The function basename. + * @param a_Params The parameter list (in parentheses). + * + * @sa BS3_MODE_PROTO + */ +#if ARCH_BITS == 16 +# define BS3_MODE_DEF(a_RetType, a_Name, a_Params) BS3_DECL_FAR(a_RetType) TMPL_FAR_NM(a_Name) a_Params +#else +# define BS3_MODE_DEF(a_RetType, a_Name, a_Params) BS3_DECL_NEAR(a_RetType) TMPL_NM(a_Name) a_Params +#endif + + + +#ifndef TMPL_MODE_STR +# error "internal error" +#endif + +#endif /* !DOXYGEN_RUNNING */ +/** @} */ + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-template-header.mac b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-template-header.mac new file mode 100644 index 00000000..ae9acdd9 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-template-header.mac @@ -0,0 +1,532 @@ +; $Id: bs3kit-template-header.mac $ +;; @file +; BS3Kit header for multi-mode code templates. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%include "bs3kit.mac" + +; +; Check and expand the mode defines. +; One of the following must be defined: +; - TMPL_RM - real mode. +; - TMPL_PE16 - 16-bit protected mode, unpaged. +; - TMPL_PE32 - 32-bit protected mode, unpaged. +; - TMPL_PEV86 - virtual 8086 mode under protected mode, unpaged. +; - TMPL_PP16 - 16-bit protected mode, paged. +; - TMPL_PP32 - 32-bit protected mode, paged. +; - TMPL_PPV86 - virtual 8086 mode under protected mode, paged. +; - TMPL_PAE16 - 16-bit protected mode with PAE (paged). +; - TMPL_PAE32 - 16-bit protected mode with PAE (paged). +; - TMPL_PAEV86- virtual 8086 mode under protected mode with PAE (paged). +; - TMPL_LM16 - 16-bit long mode (paged). +; - TMPL_LM32 - 32-bit long mode (paged). +; - TMPL_LM64 - 64-bit long mode (paged). +; +; Derived indicators: +; - TMPL_CMN_PE = TMPL_PE16 | TMPL_PE32 | TMPL_PEV86 +; - TMPL_CMN_PP = TMPL_PP16 | TMPL_PP32 | TMPL_PPV86 +; - TMPL_CMN_PAE = TMPL_PAE16 | TMPL_PAE32 | TMPL_PAEV86 +; - TMPL_CMN_LM = TMPL_LM16 | TMPL_LM32 | TMPL_LM64 +; - TMPL_CMN_V86 = TMPL_PEV86 | TMPL_PPV86 | TMPL_PAEV86 +; - TMPL_CMN_R86 = TMPL_CMN_V86 | TMPL_RM +; - TMPL_CMN_PAGING = TMPL_CMN_PP | TMPL_CMN_PAE | TMPL_CMN_LM +; + + +; +; Convert TMPL_XXX to TMPL_MODE. +; +%ifndef TMPL_MODE + %ifdef TMPL_RM + %define TMPL_MODE BS3_MODE_RM + %elifdef TMPL_PE16 + %define TMPL_MODE BS3_MODE_PE16 + %elifdef TMPL_PE16_32 + %define TMPL_MODE BS3_MODE_PE16_32 + %elifdef TMPL_PE16_V86 + %define TMPL_MODE BS3_MODE_PE16_V86 + %elifdef TMPL_PE32 + %define TMPL_MODE BS3_MODE_PE32 + %elifdef TMPL_PE32_16 + %define TMPL_MODE BS3_MODE_PE32_16 + %elifdef TMPL_PEV86 + %define TMPL_MODE BS3_MODE_PEV86 + %elifdef TMPL_PP16 + %define TMPL_MODE BS3_MODE_PP16 + %elifdef TMPL_PP16_32 + %define TMPL_MODE BS3_MODE_PP16_32 + %elifdef TMPL_PP16_V86 + %define TMPL_MODE BS3_MODE_PP16_V86 + %elifdef TMPL_PP32 + %define TMPL_MODE BS3_MODE_PP32 + %elifdef TMPL_PP32_16 + %define TMPL_MODE BS3_MODE_PP32_16 + %elifdef TMPL_PPV86 + %define TMPL_MODE BS3_MODE_PPV86 + %elifdef TMPL_PAE16 + %define TMPL_MODE BS3_MODE_PAE16 + %elifdef TMPL_PAE16_32 + %define TMPL_MODE BS3_MODE_PAE16_32 + %elifdef TMPL_PAE16_V86 + %define TMPL_MODE BS3_MODE_PAE16_V86 + %elifdef TMPL_PAE32 + %define TMPL_MODE BS3_MODE_PAE32 + %elifdef TMPL_PAE32_16 + %define TMPL_MODE BS3_MODE_PAE32_16 + %elifdef TMPL_PAEV86 + %define TMPL_MODE BS3_MODE_PAEV86 + %elifdef TMPL_LM16 + %define TMPL_MODE BS3_MODE_LM16 + %elifdef TMPL_LM32 + %define TMPL_MODE BS3_MODE_LM32 + %elifdef TMPL_LM64 + %define TMPL_MODE BS3_MODE_LM64 + %else + %error "Unable to to figure out the template mode." + %endif +%endif + +; +; Check the code bitness and set TMPL_XXBITS, TMPL_BITS, BS3_CMN_NM +; +%if (TMPL_MODE & BS3_MODE_CODE_MASK) == BS3_MODE_CODE_16 + %define TMPL_16BIT + %define TMPL_BITS 16 + %define TMPL_PTR_DEF dw + %define TMPL_UNDERSCORE _ + %define BS3_CMN_NM(Name) _ %+ Name %+ _c16 + +%elif (TMPL_MODE & BS3_MODE_CODE_MASK) == BS3_MODE_CODE_32 + %define TMPL_32BIT + %define TMPL_BITS 32 + %define TMPL_PTR_DEF dd + %define TMPL_UNDERSCORE _ + %define BS3_CMN_NM(Name) _ %+ Name %+ _c32 + +%elif (TMPL_MODE & BS3_MODE_CODE_MASK) == BS3_MODE_CODE_V86 + %define TMPL_16BIT + %define TMPL_BITS 16 + %define TMPL_UNDERSCORE _ + %define BS3_CMN_NM(Name) _ %+ Name %+ _c16 + %define TMPL_CMN_R86 + %define TMPL_CMN_V86 + +%elif (TMPL_MODE & BS3_MODE_CODE_MASK) == BS3_MODE_CODE_64 + %define TMPL_64BIT + %define TMPL_BITS 64 + %define TMPL_PTR_DEF dq + %define TMPL_UNDERSCORE _ + %define BS3_CMN_NM(Name) _ %+ Name %+ _c64 + +%else + %error "Invalid TMPL_MODE value!" +%endif + +; +; Check the system specific mask and set derived values. +; +%if (TMPL_MODE & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_RM + %define TMPL_HAVE_BIOS + %define TMPL_CMN_R86 + +%elif (TMPL_MODE & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PE16 + %define TMPL_SYS_PE16 + %define TMPL_CMN_PE + +%elif (TMPL_MODE & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PE32 + %define TMPL_SYS_PE32 + %define TMPL_CMN_PE + +%elif (TMPL_MODE & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PP16 + %define TMPL_SYS_PP16 + %define TMPL_CMN_PP + %define TMPL_CMN_PAGING + +%elif (TMPL_MODE & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PP32 + %define TMPL_SYS_PP32 + %define TMPL_CMN_PP + %define TMPL_CMN_PAGING + +%elif (TMPL_MODE & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PAE16 + %define TMPL_SYS_PAE16 + %define TMPL_CMN_PAE + %define TMPL_CMN_PAGING + +%elif (TMPL_MODE & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PAE32 + %define TMPL_SYS_PAE32 + %define TMPL_CMN_PAE + %define TMPL_CMN_PAGING + +%elif (TMPL_MODE & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_LM + %define TMPL_SYS_LM + %define TMPL_CMN_LM + %define TMPL_CMN_PAGING + +%else + %error "Invalid TMPL_MODE value!" +%endif + + +; +; Mode specific stuff. +; +%if TMPL_MODE == BS3_MODE_RM + %define TMPL_RM + %define TMPL_MODE_STR "real mode" + %define TMPL_NM(Name) _ %+ Name %+ _rm + %define TMPL_MODE_LNAME rm + %define TMPL_MODE_UNAME RM + + +%elif TMPL_MODE == BS3_MODE_PE16 + %define TMPL_PE16 + %define TMPL_MODE_STR "16-bit prot, 16-bit" + %define TMPL_NM(Name) _ %+ Name %+ _pe16 + %define TMPL_MODE_LNAME pe16 + %define TMPL_MODE_UNAME PE16 + +%elif TMPL_MODE == BS3_MODE_PE16_32 + %define TMPL_PE16_32 + %define TMPL_MODE_STR "16-bit prot, 32-bit" + %define TMPL_NM(Name) _ %+ Name %+ _pe16_32 + %define TMPL_MODE_LNAME pe16_32 + %define TMPL_MODE_UNAME PE16_32 + %define TMPL_CMN_WEIRD + +%elif TMPL_MODE == BS3_MODE_PE16_V86 + %define TMPL_PE16_V86 + %define TMPL_MODE_STR "16-bit prot, v8086" + %define TMPL_NM(Name) _ %+ Name %+ _pe16_v86 + %define TMPL_MODE_LNAME pe16_v86 + %define TMPL_MODE_UNAME PE16_v86 + %define TMPL_CMN_WEIRD + %define TMPL_CMN_WEIRD_V86 + + +%elif TMPL_MODE == BS3_MODE_PE32 + %define TMPL_PE32 + %define TMPL_MODE_STR "32-bit prot, 32-bit" + %define TMPL_NM(Name) _ %+ Name %+ _pe32 + %define TMPL_MODE_LNAME pe32 + %define TMPL_MODE_UNAME PE32 + +%elif TMPL_MODE == BS3_MODE_PE32_16 + %define TMPL_PE32_16 + %define TMPL_MODE_STR "32-bit prot, 16-bit" + %define TMPL_NM(Name) _ %+ Name %+ _pe32_16 + %define TMPL_MODE_LNAME pe32_16 + %define TMPL_MODE_UNAME PE32_16 + %define TMPL_CMN_WEIRD + +%elif TMPL_MODE == BS3_MODE_PEV86 + %define TMPL_PEV86 + %define TMPL_MODE_STR "32-bit prot, v8086" + %define TMPL_NM(Name) _ %+ Name %+ _pev86 + %define TMPL_MODE_LNAME pev86 + %define TMPL_MODE_UNAME PEV86 + + +%elif TMPL_MODE == BS3_MODE_PP16 + %define TMPL_PP16 + %define TMPL_MODE_STR "16-bit paged, 16-bit" + %define TMPL_NM(Name) _ %+ Name %+ _pp16 + %define TMPL_MODE_LNAME pp16 + %define TMPL_MODE_UNAME PP16 + +%elif TMPL_MODE == BS3_MODE_PP16_32 + %define TMPL_PP16_32 + %define TMPL_MODE_STR "16-bit paged, 32-bit" + %define TMPL_NM(Name) _ %+ Name %+ _pp16_32 + %define TMPL_MODE_LNAME pp16_32 + %define TMPL_MODE_UNAME PP16_32 + %define TMPL_CMN_WEIRD + +%elif TMPL_MODE == BS3_MODE_PP16_V86 + %define TMPL_PP16_V86 + %define TMPL_MODE_STR "16-bit paged, v8086" + %define TMPL_NM(Name) _ %+ Name %+ _pp16_v86 + %define TMPL_MODE_LNAME pp16_v86 + %define TMPL_MODE_UNAME PP16_v86 + %define TMPL_CMN_WEIRD + %define TMPL_CMN_WEIRD_V86 + + +%elif TMPL_MODE == BS3_MODE_PP32 + %define TMPL_PP32 + %define TMPL_MODE_STR "32-bit paged, 32-bit" + %define TMPL_NM(Name) _ %+ Name %+ _pp32 + %define TMPL_MODE_LNAME pp32 + %define TMPL_MODE_UNAME PP32 + +%elif TMPL_MODE == BS3_MODE_PP32_16 + %define TMPL_PP32_16 + %define TMPL_MODE_STR "32-bit paged, 16-bit" + %define TMPL_NM(Name) _ %+ Name %+ _pp32_16 + %define TMPL_MODE_LNAME pp32_16 + %define TMPL_MODE_UNAME PP32_16 + %define TMPL_CMN_WEIRD + +%elif TMPL_MODE == BS3_MODE_PPV86 + %define TMPL_PPV86 + %define TMPL_MODE_STR "32-bit paged, v8086" + %define TMPL_NM(Name) _ %+ Name %+ _ppv86 + %define TMPL_MODE_LNAME ppv86 + %define TMPL_MODE_UNAME PPV86 + + +%elif TMPL_MODE == BS3_MODE_PAE16 + %define TMPL_PAE16 + %define TMPL_MODE_STR "16-bit pae, 16-bit" + %define TMPL_NM(Name) _ %+ Name %+ _pae16 + %define TMPL_MODE_LNAME pae16 + %define TMPL_MODE_UNAME PAE16 + +%elif TMPL_MODE == BS3_MODE_PAE16_32 + %define TMPL_PAE16_32 + %define TMPL_MODE_STR "16-bit pae, 32-bit" + %define TMPL_NM(Name) _ %+ Name %+ _pae16_32 + %define TMPL_MODE_LNAME pae16_32 + %define TMPL_MODE_UNAME PAE16_32 + %define TMPL_CMN_WEIRD + +%elif TMPL_MODE == BS3_MODE_PAE16_V86 + %define TMPL_PAE16_V86 + %define TMPL_MODE_STR "16-bit pae, v8086" + %define TMPL_NM(Name) _ %+ Name %+ _pae16_v86 + %define TMPL_MODE_LNAME pae16_v86 + %define TMPL_MODE_UNAME PAE16_v86 + %define TMPL_CMN_WEIRD + %define TMPL_CMN_WEIRD_V86 + + +%elif TMPL_MODE == BS3_MODE_PAE32 + %define TMPL_PAE32 + %define TMPL_MODE_STR "32-bit pae, 32-bit" + %define TMPL_NM(Name) _ %+ Name %+ _pae32 + %define TMPL_MODE_LNAME pae32 + %define TMPL_MODE_UNAME PAE32 + +%elif TMPL_MODE == BS3_MODE_PAE32_16 + %define TMPL_PAE32_16 + %define TMPL_MODE_STR "32-bit pae, 16-bit" + %define TMPL_NM(Name) _ %+ Name %+ _pae32_16 + %define TMPL_MODE_LNAME pae32_16 + %define TMPL_MODE_UNAME PAE32_16 + %define TMPL_CMN_WEIRD + +%elif TMPL_MODE == BS3_MODE_PAEV86 + %define TMPL_PAEV86 + %define TMPL_MODE_STR "32-bit pae, v8086 pae" + %define TMPL_NM(Name) _ %+ Name %+ _paev86 + %define TMPL_MODE_LNAME paev86 + %define TMPL_MODE_UNAME PAEV86 + + +%elif TMPL_MODE == BS3_MODE_LM16 + %define TMPL_LM16 + %define TMPL_MODE_STR "long, 16-bit" + %define TMPL_NM(Name) _ %+ Name %+ _lm16 + %define TMPL_MODE_LNAME lm16 + %define TMPL_MODE_UNAME LM16 + +%elif TMPL_MODE == BS3_MODE_LM32 + %define TMPL_LM32 + %define TMPL_MODE_STR "long, 32-bit" + %define TMPL_NM(Name) _ %+ Name %+ _lm32 + %define TMPL_MODE_LNAME lm32 + %define TMPL_MODE_UNAME LM32 + +%elif TMPL_MODE == BS3_MODE_LM64 + %define TMPL_LM64 + %define TMPL_MODE_STR "long, 64-bit" + %define TMPL_NM(Name) _ %+ Name %+ _lm64 + %define TMPL_MODE_LNAME lm64 + %define TMPL_MODE_UNAME LM64 + +%else + %error "Invalid TMPL_MODE value!!" +%endif + +%ifnidn TMPL_UNDERSCORE,_; RT_CONCAT3 doesn't work with TMPL_UNDERSCORE being empty. duh. + %ifidn RT_CONCAT(TestName_,TMPL_MODE_LNAME),TMPL_NM(TestName) + %else + %error internal error: RT_CONCAT(TestName_,TMPL_MODE_LNAME) vs TMPL_NM(TestName) + %endif +%else + %ifidn RT_CONCAT3(TMPL_UNDERSCORE,TestName_,TMPL_MODE_LNAME),TMPL_NM(TestName) + %else + %error internal error: RT_CONCAT3(TMPL_UNDERSCORE,TestName_,TMPL_MODE_LNAME) vs TMPL_NM(TestName) + %endif +%endif + +; TMPL_NM version with uppercased suffix and no underscore separating them. +%define TMPL_NM_U(Name) TMPL_UNDERSCORE %+ Name %+ TMPL_MODE_UNAME + +; TMPL_FAR_NM +%if TMPL_MODE & (BS3_MODE_CODE_16 | BS3_MODE_CODE_V86) + %define TMPL_FAR_NM(Name) TMPL_NM(Name) %+ _far +%else + %define TMPL_FAR_NM(Name) TMPL_NM(Name) +%endif + + +;; @def TMPL_WRT_FLAT +; WRT flat when not in 16-bit modes. +; +%ifdef TMPL_16BIT + %define TMPL_WRT_FLAT +%else + %define TMPL_WRT_FLAT wrt FLAT +%endif + +;; @def TMPL_WRT_DATA16_OR_FLAT +; WRT DATA16 in 16-bit mode, WRT FLAT in 32- and 64-bit modes. +; This is important when accessing global variables. +; +%ifdef TMPL_16BIT + %define TMPL_WRT_DATA16_OR_FLAT wrt BS3KIT_GRPNM_DATA16 +%else + %define TMPL_WRT_DATA16_OR_FLAT wrt FLAT +%endif + +;; @def TMPL_DATA16_WRT +; WRT DATA16 in 16-bit mode, WRT FLAT in 32- and 64-bit modes. +; This is important when accessing global variables. +; +%if TMPL_BITS == 16 + %define TMPL_DATA16_WRT(a_Var) a_Var wrt BS3KIT_GRPNM_DATA16 +%elif TMPL_BITS == 32 + %define TMPL_DATA16_WRT(a_Var) a_Var wrt FLAT +%elif TMPL_BITS == 64 + %define TMPL_DATA16_WRT(a_Var) rel a_Var wrt FLAT +%else + %error TMPL_BITS +%endif + +;; @def TMPL_WRT_SYSTEM16_OR_FLAT +; WRT BS3SYSTEM16 in 16-bit mode, WRT FLAT in 32- and 64-bit modes. +; This is important when accessing global variables in the BS3SYSTEM16 segment. +%ifdef TMPL_16BIT + %define TMPL_WRT_SYSTEM16_OR_FLAT wrt BS3SYSTEM16 +%else + %define TMPL_WRT_SYSTEM16_OR_FLAT wrt FLAT +%endif + +;; @def TONLY16 +; Version of BONLY16 that follows the code template. +; Like BONLY16 this normally goes in column 1. +%if TMPL_BITS == 16 + %macro TONLY16 1+ + %1 + %endmacro +%else + %macro TONLY16 1+ + %endmacro +%endif + +;; @def TONLY32 +; Version of BONLY32 that follows the code template. +; Like BONLY32 this normally goes in column 1. +%if TMPL_BITS == 32 + %macro TONLY32 1+ + %1 + %endmacro +%else + %macro TONLY32 1+ + %endmacro +%endif + +;; @def TONLY64 +; Version of BONLY64 that follows the code template. +; Like BONLY64 this normally goes in column 1. +%if TMPL_BITS == 64 + %macro TONLY64 1+ + %1 + %endmacro +%else + %macro TONLY64 1+ + %endmacro +%endif + +;; @def TNOT16 +; Version of BNOT16 that follows the code template. +; Like BNOT16 this normally goes in column 1. +%if TMPL_BITS == 16 + %macro TNOT16 1+ + %endmacro +%else + %macro TNOT16 1+ + %1 + %endmacro +%endif + +;; @def TNOT32 +; Version of BNOT32 that follows the code template. +; Like BNOT32 this normally goes in column 1. +%if TMPL_BITS == 32 + %macro TNOT32 1+ + %endmacro +%else + %macro TNOT32 1+ + %1 + %endmacro +%endif + +;; @def TNOT64 +; Version of BNOT64 that follows the code template. +; Like BNOT64 this normally goes in column 1. +%if TMPL_BITS == 64 + %macro TNOT64 1+ + %endmacro +%else + %macro TNOT64 1+ + %1 + %endmacro +%endif + + +; +; Default code segment (changes BITS too). +; +%ifdef TMPL_64BIT + %define TMPL_BEGIN_TEXT BS3_BEGIN_TEXT64 +%elifdef TMPL_32BIT + %define TMPL_BEGIN_TEXT BS3_BEGIN_TEXT32 +%elifdef TMPL_16BIT + %define TMPL_BEGIN_TEXT BS3_BEGIN_TEXT16 +%else + %error "Missing TMPL_xxBIT!" +%endif +TMPL_BEGIN_TEXT + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit.h b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit.h new file mode 100644 index 00000000..3aa214e4 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit.h @@ -0,0 +1,4534 @@ +/* $Id: bs3kit.h $ */ +/** @file + * BS3Kit - structures, symbols, macros and stuff. + */ + +/* + * Copyright (C) 2007-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#ifndef BS3KIT_INCLUDED_bs3kit_h +#define BS3KIT_INCLUDED_bs3kit_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#ifndef DOXYGEN_RUNNING +# undef IN_RING0 +# define IN_RING0 +#endif + +#define RT_NO_STRICT /* Don't drag in IPRT assertion code in inline code we may use (asm.h). */ +#include <iprt/cdefs.h> +#include <iprt/types.h> + +#ifndef DOXYGEN_RUNNING +# undef IN_RING0 +#endif + +/* + * Make asm.h and friend compatible with our 64-bit assembly config (ASM_CALL64_MSC). + */ +#if defined(__GNUC__) && ARCH_BITS == 64 +# undef DECLASM +# ifdef __cplusplus +# define DECLASM(type) extern "C" type BS3_CALL +# else +# define DECLASM(type) type BS3_CALL +# endif +#endif + + +/* + * Work around ms_abi trouble in the gcc camp (gcc bugzilla #50818). + * ASSUMES all va_lists are in functions with + */ +#if defined(__GNUC__) && ARCH_BITS == 64 +# undef va_list +# undef va_start +# undef va_end +# undef va_copy +# define va_list __builtin_ms_va_list +# define va_start(a_Va, a_Arg) __builtin_ms_va_start(a_Va, a_Arg) +# define va_end(a_Va) __builtin_ms_va_end(a_Va) +# define va_copy(a_DstVa, a_SrcVa) __builtin_ms_va_copy(a_DstVa, a_SrcVa) +#endif + + +/** @def BS3_USE_ALT_16BIT_TEXT_SEG + * @ingroup grp_bs3kit + * Combines the BS3_USE_RM_TEXT_SEG, BS3_USE_X0_TEXT_SEG, and + * BS3_USE_X1_TEXT_SEG indicators into a single one. + */ +#if defined(BS3_USE_RM_TEXT_SEG) || defined(BS3_USE_X0_TEXT_SEG) || defined(BS3_USE_X1_TEXT_SEG) || defined(DOXYGEN_RUNNING) +# define BS3_USE_ALT_16BIT_TEXT_SEG +#else +# undef BS3_USE_ALT_16BIT_TEXT_SEG +#endif + +/** @def BS3_USE_X0_TEXT_SEG + * @ingroup grp_bs3kit + * Emit 16-bit code to the BS3X0TEXT16 segment - ignored for 32-bit and 64-bit. + * + * Calling directly into the BS3X0TEXT16 segment is only possible in real-mode + * and v8086 mode. In protected mode the real far pointer have to be converted + * to a protected mode pointer that uses BS3_SEL_X0TEXT16_CS, Bs3TestDoModes and + * associates does this automatically. + */ +#ifdef DOXYGEN_RUNNING +# define BS3_USE_X0_TEXT_SEG +#endif + +/** @def BS3_USE_X1_TEXT_SEG + * @ingroup grp_bs3kit + * Emit 16-bit code to the BS3X1TEXT16 segment - ignored for 32-bit and 64-bit. + * + * Calling directly into the BS3X1TEXT16 segment is only possible in real-mode + * and v8086 mode. In protected mode the real far pointer have to be converted + * to a protected mode pointer that uses BS3_SEL_X1TEXT16_CS, Bs3TestDoModes and + * associates does this automatically. + */ +#ifdef DOXYGEN_RUNNING +# define BS3_USE_X1_TEXT_SEG +#endif + +/** @def BS3_USE_RM_TEXT_SEG + * @ingroup grp_bs3kit + * Emit 16-bit code to the BS3RMTEXT16 segment - ignored for 32-bit and 64-bit. + * + * This segment is normally used for real-mode only code, though + * BS3_SEL_RMTEXT16_CS can be used to call it from protected mode. Unlike the + * BS3X0TEXT16 and BS3X1TEXT16 segments which are empty by default, this segment + * is used by common BS3Kit code. + */ +#ifdef DOXYGEN_RUNNING +# define BS3_USE_X0_TEXT_SEG +#endif + +/** @def BS3_MODEL_FAR_CODE + * @ingroup grp_bs3kit + * Default compiler model indicates far code. + */ +#ifdef DOXYGEN_RUNNING +# define BS3_MODEL_FAR_CODE +#elif !defined(BS3_MODEL_FAR_CODE) && (defined(__LARGE__) || defined(__MEDIUM__) || defined(__HUGE__)) && ARCH_BITS == 16 +# define BS3_MODEL_FAR_CODE +#endif + + +/* + * We normally don't want the noreturn / aborts attributes as they mess up stack traces. + * + * Note! pragma aux <fnname> aborts can only be used with functions + * implemented in C and functions that does not have parameters. + */ +#define BS3_KIT_WITH_NO_RETURN +#ifndef BS3_KIT_WITH_NO_RETURN +# undef DECL_NO_RETURN +# define DECL_NO_RETURN(type) type +#endif + + +/* + * We may want to reuse some IPRT code in the common name space, so we + * redefine the RT_MANGLER to work like BS3_CMN_NM. (We cannot use + * BS3_CMN_NM yet, as we need to include IPRT headers with function + * declarations before we can define it. Thus the duplciate effort.) + */ +#if ARCH_BITS == 16 +# undef RTCALL +# if defined(BS3_USE_ALT_16BIT_TEXT_SEG) +# define RTCALL __cdecl __far +# define RT_MANGLER(a_Name) RT_CONCAT(a_Name,_f16) +# else +# define RTCALL __cdecl __near +# define RT_MANGLER(a_Name) RT_CONCAT(a_Name,_c16) +# endif +#else +# define RT_MANGLER(a_Name) RT_CONCAT3(a_Name,_c,ARCH_BITS) +#endif +#include <iprt/mangling.h> +#include <iprt/x86.h> +#include <iprt/err.h> + +/* + * Include data symbol mangling (function mangling/mapping must be done + * after the protypes). + */ +#include "bs3kit-mangling-data.h" + + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_bs3kit BS3Kit - Boot Sector Kit \#3 + * + * The BS3Kit is a framework for bare metal floppy/usb image tests, + * see the @ref pg_bs3kit "doc page" for more. + * + * @{ */ + +/** @name Execution modes. + * @{ */ +#define BS3_MODE_INVALID UINT8_C(0x00) +#define BS3_MODE_RM UINT8_C(0x01) /**< real mode. */ +#define BS3_MODE_PE16 UINT8_C(0x11) /**< 16-bit protected mode kernel+tss, running 16-bit code, unpaged. */ +#define BS3_MODE_PE16_32 UINT8_C(0x12) /**< 16-bit protected mode kernel+tss, running 32-bit code, unpaged. */ +#define BS3_MODE_PE16_V86 UINT8_C(0x18) /**< 16-bit protected mode kernel+tss, running virtual 8086 mode code, unpaged. */ +#define BS3_MODE_PE32 UINT8_C(0x22) /**< 32-bit protected mode kernel+tss, running 32-bit code, unpaged. */ +#define BS3_MODE_PE32_16 UINT8_C(0x21) /**< 32-bit protected mode kernel+tss, running 16-bit code, unpaged. */ +#define BS3_MODE_PEV86 UINT8_C(0x28) /**< 32-bit protected mode kernel+tss, running virtual 8086 mode code, unpaged. */ +#define BS3_MODE_PP16 UINT8_C(0x31) /**< 16-bit protected mode kernel+tss, running 16-bit code, paged. */ +#define BS3_MODE_PP16_32 UINT8_C(0x32) /**< 16-bit protected mode kernel+tss, running 32-bit code, paged. */ +#define BS3_MODE_PP16_V86 UINT8_C(0x38) /**< 16-bit protected mode kernel+tss, running virtual 8086 mode code, paged. */ +#define BS3_MODE_PP32 UINT8_C(0x42) /**< 32-bit protected mode kernel+tss, running 32-bit code, paged. */ +#define BS3_MODE_PP32_16 UINT8_C(0x41) /**< 32-bit protected mode kernel+tss, running 16-bit code, paged. */ +#define BS3_MODE_PPV86 UINT8_C(0x48) /**< 32-bit protected mode kernel+tss, running virtual 8086 mode code, paged. */ +#define BS3_MODE_PAE16 UINT8_C(0x51) /**< 16-bit protected mode kernel+tss, running 16-bit code, PAE paging. */ +#define BS3_MODE_PAE16_32 UINT8_C(0x52) /**< 16-bit protected mode kernel+tss, running 32-bit code, PAE paging. */ +#define BS3_MODE_PAE16_V86 UINT8_C(0x58) /**< 16-bit protected mode kernel+tss, running virtual 8086 mode, PAE paging. */ +#define BS3_MODE_PAE32 UINT8_C(0x62) /**< 32-bit protected mode kernel+tss, running 32-bit code, PAE paging. */ +#define BS3_MODE_PAE32_16 UINT8_C(0x61) /**< 32-bit protected mode kernel+tss, running 16-bit code, PAE paging. */ +#define BS3_MODE_PAEV86 UINT8_C(0x68) /**< 32-bit protected mode kernel+tss, running virtual 8086 mode, PAE paging. */ +#define BS3_MODE_LM16 UINT8_C(0x71) /**< 16-bit long mode (paged), kernel+tss always 64-bit. */ +#define BS3_MODE_LM32 UINT8_C(0x72) /**< 32-bit long mode (paged), kernel+tss always 64-bit. */ +#define BS3_MODE_LM64 UINT8_C(0x74) /**< 64-bit long mode (paged), kernel+tss always 64-bit. */ + +#define BS3_MODE_CODE_MASK UINT8_C(0x0f) /**< Running code mask. */ +#define BS3_MODE_CODE_16 UINT8_C(0x01) /**< Running 16-bit code. */ +#define BS3_MODE_CODE_32 UINT8_C(0x02) /**< Running 32-bit code. */ +#define BS3_MODE_CODE_64 UINT8_C(0x04) /**< Running 64-bit code. */ +#define BS3_MODE_CODE_V86 UINT8_C(0x08) /**< Running 16-bit virtual 8086 code. */ + +#define BS3_MODE_SYS_MASK UINT8_C(0xf0) /**< kernel+tss mask. */ +#define BS3_MODE_SYS_RM UINT8_C(0x00) /**< Real mode kernel+tss. */ +#define BS3_MODE_SYS_PE16 UINT8_C(0x10) /**< 16-bit protected mode kernel+tss. */ +#define BS3_MODE_SYS_PE32 UINT8_C(0x20) /**< 32-bit protected mode kernel+tss. */ +#define BS3_MODE_SYS_PP16 UINT8_C(0x30) /**< 16-bit paged protected mode kernel+tss. */ +#define BS3_MODE_SYS_PP32 UINT8_C(0x40) /**< 32-bit paged protected mode kernel+tss. */ +#define BS3_MODE_SYS_PAE16 UINT8_C(0x50) /**< 16-bit PAE paged protected mode kernel+tss. */ +#define BS3_MODE_SYS_PAE32 UINT8_C(0x60) /**< 32-bit PAE paged protected mode kernel+tss. */ +#define BS3_MODE_SYS_LM UINT8_C(0x70) /**< 64-bit (paged) long mode protected mode kernel+tss. */ + +/** Whether the mode has paging enabled. */ +#define BS3_MODE_IS_PAGED(a_fMode) ((a_fMode) >= BS3_MODE_PP16) +/** Whether the mode has legacy paging enabled (legacy as opposed to PAE or + * long mode). */ +#define BS3_MODE_IS_LEGACY_PAGING(a_fMode) ((a_fMode) >= BS3_MODE_PP16 && (a_fMode) < BS3_MODE_PAE16) + +/** Whether the mode is running v8086 code. */ +#define BS3_MODE_IS_V86(a_fMode) (((a_fMode) & BS3_MODE_CODE_MASK) == BS3_MODE_CODE_V86) +/** Whether the we're executing in real mode or v8086 mode. */ +#define BS3_MODE_IS_RM_OR_V86(a_fMode) ((a_fMode) == BS3_MODE_RM || BS3_MODE_IS_V86(a_fMode)) +/** Whether the mode is running 16-bit code, except v8086. */ +#define BS3_MODE_IS_16BIT_CODE_NO_V86(a_fMode) (((a_fMode) & BS3_MODE_CODE_MASK) == BS3_MODE_CODE_16) +/** Whether the mode is running 16-bit code (includes v8086). */ +#define BS3_MODE_IS_16BIT_CODE(a_fMode) (BS3_MODE_IS_16BIT_CODE_NO_V86(a_fMode) || BS3_MODE_IS_V86(a_fMode)) +/** Whether the mode is running 32-bit code. */ +#define BS3_MODE_IS_32BIT_CODE(a_fMode) (((a_fMode) & BS3_MODE_CODE_MASK) == BS3_MODE_CODE_32) +/** Whether the mode is running 64-bit code. */ +#define BS3_MODE_IS_64BIT_CODE(a_fMode) (((a_fMode) & BS3_MODE_CODE_MASK) == BS3_MODE_CODE_64) + +/** Whether the system is in real mode. */ +#define BS3_MODE_IS_RM_SYS(a_fMode) (((a_fMode) & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_RM) +/** Whether the system is some 16-bit mode that isn't real mode. */ +#define BS3_MODE_IS_16BIT_SYS_NO_RM(a_fMode) ( ((a_fMode) & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PE16 \ + || ((a_fMode) & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PP16 \ + || ((a_fMode) & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PAE16) +/** Whether the system is some 16-bit mode (includes real mode). */ +#define BS3_MODE_IS_16BIT_SYS(a_fMode) (BS3_MODE_IS_16BIT_SYS_NO_RM(a_fMode) || BS3_MODE_IS_RM_SYS(a_fMode)) +/** Whether the system is some 32-bit mode. */ +#define BS3_MODE_IS_32BIT_SYS(a_fMode) ( ((a_fMode) & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PE32 \ + || ((a_fMode) & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PP32 \ + || ((a_fMode) & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PAE32) +/** Whether the system is long mode. */ +#define BS3_MODE_IS_64BIT_SYS(a_fMode) (((a_fMode) & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_LM) + +/** Whether the system is in protected mode (with or without paging). + * @note Long mode is not included. */ +#define BS3_MODE_IS_PM_SYS(a_fMode) ((a_fMode) >= BS3_MODE_SYS_PE16 && (a_fMode) < BS3_MODE_SYS_LM) + +/** @todo testcase: How would long-mode handle a 16-bit TSS loaded prior to the switch? (mainly stack switching wise) Hopefully, it will tripple fault, right? */ +/** @} */ + + +/** @name BS3_ADDR_XXX - Static Memory Allocation + * @{ */ +/** The flat load address for the code after the bootsector. */ +#define BS3_ADDR_LOAD 0x10000 +/** Where we save the boot registers during init. + * Located right before the code. */ +#define BS3_ADDR_REG_SAVE (BS3_ADDR_LOAD - sizeof(BS3REGCTX) - 8) +/** Where the stack starts (initial RSP value). + * Located 16 bytes (assumed by boot sector) before the saved registers. + * SS.BASE=0. The size is a little short of 32KB */ +#define BS3_ADDR_STACK (BS3_ADDR_REG_SAVE - 16) +/** The ring-0 stack (8KB) for ring transitions. */ +#define BS3_ADDR_STACK_R0 0x06000 +/** The ring-1 stack (8KB) for ring transitions. */ +#define BS3_ADDR_STACK_R1 0x04000 +/** The ring-2 stack (8KB) for ring transitions. */ +#define BS3_ADDR_STACK_R2 0x02000 +/** IST1 ring-0 stack for long mode (4KB), used for double faults elsewhere. */ +#define BS3_ADDR_STACK_R0_IST1 0x09000 +/** IST2 ring-0 stack for long mode (3KB), used for spare 0 stack elsewhere. */ +#define BS3_ADDR_STACK_R0_IST2 0x08000 +/** IST3 ring-0 stack for long mode (1KB). */ +#define BS3_ADDR_STACK_R0_IST3 0x07400 +/** IST4 ring-0 stack for long mode (1KB), used for spare 1 stack elsewhere. */ +#define BS3_ADDR_STACK_R0_IST4 0x07000 +/** IST5 ring-0 stack for long mode (1KB). */ +#define BS3_ADDR_STACK_R0_IST5 0x06c00 +/** IST6 ring-0 stack for long mode (1KB). */ +#define BS3_ADDR_STACK_R0_IST6 0x06800 +/** IST7 ring-0 stack for long mode (1KB). */ +#define BS3_ADDR_STACK_R0_IST7 0x06400 + +/** The base address of the BS3TEXT16 segment (same as BS3_LOAD_ADDR). + * @sa BS3_SEL_TEXT16 */ +#define BS3_ADDR_BS3TEXT16 0x10000 +/** The base address of the BS3SYSTEM16 segment. + * @sa BS3_SEL_SYSTEM16 */ +#define BS3_ADDR_BS3SYSTEM16 0x20000 +/** The base address of the BS3DATA16/BS3KIT_GRPNM_DATA16 segment. + * @sa BS3_SEL_DATA16 */ +#define BS3_ADDR_BS3DATA16 0x29000 +/** @} */ + +/** @name BS3_SEL_XXX - GDT selector assignments. + * + * The real mode segment numbers for BS16TEXT, BS16DATA and BS16SYSTEM are + * present in the GDT, this allows the 16-bit C/C++ and assembly code to + * continue using the real mode segment values in ring-0 protected mode. + * + * The three segments have fixed locations: + * | segment | flat address | real mode segment | + * | ----------- | ------------ | ----------------- | + * | BS3TEXT16 | 0x00010000 | 1000h | + * | BS3SYSTEM16 | 0x00020000 | 2000h | + * | BS3DATA16 | 0x00029000 | 2900h | + * + * This means that we've got a lot of GDT space to play around with. + * + * @{ */ +#define BS3_SEL_LDT 0x0010 /**< The LDT selector for Bs3Ldt. */ +#define BS3_SEL_TSS16 0x0020 /**< The 16-bit TSS selector. */ +#define BS3_SEL_TSS16_DF 0x0028 /**< The 16-bit TSS selector for double faults. */ +#define BS3_SEL_TSS16_SPARE0 0x0030 /**< The 16-bit TSS selector for testing. */ +#define BS3_SEL_TSS16_SPARE1 0x0038 /**< The 16-bit TSS selector for testing. */ +#define BS3_SEL_TSS32 0x0040 /**< The 32-bit TSS selector. */ +#define BS3_SEL_TSS32_DF 0x0048 /**< The 32-bit TSS selector for double faults. */ +#define BS3_SEL_TSS32_SPARE0 0x0050 /**< The 32-bit TSS selector for testing. */ +#define BS3_SEL_TSS32_SPARE1 0x0058 /**< The 32-bit TSS selector for testing. */ +#define BS3_SEL_TSS32_IOBP_IRB 0x0060 /**< The 32-bit TSS selector with I/O permission and interrupt redirection bitmaps. */ +#define BS3_SEL_TSS32_IRB 0x0068 /**< The 32-bit TSS selector with only interrupt redirection bitmap (IOPB stripped by limit). */ +#define BS3_SEL_TSS64 0x0070 /**< The 64-bit TSS selector. */ +#define BS3_SEL_TSS64_SPARE0 0x0080 /**< The 64-bit TSS selector. */ +#define BS3_SEL_TSS64_SPARE1 0x0090 /**< The 64-bit TSS selector. */ +#define BS3_SEL_TSS64_IOBP 0x00a0 /**< The 64-bit TSS selector. */ + +#define BS3_SEL_RMTEXT16_CS 0x00e0 /**< Conforming code selector for accessing the BS3RMTEXT16 segment. Runtime config. */ +#define BS3_SEL_X0TEXT16_CS 0x00e8 /**< Conforming code selector for accessing the BS3X0TEXT16 segment. Runtime config. */ +#define BS3_SEL_X1TEXT16_CS 0x00f0 /**< Conforming code selector for accessing the BS3X1TEXT16 segment. Runtime config. */ +#define BS3_SEL_VMMDEV_MMIO16 0x00f8 /**< Selector for accessing the VMMDev MMIO segment at 00df000h from 16-bit code. */ + +/** Checks if @a uSel is in the BS3_SEL_RX_XXX range. */ +#define BS3_SEL_IS_IN_RING_RANGE(uSel) ( (unsigned)(uSel - BS3_SEL_R0_FIRST) < (unsigned)(4 << BS3_SEL_RING_SHIFT) ) +#define BS3_SEL_RING_SHIFT 8 /**< For the formula: BS3_SEL_R0_XXX + ((cs & 3) << BS3_SEL_RING_SHIFT) */ +#define BS3_SEL_RING_SUB_MASK 0x00f8 /**< Mask for getting the sub-selector. For use with BS3_SEL_R*_FIRST. */ + +/** Checks if @a uSel is in the BS3_SEL_R0_XXX range. */ +#define BS3_SEL_IS_IN_R0_RANGE(uSel) ( (unsigned)(uSel - BS3_SEL_R0_FIRST) < (unsigned)(1 << BS3_SEL_RING_SHIFT) ) +#define BS3_SEL_R0_FIRST 0x0100 /**< The first selector in the ring-0 block. */ +#define BS3_SEL_R0_CS16 0x0100 /**< ring-0: 16-bit code selector, base 0x10000. */ +#define BS3_SEL_R0_DS16 0x0108 /**< ring-0: 16-bit data selector, base 0x23000. */ +#define BS3_SEL_R0_SS16 0x0110 /**< ring-0: 16-bit stack selector, base 0x00000. */ +#define BS3_SEL_R0_CS32 0x0118 /**< ring-0: 32-bit flat code selector. */ +#define BS3_SEL_R0_DS32 0x0120 /**< ring-0: 32-bit flat data selector. */ +#define BS3_SEL_R0_SS32 0x0128 /**< ring-0: 32-bit flat stack selector. */ +#define BS3_SEL_R0_CS64 0x0130 /**< ring-0: 64-bit flat code selector. */ +#define BS3_SEL_R0_DS64 0x0138 /**< ring-0: 64-bit flat data & stack selector. */ +#define BS3_SEL_R0_CS16_EO 0x0140 /**< ring-0: 16-bit execute-only code selector, not accessed, 0xfffe limit, CS16 base. */ +#define BS3_SEL_R0_CS16_CNF 0x0148 /**< ring-0: 16-bit conforming code selector, not accessed, 0xfffe limit, CS16 base. */ +#define BS3_SEL_R0_CS16_CNF_EO 0x0150 /**< ring-0: 16-bit execute-only conforming code selector, not accessed, 0xfffe limit, CS16 base. */ +#define BS3_SEL_R0_CS32_EO 0x0158 /**< ring-0: 32-bit execute-only code selector, not accessed, flat. */ +#define BS3_SEL_R0_CS32_CNF 0x0160 /**< ring-0: 32-bit conforming code selector, not accessed, flat. */ +#define BS3_SEL_R0_CS32_CNF_EO 0x0168 /**< ring-0: 32-bit execute-only conforming code selector, not accessed, flat. */ +#define BS3_SEL_R0_CS64_EO 0x0170 /**< ring-0: 64-bit execute-only code selector, not accessed, flat. */ +#define BS3_SEL_R0_CS64_CNF 0x0178 /**< ring-0: 64-bit conforming code selector, not accessed, flat. */ +#define BS3_SEL_R0_CS64_CNF_EO 0x0180 /**< ring-0: 64-bit execute-only conforming code selector, not accessed, flat. */ + +#define BS3_SEL_R1_FIRST 0x0200 /**< The first selector in the ring-1 block. */ +#define BS3_SEL_R1_CS16 0x0200 /**< ring-1: 16-bit code selector, base 0x10000. */ +#define BS3_SEL_R1_DS16 0x0208 /**< ring-1: 16-bit data selector, base 0x23000. */ +#define BS3_SEL_R1_SS16 0x0210 /**< ring-1: 16-bit stack selector, base 0x00000. */ +#define BS3_SEL_R1_CS32 0x0218 /**< ring-1: 32-bit flat code selector. */ +#define BS3_SEL_R1_DS32 0x0220 /**< ring-1: 32-bit flat data selector. */ +#define BS3_SEL_R1_SS32 0x0228 /**< ring-1: 32-bit flat stack selector. */ +#define BS3_SEL_R1_CS64 0x0230 /**< ring-1: 64-bit flat code selector. */ +#define BS3_SEL_R1_DS64 0x0238 /**< ring-1: 64-bit flat data & stack selector. */ +#define BS3_SEL_R1_CS16_EO 0x0240 /**< ring-1: 16-bit execute-only code selector, not accessed, 0xfffe limit, CS16 base. */ +#define BS3_SEL_R1_CS16_CNF 0x0248 /**< ring-1: 16-bit conforming code selector, not accessed, 0xfffe limit, CS16 base. */ +#define BS3_SEL_R1_CS16_CNF_EO 0x0250 /**< ring-1: 16-bit execute-only conforming code selector, not accessed, 0xfffe limit, CS16 base. */ +#define BS3_SEL_R1_CS32_EO 0x0258 /**< ring-1: 32-bit execute-only code selector, not accessed, flat. */ +#define BS3_SEL_R1_CS32_CNF 0x0260 /**< ring-1: 32-bit conforming code selector, not accessed, flat. */ +#define BS3_SEL_R1_CS32_CNF_EO 0x0268 /**< ring-1: 32-bit execute-only conforming code selector, not accessed, flat. */ +#define BS3_SEL_R1_CS64_EO 0x0270 /**< ring-1: 64-bit execute-only code selector, not accessed, flat. */ +#define BS3_SEL_R1_CS64_CNF 0x0278 /**< ring-1: 64-bit conforming code selector, not accessed, flat. */ +#define BS3_SEL_R1_CS64_CNF_EO 0x0280 /**< ring-1: 64-bit execute-only conforming code selector, not accessed, flat. */ + +#define BS3_SEL_R2_FIRST 0x0300 /**< The first selector in the ring-2 block. */ +#define BS3_SEL_R2_CS16 0x0300 /**< ring-2: 16-bit code selector, base 0x10000. */ +#define BS3_SEL_R2_DS16 0x0308 /**< ring-2: 16-bit data selector, base 0x23000. */ +#define BS3_SEL_R2_SS16 0x0310 /**< ring-2: 16-bit stack selector, base 0x00000. */ +#define BS3_SEL_R2_CS32 0x0318 /**< ring-2: 32-bit flat code selector. */ +#define BS3_SEL_R2_DS32 0x0320 /**< ring-2: 32-bit flat data selector. */ +#define BS3_SEL_R2_SS32 0x0328 /**< ring-2: 32-bit flat stack selector. */ +#define BS3_SEL_R2_CS64 0x0330 /**< ring-2: 64-bit flat code selector. */ +#define BS3_SEL_R2_DS64 0x0338 /**< ring-2: 64-bit flat data & stack selector. */ +#define BS3_SEL_R2_CS16_EO 0x0340 /**< ring-2: 16-bit execute-only code selector, not accessed, 0xfffe limit, CS16 base. */ +#define BS3_SEL_R2_CS16_CNF 0x0348 /**< ring-2: 16-bit conforming code selector, not accessed, 0xfffe limit, CS16 base. */ +#define BS3_SEL_R2_CS16_CNF_EO 0x0350 /**< ring-2: 16-bit execute-only conforming code selector, not accessed, 0xfffe limit, CS16 base. */ +#define BS3_SEL_R2_CS32_EO 0x0358 /**< ring-2: 32-bit execute-only code selector, not accessed, flat. */ +#define BS3_SEL_R2_CS32_CNF 0x0360 /**< ring-2: 32-bit conforming code selector, not accessed, flat. */ +#define BS3_SEL_R2_CS32_CNF_EO 0x0368 /**< ring-2: 32-bit execute-only conforming code selector, not accessed, flat. */ +#define BS3_SEL_R2_CS64_EO 0x0370 /**< ring-2: 64-bit execute-only code selector, not accessed, flat. */ +#define BS3_SEL_R2_CS64_CNF 0x0378 /**< ring-2: 64-bit conforming code selector, not accessed, flat. */ +#define BS3_SEL_R2_CS64_CNF_EO 0x0380 /**< ring-2: 64-bit execute-only conforming code selector, not accessed, flat. */ + +#define BS3_SEL_R3_FIRST 0x0400 /**< The first selector in the ring-3 block. */ +#define BS3_SEL_R3_CS16 0x0400 /**< ring-3: 16-bit code selector, base 0x10000. */ +#define BS3_SEL_R3_DS16 0x0408 /**< ring-3: 16-bit data selector, base 0x23000. */ +#define BS3_SEL_R3_SS16 0x0410 /**< ring-3: 16-bit stack selector, base 0x00000. */ +#define BS3_SEL_R3_CS32 0x0418 /**< ring-3: 32-bit flat code selector. */ +#define BS3_SEL_R3_DS32 0x0420 /**< ring-3: 32-bit flat data selector. */ +#define BS3_SEL_R3_SS32 0x0428 /**< ring-3: 32-bit flat stack selector. */ +#define BS3_SEL_R3_CS64 0x0430 /**< ring-3: 64-bit flat code selector. */ +#define BS3_SEL_R3_DS64 0x0438 /**< ring-3: 64-bit flat data & stack selector. */ +#define BS3_SEL_R3_CS16_EO 0x0440 /**< ring-3: 16-bit execute-only code selector, not accessed, 0xfffe limit, CS16 base. */ +#define BS3_SEL_R3_CS16_CNF 0x0448 /**< ring-3: 16-bit conforming code selector, not accessed, 0xfffe limit, CS16 base. */ +#define BS3_SEL_R3_CS16_CNF_EO 0x0450 /**< ring-3: 16-bit execute-only conforming code selector, not accessed, 0xfffe limit, CS16 base. */ +#define BS3_SEL_R3_CS32_EO 0x0458 /**< ring-3: 32-bit execute-only code selector, not accessed, flat. */ +#define BS3_SEL_R3_CS32_CNF 0x0460 /**< ring-3: 32-bit conforming code selector, not accessed, flat. */ +#define BS3_SEL_R3_CS32_CNF_EO 0x0468 /**< ring-3: 32-bit execute-only conforming code selector, not accessed, flat. */ +#define BS3_SEL_R3_CS64_EO 0x0470 /**< ring-3: 64-bit execute-only code selector, not accessed, flat. */ +#define BS3_SEL_R3_CS64_CNF 0x0478 /**< ring-3: 64-bit conforming code selector, not accessed, flat. */ +#define BS3_SEL_R3_CS64_CNF_EO 0x0480 /**< ring-3: 64-bit execute-only conforming code selector, not accessed, flat. */ + +#define BS3_SEL_R3_LAST 0x04f8 /**< ring-3: Last of the BS3_SEL_RX_XXX range. */ + +#define BS3_SEL_SPARE_FIRST 0x0500 /**< The first selector in the spare block */ +#define BS3_SEL_SPARE_00 0x0500 /**< Spare selector number 00h. */ +#define BS3_SEL_SPARE_01 0x0508 /**< Spare selector number 01h. */ +#define BS3_SEL_SPARE_02 0x0510 /**< Spare selector number 02h. */ +#define BS3_SEL_SPARE_03 0x0518 /**< Spare selector number 03h. */ +#define BS3_SEL_SPARE_04 0x0520 /**< Spare selector number 04h. */ +#define BS3_SEL_SPARE_05 0x0528 /**< Spare selector number 05h. */ +#define BS3_SEL_SPARE_06 0x0530 /**< Spare selector number 06h. */ +#define BS3_SEL_SPARE_07 0x0538 /**< Spare selector number 07h. */ +#define BS3_SEL_SPARE_08 0x0540 /**< Spare selector number 08h. */ +#define BS3_SEL_SPARE_09 0x0548 /**< Spare selector number 09h. */ +#define BS3_SEL_SPARE_0a 0x0550 /**< Spare selector number 0ah. */ +#define BS3_SEL_SPARE_0b 0x0558 /**< Spare selector number 0bh. */ +#define BS3_SEL_SPARE_0c 0x0560 /**< Spare selector number 0ch. */ +#define BS3_SEL_SPARE_0d 0x0568 /**< Spare selector number 0dh. */ +#define BS3_SEL_SPARE_0e 0x0570 /**< Spare selector number 0eh. */ +#define BS3_SEL_SPARE_0f 0x0578 /**< Spare selector number 0fh. */ +#define BS3_SEL_SPARE_10 0x0580 /**< Spare selector number 10h. */ +#define BS3_SEL_SPARE_11 0x0588 /**< Spare selector number 11h. */ +#define BS3_SEL_SPARE_12 0x0590 /**< Spare selector number 12h. */ +#define BS3_SEL_SPARE_13 0x0598 /**< Spare selector number 13h. */ +#define BS3_SEL_SPARE_14 0x05a0 /**< Spare selector number 14h. */ +#define BS3_SEL_SPARE_15 0x05a8 /**< Spare selector number 15h. */ +#define BS3_SEL_SPARE_16 0x05b0 /**< Spare selector number 16h. */ +#define BS3_SEL_SPARE_17 0x05b8 /**< Spare selector number 17h. */ +#define BS3_SEL_SPARE_18 0x05c0 /**< Spare selector number 18h. */ +#define BS3_SEL_SPARE_19 0x05c8 /**< Spare selector number 19h. */ +#define BS3_SEL_SPARE_1a 0x05d0 /**< Spare selector number 1ah. */ +#define BS3_SEL_SPARE_1b 0x05d8 /**< Spare selector number 1bh. */ +#define BS3_SEL_SPARE_1c 0x05e0 /**< Spare selector number 1ch. */ +#define BS3_SEL_SPARE_1d 0x05e8 /**< Spare selector number 1dh. */ +#define BS3_SEL_SPARE_1e 0x05f0 /**< Spare selector number 1eh. */ +#define BS3_SEL_SPARE_1f 0x05f8 /**< Spare selector number 1fh. */ + +#define BS3_SEL_TILED 0x0600 /**< 16-bit data tiling: First - base=0x00000000, limit=64KB, DPL=3. */ +#define BS3_SEL_TILED_LAST 0x0df8 /**< 16-bit data tiling: Last - base=0x00ff0000, limit=64KB, DPL=3. */ +#define BS3_SEL_TILED_AREA_SIZE 0x001000000 /**< 16-bit data tiling: Size of addressable area, in bytes. (16 MB) */ + +#define BS3_SEL_FREE_PART1 0x0e00 /**< Free selector space - part \#1. */ +#define BS3_SEL_FREE_PART1_LAST 0x0ff8 /**< Free selector space - part \#1, last entry. */ + +#define BS3_SEL_TEXT16 0x1000 /**< The BS3TEXT16 selector. */ + +#define BS3_SEL_FREE_PART2 0x1008 /**< Free selector space - part \#2. */ +#define BS3_SEL_FREE_PART2_LAST 0x17f8 /**< Free selector space - part \#2, last entry. */ + +#define BS3_SEL_TILED_R0 0x1800 /**< 16-bit data/stack tiling: First - base=0x00000000, limit=64KB, DPL=0. */ +#define BS3_SEL_TILED_R0_LAST 0x1ff8 /**< 16-bit data/stack tiling: Last - base=0x00ff0000, limit=64KB, DPL=0. */ + +#define BS3_SEL_SYSTEM16 0x2000 /**< The BS3SYSTEM16 selector. */ + +#define BS3_SEL_FREE_PART3 0x2008 /**< Free selector space - part \#3. */ +#define BS3_SEL_FREE_PART3_LAST 0x28f8 /**< Free selector space - part \#3, last entry. */ + +#define BS3_SEL_DATA16 0x2900 /**< The BS3DATA16/BS3KIT_GRPNM_DATA16 selector. */ + +#define BS3_SEL_FREE_PART4 0x2908 /**< Free selector space - part \#4. */ +#define BS3_SEL_FREE_PART4_LAST 0x2f98 /**< Free selector space - part \#4, last entry. */ + +#define BS3_SEL_PRE_TEST_PAGE_08 0x2fa0 /**< Selector located 8 selectors before the test page. */ +#define BS3_SEL_PRE_TEST_PAGE_07 0x2fa8 /**< Selector located 7 selectors before the test page. */ +#define BS3_SEL_PRE_TEST_PAGE_06 0x2fb0 /**< Selector located 6 selectors before the test page. */ +#define BS3_SEL_PRE_TEST_PAGE_05 0x2fb8 /**< Selector located 5 selectors before the test page. */ +#define BS3_SEL_PRE_TEST_PAGE_04 0x2fc0 /**< Selector located 4 selectors before the test page. */ +#define BS3_SEL_PRE_TEST_PAGE_03 0x2fc8 /**< Selector located 3 selectors before the test page. */ +#define BS3_SEL_PRE_TEST_PAGE_02 0x2fd0 /**< Selector located 2 selectors before the test page. */ +#define BS3_SEL_PRE_TEST_PAGE_01 0x2fd8 /**< Selector located 1 selector before the test page. */ +#define BS3_SEL_TEST_PAGE 0x2fe0 /**< Start of the test page intended for playing around with paging and GDT. */ +#define BS3_SEL_TEST_PAGE_00 0x2fe0 /**< Test page selector number 00h (convenience). */ +#define BS3_SEL_TEST_PAGE_01 0x2fe8 /**< Test page selector number 01h (convenience). */ +#define BS3_SEL_TEST_PAGE_02 0x2ff0 /**< Test page selector number 02h (convenience). */ +#define BS3_SEL_TEST_PAGE_03 0x2ff8 /**< Test page selector number 03h (convenience). */ +#define BS3_SEL_TEST_PAGE_04 0x3000 /**< Test page selector number 04h (convenience). */ +#define BS3_SEL_TEST_PAGE_05 0x3008 /**< Test page selector number 05h (convenience). */ +#define BS3_SEL_TEST_PAGE_06 0x3010 /**< Test page selector number 06h (convenience). */ +#define BS3_SEL_TEST_PAGE_07 0x3018 /**< Test page selector number 07h (convenience). */ +#define BS3_SEL_TEST_PAGE_LAST 0x3fd0 /**< The last selector in the spare page. */ + +#define BS3_SEL_GDT_LIMIT 0x3fd8 /**< The GDT limit. */ +/** @} */ + +/** @name BS3_SEL_IS_XXX - Predicates for standard selectors. + * + * Standard selectors are in the range BS3_SEL_R0_FIRST thru BS3_SEL_R3_LAST. + * + * @{ */ +#define BS3_SEL_IS_CS16(a_uSel) (((a_uSel) & 0xf8) == 0x00) +#define BS3_SEL_IS_CS32(a_uSel) (((a_uSel) & 0xf8) == 0x18) +#define BS3_SEL_IS_CS64(a_uSel) (((a_uSel) & 0xf8) == 0x30) + +#define BS3_SEL_IS_ANY_CS16(a_uSel) ( ((a_uSel) & 0xf8) == 0x00 \ + || ((a_uSel) & 0xf8) == 0x40 \ + || ((a_uSel) & 0xf8) == 0x48 \ + || ((a_uSel) & 0xf8) == 0x50 ) +#define BS3_SEL_IS_ANY_CS32(a_uSel) ( ((a_uSel) & 0xf8) == 0x18 \ + || ((a_uSel) & 0xf8) == 0x58 \ + || ((a_uSel) & 0xf8) == 0x60 \ + || ((a_uSel) & 0xf8) == 0x68 ) +#define BS3_SEL_IS_ANY_CS64(a_uSel) ( ((a_uSel) & 0xf8) == 0x18 \ + || ((a_uSel) & 0xf8) == 0x58 \ + || ((a_uSel) & 0xf8) == 0x60 \ + || ((a_uSel) & 0xf8) == 0x68 ) + +#define BS3_SEL_IS_DS16(a_uSel) (((a_uSel) & 0xf8) == 0x08) +#define BS3_SEL_IS_DS32(a_uSel) (((a_uSel) & 0xf8) == 0x20) +#define BS3_SEL_IS_DS64(a_uSel) (((a_uSel) & 0xf8) == 0x38) + +#define BS3_SEL_IS_SS16(a_uSel) (((a_uSel) & 0xf8) == 0x10) +#define BS3_SEL_IS_SS32(a_uSel) (((a_uSel) & 0xf8) == 0x28) +/** @} */ + + +/** @def BS3_FAR + * For indicating far pointers in 16-bit code. + * Does nothing in 32-bit and 64-bit code. */ +/** @def BS3_NEAR + * For indicating near pointers in 16-bit code. + * Does nothing in 32-bit and 64-bit code. */ +/** @def BS3_FAR_CODE + * For indicating far 16-bit functions. + * Does nothing in 32-bit and 64-bit code. */ +/** @def BS3_NEAR_CODE + * For indicating near 16-bit functions. + * Does nothing in 32-bit and 64-bit code. */ +/** @def BS3_FAR_DATA + * For indicating far 16-bit external data, i.e. in a segment other than DATA16. + * Does nothing in 32-bit and 64-bit code. */ +#ifdef M_I86 +# define BS3_FAR __far +# define BS3_NEAR __near +# define BS3_FAR_CODE __far +# define BS3_NEAR_CODE __near +# define BS3_FAR_DATA __far +#else +# define BS3_FAR +# define BS3_NEAR +# define BS3_FAR_CODE +# define BS3_NEAR_CODE +# define BS3_FAR_DATA +#endif + +#if ARCH_BITS == 16 || defined(DOXYGEN_RUNNING) +/** @def BS3_FP_SEG + * Get the selector (segment) part of a far pointer. + * + * @returns selector. + * @param a_pv Far pointer. + */ +# define BS3_FP_SEG(a_pv) ((uint16_t)(__segment)(void BS3_FAR *)(a_pv)) +/** @def BS3_FP_OFF + * Get the segment offset part of a far pointer. + * + * For sake of convenience, this works like a uintptr_t cast in 32-bit and + * 64-bit code. + * + * @returns offset. + * @param a_pv Far pointer. + */ +# define BS3_FP_OFF(a_pv) ((uint16_t)(void __near *)(a_pv)) +/** @def BS3_FP_MAKE + * Create a far pointer. + * + * @returns Far pointer. + * @param a_uSeg The selector/segment. + * @param a_off The offset into the segment. + */ +# define BS3_FP_MAKE(a_uSeg, a_off) (((__segment)(a_uSeg)) :> ((void __near *)(a_off))) +#else +# define BS3_FP_OFF(a_pv) ((uintptr_t)(a_pv)) +#endif + +/** @def BS3_MAKE_PROT_R0PTR_FROM_FLAT + * Creates a protected mode pointer from a flat address. + * + * For sake of convenience, this macro also works in 32-bit and 64-bit mode, + * only there it doesn't return a far pointer but a flat point. + * + * @returns far void pointer if 16-bit code, near/flat void pointer in 32-bit + * and 64-bit. + * @param a_uFlat Flat address in the first 16MB. */ +#if ARCH_BITS == 16 +# define BS3_MAKE_PROT_R0PTR_FROM_FLAT(a_uFlat) \ + BS3_FP_MAKE(((uint16_t)(a_uFlat >> 16) << 3) + BS3_SEL_TILED, (uint16_t)(a_uFlat)) +#else +# define BS3_MAKE_PROT_R0PTR_FROM_FLAT(a_uFlat) ((void *)(uintptr_t)(a_uFlat)) +#endif + +/** @def BS3_MAKE_PROT_R0PTR_FROM_REAL + * Creates a protected mode pointer from a far real mode address. + * + * For sake of convenience, this macro also works in 32-bit and 64-bit mode, + * only there it doesn't return a far pointer but a flat point. + * + * @returns far void pointer if 16-bit code, near/flat void pointer in 32-bit + * and 64-bit. + * @param a_uSeg The selector/segment. + * @param a_off The offset into the segment. + */ +#if ARCH_BITS == 16 +# define BS3_MAKE_PROT_R0PTR_FROM_REAL(a_uSeg, a_off) BS3_MAKE_PROT_R0PTR_FROM_FLAT(((uint32_t)(a_uSeg) << 4) + (uint16_t)(a_off)) +#else +# define BS3_MAKE_PROT_R0PTR_FROM_REAL(a_uSeg, a_off) ( (void *)(uintptr_t)(((uint32_t)(a_uSeg) << 4) + (uint16_t)(a_off)) ) +#endif + + +/** @def BS3_CALL + * The calling convension used by BS3 functions. */ +#if ARCH_BITS != 64 +# define BS3_CALL __cdecl +#elif !defined(_MSC_VER) +# define BS3_CALL __attribute__((__ms_abi__)) +#else +# define BS3_CALL +#endif + +/** @def IN_BS3KIT + * Indicates that we're in the same link job as the BS3Kit code. */ +#ifdef DOXYGEN_RUNNING +# define IN_BS3KIT +#endif + +/** @def BS3_DECL + * Declares a BS3Kit function with default far/near. + * + * Until we outgrow BS3TEXT16, we use all near functions in 16-bit. + * + * @param a_Type The return type. */ +#if ARCH_BITS != 16 || !defined(BS3_USE_ALT_16BIT_TEXT_SEG) +# define BS3_DECL(a_Type) BS3_DECL_NEAR(a_Type) +#else +# define BS3_DECL(a_Type) BS3_DECL_FAR(a_Type) +#endif + +/** @def BS3_DECL_NEAR + * Declares a BS3Kit function, always near everywhere. + * + * Until we outgrow BS3TEXT16, we use all near functions in 16-bit. + * + * @param a_Type The return type. */ +#ifdef IN_BS3KIT +# define BS3_DECL_NEAR(a_Type) DECLEXPORT(a_Type) BS3_NEAR_CODE BS3_CALL +#else +# define BS3_DECL_NEAR(a_Type) DECLIMPORT(a_Type) BS3_NEAR_CODE BS3_CALL +#endif + +/** @def BS3_DECL_FAR + * Declares a BS3Kit function, far 16-bit, otherwise near. + * + * Until we outgrow BS3TEXT16, we use all near functions in 16-bit. + * + * @param a_Type The return type. */ +#ifdef IN_BS3KIT +# define BS3_DECL_FAR(a_Type) DECLEXPORT(a_Type) BS3_FAR_CODE BS3_CALL +#else +# define BS3_DECL_FAR(a_Type) DECLIMPORT(a_Type) BS3_FAR_CODE BS3_CALL +#endif + +/** @def BS3_DECL_CALLBACK + * Declares a BS3Kit callback function (typically static). + * + * @param a_Type The return type. */ +#ifdef IN_BS3KIT +# define BS3_DECL_CALLBACK(a_Type) a_Type BS3_FAR_CODE BS3_CALL +#else +# define BS3_DECL_CALLBACK(a_Type) a_Type BS3_FAR_CODE BS3_CALL +#endif + +/** @def BS3_DECL_NEAR_CALLBACK + * Declares a near BS3Kit callback function (typically static). + * + * 16-bit users must be in CGROUP16! + * + * @param a_Type The return type. */ +#ifdef IN_BS3KIT +# define BS3_DECL_NEAR_CALLBACK(a_Type) a_Type BS3_NEAR_CODE BS3_CALL +#else +# define BS3_DECL_NEAR_CALLBACK(a_Type) a_Type BS3_NEAR_CODE BS3_CALL +#endif + +/** + * Constructs a common name. + * + * Example: BS3_CMN_NM(Bs3Shutdown) + * + * @param a_Name The name of the function or global variable. + */ +#define BS3_CMN_NM(a_Name) RT_CONCAT3(a_Name,_c,ARCH_BITS) + +/** + * Constructs a common function name, far in 16-bit code. + * + * Example: BS3_CMN_FAR_NM(Bs3Shutdown) + * + * @param a_Name The name of the function. + */ +#if ARCH_BITS == 16 +# define BS3_CMN_FAR_NM(a_Name) RT_CONCAT(a_Name,_f16) +#else +# define BS3_CMN_FAR_NM(a_Name) RT_CONCAT3(a_Name,_c,ARCH_BITS) +#endif + +/** + * Constructs a common function name, far or near as defined by the source. + * + * Which to use in 16-bit mode is defined by BS3_USE_ALT_16BIT_TEXT_SEG. In + * 32-bit and 64-bit mode there are no far symbols, only near ones. + * + * Example: BS3_CMN_FN_NM(Bs3Shutdown) + * + * @param a_Name The name of the function. + */ +#if ARCH_BITS != 16 || !defined(BS3_USE_ALT_16BIT_TEXT_SEG) +# define BS3_CMN_FN_NM(a_Name) BS3_CMN_NM(a_Name) +#else +# define BS3_CMN_FN_NM(a_Name) BS3_CMN_FAR_NM(a_Name) +#endif + + +/** + * Constructs a data name. + * + * This glosses over the underscore prefix usage of our 16-bit, 32-bit and + * 64-bit compilers. + * + * Example: @code{.c} + * \#define Bs3Gdt BS3_DATA_NM(Bs3Gdt) + * extern X86DESC BS3_FAR_DATA Bs3Gdt + * @endcode + * + * @param a_Name The name of the global variable. + * @remarks Mainly used in bs3kit-mangling.h, internal headers and templates. + */ +//converter does this now//#if ARCH_BITS == 64 +//converter does this now//# define BS3_DATA_NM(a_Name) RT_CONCAT(_,a_Name) +//converter does this now//#else +# define BS3_DATA_NM(a_Name) a_Name +//converter does this now//#endif + +/** + * Template for creating a pointer union type. + * @param a_BaseName The base type name. + * @param a_Modifiers The type modifier. + */ +#define BS3_PTR_UNION_TEMPLATE(a_BaseName, a_Modifiers) \ + typedef union a_BaseName \ + { \ + /** Pointer into the void. */ \ + a_Modifiers void BS3_FAR *pv; \ + /** As a signed integer. */ \ + intptr_t i; \ + /** As an unsigned integer. */ \ + uintptr_t u; \ + /** Pointer to char value. */ \ + a_Modifiers char BS3_FAR *pch; \ + /** Pointer to char value. */ \ + a_Modifiers unsigned char BS3_FAR *puch; \ + /** Pointer to a int value. */ \ + a_Modifiers int BS3_FAR *pi; \ + /** Pointer to a unsigned int value. */ \ + a_Modifiers unsigned int BS3_FAR *pu; \ + /** Pointer to a long value. */ \ + a_Modifiers long BS3_FAR *pl; \ + /** Pointer to a long value. */ \ + a_Modifiers unsigned long BS3_FAR *pul; \ + /** Pointer to a memory size value. */ \ + a_Modifiers size_t BS3_FAR *pcb; \ + /** Pointer to a byte value. */ \ + a_Modifiers uint8_t BS3_FAR *pb; \ + /** Pointer to a 8-bit unsigned value. */ \ + a_Modifiers uint8_t BS3_FAR *pu8; \ + /** Pointer to a 16-bit unsigned value. */ \ + a_Modifiers uint16_t BS3_FAR *pu16; \ + /** Pointer to a 32-bit unsigned value. */ \ + a_Modifiers uint32_t BS3_FAR *pu32; \ + /** Pointer to a 64-bit unsigned value. */ \ + a_Modifiers uint64_t BS3_FAR *pu64; \ + /** Pointer to a UTF-16 character. */ \ + a_Modifiers RTUTF16 BS3_FAR *pwc; \ + /** Pointer to a UUID character. */ \ + a_Modifiers RTUUID BS3_FAR *pUuid; \ + } a_BaseName; \ + /** Pointer to a pointer union. */ \ + typedef a_BaseName *RT_CONCAT(P,a_BaseName) +BS3_PTR_UNION_TEMPLATE(BS3PTRUNION, RT_NOTHING); +BS3_PTR_UNION_TEMPLATE(BS3CPTRUNION, const); +BS3_PTR_UNION_TEMPLATE(BS3VPTRUNION, volatile); +BS3_PTR_UNION_TEMPLATE(BS3CVPTRUNION, const volatile); + +/** Generic far function type. */ +typedef BS3_DECL_FAR(void) FNBS3FAR(void); +/** Generic far function pointer type. */ +typedef FNBS3FAR *FPFNBS3FAR; + +/** Generic near function type. */ +typedef BS3_DECL_NEAR(void) FNBS3NEAR(void); +/** Generic near function pointer type. */ +typedef FNBS3NEAR *PFNBS3NEAR; + +/** Generic far 16:16 function pointer type for address conversion functions. */ +#if ARCH_BITS == 16 +typedef FPFNBS3FAR PFNBS3FARADDRCONV; +#else +typedef uint32_t PFNBS3FARADDRCONV; +#endif + +/** The system call vector. */ +#define BS3_TRAP_SYSCALL UINT8_C(0x20) + +/** @name System call numbers (ax). + * Paramenters are generally passed in registers specific to each system call, + * however cx:xSI is used for passing a pointer parameter. + * @{ */ +/** Print char (cl). */ +#define BS3_SYSCALL_PRINT_CHR UINT16_C(0x0001) +/** Print string (pointer in cx:xSI, length in dx). */ +#define BS3_SYSCALL_PRINT_STR UINT16_C(0x0002) +/** Switch to ring-0. */ +#define BS3_SYSCALL_TO_RING0 UINT16_C(0x0003) +/** Switch to ring-1. */ +#define BS3_SYSCALL_TO_RING1 UINT16_C(0x0004) +/** Switch to ring-2. */ +#define BS3_SYSCALL_TO_RING2 UINT16_C(0x0005) +/** Switch to ring-3. */ +#define BS3_SYSCALL_TO_RING3 UINT16_C(0x0006) +/** Restore context (pointer in cx:xSI, flags in dx). */ +#define BS3_SYSCALL_RESTORE_CTX UINT16_C(0x0007) +/** Set DRx register (value in ESI, register number in dl). */ +#define BS3_SYSCALL_SET_DRX UINT16_C(0x0008) +/** Get DRx register (register number in dl, value returned in ax:dx). */ +#define BS3_SYSCALL_GET_DRX UINT16_C(0x0009) +/** Set CRx register (value in ESI, register number in dl). */ +#define BS3_SYSCALL_SET_CRX UINT16_C(0x000a) +/** Get CRx register (register number in dl, value returned in ax:dx). */ +#define BS3_SYSCALL_GET_CRX UINT16_C(0x000b) +/** Set the task register (value in ESI). */ +#define BS3_SYSCALL_SET_TR UINT16_C(0x000c) +/** Get the task register (value returned in ax). */ +#define BS3_SYSCALL_GET_TR UINT16_C(0x000d) +/** Set the LDT register (value in ESI). */ +#define BS3_SYSCALL_SET_LDTR UINT16_C(0x000e) +/** Get the LDT register (value returned in ax). */ +#define BS3_SYSCALL_GET_LDTR UINT16_C(0x000f) +/** Set XCR0 register (value in edx:esi). */ +#define BS3_SYSCALL_SET_XCR0 UINT16_C(0x0010) +/** Get XCR0 register (value returned in edx:eax). */ +#define BS3_SYSCALL_GET_XCR0 UINT16_C(0x0011) +/** The last system call value. */ +#define BS3_SYSCALL_LAST BS3_SYSCALL_GET_XCR0 +/** @} */ + + + +/** @defgroup grp_bs3kit_system System Structures + * @{ */ +/** The GDT, indexed by BS3_SEL_XXX shifted by 3. */ +extern X86DESC BS3_FAR_DATA Bs3Gdt[(BS3_SEL_GDT_LIMIT + 1) / 8]; + +extern X86DESC64 BS3_FAR_DATA Bs3Gdt_Ldt; /**< @see BS3_SEL_LDT */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_Tss16; /**< @see BS3_SEL_TSS16 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_Tss16DoubleFault; /**< @see BS3_SEL_TSS16_DF */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_Tss16Spare0; /**< @see BS3_SEL_TSS16_SPARE0 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_Tss16Spare1; /**< @see BS3_SEL_TSS16_SPARE1 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_Tss32; /**< @see BS3_SEL_TSS32 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_Tss32DoubleFault; /**< @see BS3_SEL_TSS32_DF */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_Tss32Spare0; /**< @see BS3_SEL_TSS32_SPARE0 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_Tss32Spare1; /**< @see BS3_SEL_TSS32_SPARE1 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_Tss32IobpIntRedirBm; /**< @see BS3_SEL_TSS32_IOBP_IRB */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_Tss32IntRedirBm; /**< @see BS3_SEL_TSS32_IRB */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_Tss64; /**< @see BS3_SEL_TSS64 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_Tss64Spare0; /**< @see BS3_SEL_TSS64_SPARE0 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_Tss64Spare1; /**< @see BS3_SEL_TSS64_SPARE1 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_Tss64Iobp; /**< @see BS3_SEL_TSS64_IOBP */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_RMTEXT16_CS; /**< @see BS3_SEL_RMTEXT16_CS */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_X0TEXT16_CS; /**< @see BS3_SEL_X0TEXT16_CS */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_X1TEXT16_CS; /**< @see BS3_SEL_X1TEXT16_CS */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_MMIO16; /**< @see BS3_SEL_VMMDEV_MMIO16 */ + +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_First; /**< @see BS3_SEL_R0_FIRST */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_CS16; /**< @see BS3_SEL_R0_CS16 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_DS16; /**< @see BS3_SEL_R0_DS16 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_SS16; /**< @see BS3_SEL_R0_SS16 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_CS32; /**< @see BS3_SEL_R0_CS32 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_DS32; /**< @see BS3_SEL_R0_DS32 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_SS32; /**< @see BS3_SEL_R0_SS32 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_CS64; /**< @see BS3_SEL_R0_CS64 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_DS64; /**< @see BS3_SEL_R0_DS64 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_CS16_EO; /**< @see BS3_SEL_R0_CS16_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_CS16_CNF; /**< @see BS3_SEL_R0_CS16_CNF */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_CS16_CND_EO; /**< @see BS3_SEL_R0_CS16_CNF_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_CS32_EO; /**< @see BS3_SEL_R0_CS32_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_CS32_CNF; /**< @see BS3_SEL_R0_CS32_CNF */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_CS32_CNF_EO; /**< @see BS3_SEL_R0_CS32_CNF_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_CS64_EO; /**< @see BS3_SEL_R0_CS64_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_CS64_CNF; /**< @see BS3_SEL_R0_CS64_CNF */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R0_CS64_CNF_EO; /**< @see BS3_SEL_R0_CS64_CNF_EO */ + +extern X86DESC BS3_FAR_DATA Bs3Gdte_R1_First; /**< @see BS3_SEL_R1_FIRST */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R1_CS16; /**< @see BS3_SEL_R1_CS16 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R1_DS16; /**< @see BS3_SEL_R1_DS16 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R1_SS16; /**< @see BS3_SEL_R1_SS16 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R1_CS32; /**< @see BS3_SEL_R1_CS32 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R1_DS32; /**< @see BS3_SEL_R1_DS32 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R1_SS32; /**< @see BS3_SEL_R1_SS32 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R1_CS64; /**< @see BS3_SEL_R1_CS64 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R1_DS64; /**< @see BS3_SEL_R1_DS64 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R1_CS16_EO; /**< @see BS3_SEL_R1_CS16_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R1_CS16_CNF; /**< @see BS3_SEL_R1_CS16_CNF */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R1_CS16_CND_EO; /**< @see BS3_SEL_R1_CS16_CNF_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R1_CS32_EO; /**< @see BS3_SEL_R1_CS32_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R1_CS32_CNF; /**< @see BS3_SEL_R1_CS32_CNF */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R1_CS32_CNF_EO; /**< @see BS3_SEL_R1_CS32_CNF_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R1_CS64_EO; /**< @see BS3_SEL_R1_CS64_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R1_CS64_CNF; /**< @see BS3_SEL_R1_CS64_CNF */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R1_CS64_CNF_EO; /**< @see BS3_SEL_R1_CS64_CNF_EO */ + +extern X86DESC BS3_FAR_DATA Bs3Gdte_R2_First; /**< @see BS3_SEL_R2_FIRST */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R2_CS16; /**< @see BS3_SEL_R2_CS16 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R2_DS16; /**< @see BS3_SEL_R2_DS16 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R2_SS16; /**< @see BS3_SEL_R2_SS16 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R2_CS32; /**< @see BS3_SEL_R2_CS32 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R2_DS32; /**< @see BS3_SEL_R2_DS32 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R2_SS32; /**< @see BS3_SEL_R2_SS32 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R2_CS64; /**< @see BS3_SEL_R2_CS64 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R2_DS64; /**< @see BS3_SEL_R2_DS64 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R2_CS16_EO; /**< @see BS3_SEL_R2_CS16_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R2_CS16_CNF; /**< @see BS3_SEL_R2_CS16_CNF */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R2_CS16_CND_EO; /**< @see BS3_SEL_R2_CS16_CNF_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R2_CS32_EO; /**< @see BS3_SEL_R2_CS32_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R2_CS32_CNF; /**< @see BS3_SEL_R2_CS32_CNF */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R2_CS32_CNF_EO; /**< @see BS3_SEL_R2_CS32_CNF_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R2_CS64_EO; /**< @see BS3_SEL_R2_CS64_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R2_CS64_CNF; /**< @see BS3_SEL_R2_CS64_CNF */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R2_CS64_CNF_EO; /**< @see BS3_SEL_R2_CS64_CNF_EO */ + +extern X86DESC BS3_FAR_DATA Bs3Gdte_R3_First; /**< @see BS3_SEL_R3_FIRST */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R3_CS16; /**< @see BS3_SEL_R3_CS16 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R3_DS16; /**< @see BS3_SEL_R3_DS16 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R3_SS16; /**< @see BS3_SEL_R3_SS16 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R3_CS32; /**< @see BS3_SEL_R3_CS32 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R3_DS32; /**< @see BS3_SEL_R3_DS32 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R3_SS32; /**< @see BS3_SEL_R3_SS32 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R3_CS64; /**< @see BS3_SEL_R3_CS64 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R3_DS64; /**< @see BS3_SEL_R3_DS64 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R3_CS16_EO; /**< @see BS3_SEL_R3_CS16_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R3_CS16_CNF; /**< @see BS3_SEL_R3_CS16_CNF */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R3_CS16_CND_EO; /**< @see BS3_SEL_R3_CS16_CNF_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R3_CS32_EO; /**< @see BS3_SEL_R3_CS32_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R3_CS32_CNF; /**< @see BS3_SEL_R3_CS32_CNF */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R3_CS32_CNF_EO; /**< @see BS3_SEL_R3_CS32_CNF_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R3_CS64_EO; /**< @see BS3_SEL_R3_CS64_EO */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R3_CS64_CNF; /**< @see BS3_SEL_R3_CS64_CNF */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_R3_CS64_CNF_EO; /**< @see BS3_SEL_R3_CS64_CNF_EO */ + +extern X86DESC BS3_FAR_DATA Bs3GdteSpare00; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_00 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare01; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_01 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare02; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_02 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare03; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_03 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare04; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_04 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare05; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_05 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare06; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_06 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare07; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_07 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare08; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_08 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare09; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_09 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare0a; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_0a */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare0b; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_0b */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare0c; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_0c */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare0d; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_0d */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare0e; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_0e */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare0f; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_0f */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare10; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_10 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare11; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_11 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare12; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_12 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare13; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_13 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare14; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_14 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare15; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_15 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare16; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_16 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare17; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_17 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare18; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_18 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare19; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_19 */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare1a; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_1a */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare1b; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_1b */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare1c; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_1c */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare1d; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_1d */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare1e; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_1e */ +extern X86DESC BS3_FAR_DATA Bs3GdteSpare1f; /**< GDT entry for playing with in testcases. @see BS3_SEL_SPARE_1f */ + +/** GDTs setting up the tiled 16-bit access to the first 16 MBs of memory. + * @see BS3_SEL_TILED, BS3_SEL_TILED_LAST, BS3_SEL_TILED_AREA_SIZE */ +extern X86DESC BS3_FAR_DATA Bs3GdteTiled[256]; +/** Free GDTes, part \#1. */ +extern X86DESC BS3_FAR_DATA Bs3GdteFreePart1[64]; +/** The BS3TEXT16/BS3CLASS16CODE GDT entry. @see BS3_SEL_TEXT16 */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_CODE16; +/** Free GDTes, part \#2. */ +extern X86DESC BS3_FAR_DATA Bs3GdteFreePart2[511]; +/** The BS3SYSTEM16 GDT entry. */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_SYSTEM16; +/** Free GDTes, part \#3. */ +extern X86DESC BS3_FAR_DATA Bs3GdteFreePart3[223]; +/** The BS3DATA16/BS3KIT_GRPNM_DATA16 GDT entry. */ +extern X86DESC BS3_FAR_DATA Bs3Gdte_DATA16; + +/** Free GDTes, part \#4. */ +extern X86DESC BS3_FAR_DATA Bs3GdteFreePart4[211]; + +extern X86DESC BS3_FAR_DATA Bs3GdtePreTestPage08; /**< GDT entry 8 selectors prior to the test page, testcase resource. @see BS3_SEL_PRE_TEST_PAGE_08 */ +extern X86DESC BS3_FAR_DATA Bs3GdtePreTestPage07; /**< GDT entry 7 selectors prior to the test page, testcase resource. @see BS3_SEL_PRE_TEST_PAGE_07 */ +extern X86DESC BS3_FAR_DATA Bs3GdtePreTestPage06; /**< GDT entry 6 selectors prior to the test page, testcase resource. @see BS3_SEL_PRE_TEST_PAGE_06 */ +extern X86DESC BS3_FAR_DATA Bs3GdtePreTestPage05; /**< GDT entry 5 selectors prior to the test page, testcase resource. @see BS3_SEL_PRE_TEST_PAGE_05 */ +extern X86DESC BS3_FAR_DATA Bs3GdtePreTestPage04; /**< GDT entry 4 selectors prior to the test page, testcase resource. @see BS3_SEL_PRE_TEST_PAGE_04 */ +extern X86DESC BS3_FAR_DATA Bs3GdtePreTestPage03; /**< GDT entry 3 selectors prior to the test page, testcase resource. @see BS3_SEL_PRE_TEST_PAGE_03 */ +extern X86DESC BS3_FAR_DATA Bs3GdtePreTestPage02; /**< GDT entry 2 selectors prior to the test page, testcase resource. @see BS3_SEL_PRE_TEST_PAGE_02 */ +extern X86DESC BS3_FAR_DATA Bs3GdtePreTestPage01; /**< GDT entry 1 selectors prior to the test page, testcase resource. @see BS3_SEL_PRE_TEST_PAGE_01 */ +/** Array of GDT entries starting on a page boundrary and filling (almost) the + * whole page. This is for playing with paging and GDT usage. + * @see BS3_SEL_TEST_PAGE */ +extern X86DESC BS3_FAR_DATA Bs3GdteTestPage[2043]; +extern X86DESC BS3_FAR_DATA Bs3GdteTestPage00; /**< GDT entry 0 on the test page (convenience). @see BS3_SEL_TEST_PAGE_00 */ +extern X86DESC BS3_FAR_DATA Bs3GdteTestPage01; /**< GDT entry 1 on the test page (convenience). @see BS3_SEL_TEST_PAGE_01 */ +extern X86DESC BS3_FAR_DATA Bs3GdteTestPage02; /**< GDT entry 2 on the test page (convenience). @see BS3_SEL_TEST_PAGE_02 */ +extern X86DESC BS3_FAR_DATA Bs3GdteTestPage03; /**< GDT entry 3 on the test page (convenience). @see BS3_SEL_TEST_PAGE_03 */ +extern X86DESC BS3_FAR_DATA Bs3GdteTestPage04; /**< GDT entry 4 on the test page (convenience). @see BS3_SEL_TEST_PAGE_04 */ +extern X86DESC BS3_FAR_DATA Bs3GdteTestPage05; /**< GDT entry 5 on the test page (convenience). @see BS3_SEL_TEST_PAGE_05 */ +extern X86DESC BS3_FAR_DATA Bs3GdteTestPage06; /**< GDT entry 6 on the test page (convenience). @see BS3_SEL_TEST_PAGE_06 */ +extern X86DESC BS3_FAR_DATA Bs3GdteTestPage07; /**< GDT entry 7 on the test page (convenience). @see BS3_SEL_TEST_PAGE_07 */ + +/** The end of the GDT (exclusive - contains eye-catcher string). */ +extern X86DESC BS3_FAR_DATA Bs3GdtEnd; + +/** The default 16-bit TSS. */ +extern X86TSS16 BS3_FAR_DATA Bs3Tss16; +extern X86TSS16 BS3_FAR_DATA Bs3Tss16DoubleFault; +extern X86TSS16 BS3_FAR_DATA Bs3Tss16Spare0; +extern X86TSS16 BS3_FAR_DATA Bs3Tss16Spare1; +/** The default 32-bit TSS. */ +extern X86TSS32 BS3_FAR_DATA Bs3Tss32; +extern X86TSS32 BS3_FAR_DATA Bs3Tss32DoubleFault; +extern X86TSS32 BS3_FAR_DATA Bs3Tss32Spare0; +extern X86TSS32 BS3_FAR_DATA Bs3Tss32Spare1; +/** The default 64-bit TSS. */ +extern X86TSS64 BS3_FAR_DATA Bs3Tss64; +extern X86TSS64 BS3_FAR_DATA Bs3Tss64Spare0; +extern X86TSS64 BS3_FAR_DATA Bs3Tss64Spare1; +extern X86TSS64 BS3_FAR_DATA Bs3Tss64WithIopb; +extern X86TSS32 BS3_FAR_DATA Bs3Tss32WithIopb; +/** Interrupt redirection bitmap used by Bs3Tss32WithIopb. */ +extern uint8_t BS3_FAR_DATA Bs3SharedIntRedirBm[32]; +/** I/O permission bitmap used by Bs3Tss32WithIopb and Bs3Tss64WithIopb. */ +extern uint8_t BS3_FAR_DATA Bs3SharedIobp[8192+2]; +/** End of the I/O permission bitmap (exclusive). */ +extern uint8_t BS3_FAR_DATA Bs3SharedIobpEnd; +/** 16-bit IDT. */ +extern X86DESC BS3_FAR_DATA Bs3Idt16[256]; +/** 32-bit IDT. */ +extern X86DESC BS3_FAR_DATA Bs3Idt32[256]; +/** 64-bit IDT. */ +extern X86DESC64 BS3_FAR_DATA Bs3Idt64[256]; +/** Structure for the LIDT instruction for loading the 16-bit IDT. */ +extern X86XDTR64 BS3_FAR_DATA Bs3Lidt_Idt16; +/** Structure for the LIDT instruction for loading the 32-bit IDT. */ +extern X86XDTR64 BS3_FAR_DATA Bs3Lidt_Idt32; +/** Structure for the LIDT instruction for loading the 64-bit IDT. */ +extern X86XDTR64 BS3_FAR_DATA Bs3Lidt_Idt64; +/** Structure for the LIDT instruction for loading the real mode interrupt + * vector table. */ +extern X86XDTR64 BS3_FAR_DATA Bs3Lidt_Ivt; +/** Structure for the LGDT instruction for loading the current GDT. */ +extern X86XDTR64 BS3_FAR_DATA Bs3Lgdt_Gdt; +/** Structure for the LGDT instruction for loading the default GDT. */ +extern X86XDTR64 BS3_FAR_DATA Bs3LgdtDef_Gdt; +/** The LDT (all entries are empty, fill in for testing). */ +extern X86DESC BS3_FAR_DATA Bs3Ldt[116]; +/** The end of the LDT (exclusive). */ +extern X86DESC BS3_FAR_DATA Bs3LdtEnd; + +/** @} */ + + +/** @name Segment start and end markers, sizes. + * @{ */ +/** Start of the BS3TEXT16 segment. */ +extern uint8_t BS3_FAR_DATA Bs3Text16_StartOfSegment; +/** End of the BS3TEXT16 segment. */ +extern uint8_t BS3_FAR_DATA Bs3Text16_EndOfSegment; +/** The size of the BS3TEXT16 segment. */ +extern uint16_t BS3_FAR_DATA Bs3Text16_Size; + +/** Start of the BS3SYSTEM16 segment. */ +extern uint8_t BS3_FAR_DATA Bs3System16_StartOfSegment; +/** End of the BS3SYSTEM16 segment. */ +extern uint8_t BS3_FAR_DATA Bs3System16_EndOfSegment; + +/** Start of the BS3DATA16/BS3KIT_GRPNM_DATA16 segment. */ +extern uint8_t BS3_FAR_DATA Bs3Data16_StartOfSegment; +/** End of the BS3DATA16/BS3KIT_GRPNM_DATA16 segment. */ +extern uint8_t BS3_FAR_DATA Bs3Data16_EndOfSegment; + +/** Start of the BS3RMTEXT16 segment. */ +extern uint8_t BS3_FAR_DATA Bs3RmText16_StartOfSegment; +/** End of the BS3RMTEXT16 segment. */ +extern uint8_t BS3_FAR_DATA Bs3RmText16_EndOfSegment; +/** The size of the BS3RMTEXT16 segment. */ +extern uint16_t BS3_FAR_DATA Bs3RmText16_Size; +/** The flat start address of the BS3X0TEXT16 segment. */ +extern uint32_t BS3_FAR_DATA Bs3RmText16_FlatAddr; + +/** Start of the BS3X0TEXT16 segment. */ +extern uint8_t BS3_FAR_DATA Bs3X0Text16_StartOfSegment; +/** End of the BS3X0TEXT16 segment. */ +extern uint8_t BS3_FAR_DATA Bs3X0Text16_EndOfSegment; +/** The size of the BS3X0TEXT16 segment. */ +extern uint16_t BS3_FAR_DATA Bs3X0Text16_Size; +/** The flat start address of the BS3X0TEXT16 segment. */ +extern uint32_t BS3_FAR_DATA Bs3X0Text16_FlatAddr; + +/** Start of the BS3X1TEXT16 segment. */ +extern uint8_t BS3_FAR_DATA Bs3X1Text16_StartOfSegment; +/** End of the BS3X1TEXT16 segment. */ +extern uint8_t BS3_FAR_DATA Bs3X1Text16_EndOfSegment; +/** The size of the BS3X1TEXT16 segment. */ +extern uint16_t BS3_FAR_DATA Bs3X1Text16_Size; +/** The flat start address of the BS3X1TEXT16 segment. */ +extern uint32_t BS3_FAR_DATA Bs3X1Text16_FlatAddr; + +/** Start of the BS3TEXT32 segment. */ +extern uint8_t BS3_FAR_DATA Bs3Text32_StartOfSegment; +/** Start of the BS3TEXT32 segment. */ +extern uint8_t BS3_FAR_DATA Bs3Text32_EndOfSegment; + +/** Start of the BS3DATA32 segment. */ +extern uint8_t BS3_FAR_DATA Bs3Data32_StartOfSegment; +/** Start of the BS3DATA32 segment. */ +extern uint8_t BS3_FAR_DATA Bs3Data32_EndOfSegment; + +/** Start of the BS3TEXT64 segment. */ +extern uint8_t BS3_FAR_DATA Bs3Text64_StartOfSegment; +/** Start of the BS3TEXT64 segment. */ +extern uint8_t BS3_FAR_DATA Bs3Text64_EndOfSegment; + +/** Start of the BS3DATA64 segment. */ +extern uint8_t BS3_FAR_DATA Bs3Data64_StartOfSegment; +/** Start of the BS3DATA64 segment. */ +extern uint8_t BS3_FAR_DATA Bs3Data64_EndOfSegment; + +/** The size of the Data16, Text32, Text64, Data32 and Data64 blob. */ +extern uint32_t BS3_FAR_DATA Bs3Data16Thru64Text32And64_TotalSize; +/** The total image size (from Text16 thu Data64). */ +extern uint32_t BS3_FAR_DATA Bs3TotalImageSize; +/** @} */ + + +/** Lower case hex digits. */ +extern char const g_achBs3HexDigits[16+1]; +/** Upper case hex digits. */ +extern char const g_achBs3HexDigitsUpper[16+1]; + + +/** The current mode (BS3_MODE_XXX) of CPU \#0. */ +extern uint8_t g_bBs3CurrentMode; + +/** Hint for 16-bit trap handlers regarding the high word of EIP. */ +extern uint32_t g_uBs3TrapEipHint; + +/** Set to disable special V8086 \#GP and \#UD handling in Bs3TrapDefaultHandler. + * This is useful for getting */ +extern bool volatile g_fBs3TrapNoV86Assist; + +/** Copy of the original real-mode interrupt vector table. */ +extern RTFAR16 g_aBs3RmIvtOriginal[256]; + + +#ifdef __WATCOMC__ +/** + * Executes the SMSW instruction and returns the value. + * + * @returns Machine status word. + */ +uint16_t Bs3AsmSmsw(void); +# pragma aux Bs3AsmSmsw = \ + ".286" \ + "smsw ax" \ + value [ax] modify exact [ax] nomemory; +#endif + + +/** @defgroup bs3kit_cross_ptr Cross Context Pointer Type + * + * The cross context pointer type is + * + * @{ */ + +/** + * Cross context pointer base type. + */ +typedef union BS3XPTR +{ + /** The flat pointer. */ + uint32_t uFlat; + /** 16-bit view. */ + struct + { + uint16_t uLow; + uint16_t uHigh; + } u; +#if ARCH_BITS == 16 + /** 16-bit near pointer. */ + void __near *pvNear; +#elif ARCH_BITS == 32 + /** 32-bit pointer. */ + void *pvRaw; +#endif +} BS3XPTR; +AssertCompileSize(BS3XPTR, 4); + + +/** @def BS3_XPTR_DEF_INTERNAL + * Internal worker. + * + * @param a_Scope RT_NOTHING if structure or global, static or extern + * otherwise. + * @param a_Type The type we're pointing to. + * @param a_Name The member or variable name. + * @internal + */ +#if ARCH_BITS == 16 +# define BS3_XPTR_DEF_INTERNAL(a_Scope, a_Type, a_Name) \ + a_Scope union \ + { \ + BS3XPTR XPtr; \ + a_Type __near *pNearTyped; \ + } a_Name +#elif ARCH_BITS == 32 +# define BS3_XPTR_DEF_INTERNAL(a_Scope, a_Type, a_Name) \ + a_Scope union \ + { \ + BS3XPTR XPtr; \ + a_Type *pTyped; \ + } a_Name +#elif ARCH_BITS == 64 +# define BS3_XPTR_DEF_INTERNAL(a_Scope, a_Type, a_Name) \ + a_Scope union \ + { \ + BS3XPTR XPtr; \ + } a_Name +#else +# error "ARCH_BITS" +#endif + +/** @def BS3_XPTR_MEMBER + * Defines a pointer member that can be shared by all CPU modes. + * + * @param a_Type The type we're pointing to. + * @param a_Name The member or variable name. + */ +#define BS3_XPTR_MEMBER(a_Type, a_Name) BS3_XPTR_DEF_INTERNAL(RT_NOTHING, a_Type, a_Name) + +/** @def BS3_XPTR_AUTO + * Defines a pointer static variable for working with an XPTR. + * + * This is typically used to convert flat pointers into context specific + * pointers. + * + * @param a_Type The type we're pointing to. + * @param a_Name The member or variable name. + */ +#define BS3_XPTR_AUTO(a_Type, a_Name) BS3_XPTR_DEF_INTERNAL(RT_NOTHING, a_Type, a_Name) + +/** @def BS3_XPTR_SET_FLAT + * Sets a cross context pointer. + * + * @param a_Type The type we're pointing to. + * @param a_Name The member or variable name. + * @param a_uFlatPtr The flat pointer value to assign. If the x-pointer is + * used in real mode, this must be less than 1MB. + * Otherwise the limit is 16MB (due to selector tiling). + */ +#define BS3_XPTR_SET_FLAT(a_Type, a_Name, a_uFlatPtr) \ + do { a_Name.XPtr.uFlat = (a_uFlatPtr); } while (0) + +/** @def BS3_XPTR_GET_FLAT + * Gets the flat address of a cross context pointer. + * + * @returns 32-bit flat pointer. + * @param a_Type The type we're pointing to. + * @param a_Name The member or variable name. + */ +#define BS3_XPTR_GET_FLAT(a_Type, a_Name) (a_Name.XPtr.uFlat) + +/** @def BS3_XPTR_GET_FLAT_LOW + * Gets the low 16 bits of the flat address. + * + * @returns Low 16 bits of the flat pointer. + * @param a_Type The type we're pointing to. + * @param a_Name The member or variable name. + */ +#define BS3_XPTR_GET_FLAT_LOW(a_Type, a_Name) (a_Name.XPtr.u.uLow) + + +#if ARCH_BITS == 16 + +/** + * Gets the current ring number. + * @returns Ring number. + */ +DECLINLINE(uint16_t) Bs3Sel16GetCurRing(void); +# pragma aux Bs3Sel16GetCurRing = \ + "mov ax, ss" \ + "and ax, 3" \ + value [ax] modify exact [ax] nomemory; + +/** + * Converts the high word of a flat pointer into a 16-bit selector. + * + * This makes use of the tiled area. It also handles real mode. + * + * @returns Segment selector value. + * @param uHigh The high part of flat pointer. + * @sa BS3_XPTR_GET, BS3_XPTR_SET + */ +DECLINLINE(__segment) Bs3Sel16HighFlatPtrToSelector(uint16_t uHigh) +{ + if (!BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode)) + return (__segment)(((uHigh << 3) + BS3_SEL_TILED) | Bs3Sel16GetCurRing()); + return (__segment)(uHigh << 12); +} + +#endif /* ARCH_BITS == 16 */ + +/** @def BS3_XPTR_GET + * Gets the current context pointer value. + * + * @returns Usable pointer. + * @param a_Type The type we're pointing to. + * @param a_Name The member or variable name. + */ +#if ARCH_BITS == 16 +# define BS3_XPTR_GET(a_Type, a_Name) \ + ((a_Type BS3_FAR *)BS3_FP_MAKE(Bs3Sel16HighFlatPtrToSelector((a_Name).XPtr.u.uHigh), (a_Name).pNearTyped)) +#elif ARCH_BITS == 32 +# define BS3_XPTR_GET(a_Type, a_Name) ((a_Name).pTyped) +#elif ARCH_BITS == 64 +# define BS3_XPTR_GET(a_Type, a_Name) ((a_Type *)(uintptr_t)(a_Name).XPtr.uFlat) +#else +# error "ARCH_BITS" +#endif + +/** @def BS3_XPTR_SET + * Gets the current context pointer value. + * + * @returns Usable pointer. + * @param a_Type The type we're pointing to. + * @param a_Name The member or variable name. + * @param a_pValue The new pointer value, current context pointer. + */ +#if ARCH_BITS == 16 +# define BS3_XPTR_SET(a_Type, a_Name, a_pValue) \ + do { \ + a_Type BS3_FAR *pTypeCheck = (a_pValue); \ + if (BS3_MODE_IS_RM_OR_V86(g_bBs3CurrentMode)) \ + (a_Name).XPtr.uFlat = BS3_FP_OFF(pTypeCheck) + ((uint32_t)BS3_FP_SEG(pTypeCheck) << 4); \ + else \ + { \ + (a_Name).XPtr.u.uLow = BS3_FP_OFF(pTypeCheck); \ + (a_Name).XPtr.u.uHigh = ((BS3_FP_SEG(pTypeCheck) & UINT16_C(0xfff8)) - BS3_SEL_TILED) >> 3; \ + } \ + } while (0) +#elif ARCH_BITS == 32 +# define BS3_XPTR_SET(a_Type, a_Name, a_pValue) \ + do { (a_Name).pTyped = (a_pValue); } while (0) +#elif ARCH_BITS == 64 +# define BS3_XPTR_SET(a_Type, a_Name, a_pValue) \ + do { \ + a_Type *pTypeCheck = (a_pValue); \ + (a_Name).XPtr.uFlat = (uint32_t)(uintptr_t)pTypeCheck; \ + } while (0) +#else +# error "ARCH_BITS" +#endif + + +/** @def BS3_XPTR_IS_NULL + * Checks if the cross context pointer is NULL. + * + * @returns true if NULL, false if not. + * @param a_Type The type we're pointing to. + * @param a_Name The member or variable name. + */ +#define BS3_XPTR_IS_NULL(a_Type, a_Name) ((a_Name).XPtr.uFlat == 0) + +/** + * Gets a working pointer from a flat address. + * + * @returns Current context pointer. + * @param uFlatPtr The flat address to convert (32-bit or 64-bit). + */ +DECLINLINE(void BS3_FAR *) Bs3XptrFlatToCurrent(RTCCUINTXREG uFlatPtr) +{ + BS3_XPTR_AUTO(void, pTmp); + BS3_XPTR_SET_FLAT(void, pTmp, uFlatPtr); + return BS3_XPTR_GET(void, pTmp); +} + +/** @} */ + + + +/** @defgroup grp_bs3kit_cmn Common Functions and Data + * + * The common functions comes in three variations: 16-bit, 32-bit and 64-bit. + * Templated code uses the #BS3_CMN_NM macro to mangle the name according to the + * desired + * + * @{ + */ + +/** @def BS3_CMN_PROTO_INT + * Internal macro for prototyping all the variations of a common function. + * @param a_RetType The return type. + * @param a_Name The function basename. + * @param a_Params The parameter list (in parentheses). + * @sa BS3_CMN_PROTO_STUB, BS3_CMN_PROTO_NOSB + */ +#if ARCH_BITS == 16 +# ifndef BS3_USE_ALT_16BIT_TEXT_SEG +# define BS3_CMN_PROTO_INT(a_RetType, a_Name, a_Params) \ + BS3_DECL_NEAR(a_RetType) BS3_CMN_NM(a_Name) a_Params; \ + BS3_DECL_FAR(a_RetType) BS3_CMN_FAR_NM(a_Name) a_Params +# else +# define BS3_CMN_PROTO_INT(a_RetType, a_Name, a_Params) \ + BS3_DECL_FAR(a_RetType) BS3_CMN_FAR_NM(a_Name) a_Params +# endif +#else +# define BS3_CMN_PROTO_INT(a_RetType, a_Name, a_Params) \ + BS3_DECL_NEAR(a_RetType) BS3_CMN_NM(a_Name) a_Params +#endif + +/** @def BS3_CMN_PROTO_STUB + * Macro for prototyping all the variations of a common function with automatic + * near -> far stub. + * + * @param a_RetType The return type. + * @param a_Name The function basename. + * @param a_Params The parameter list (in parentheses). + * @sa BS3_CMN_PROTO_NOSB + */ +#define BS3_CMN_PROTO_STUB(a_RetType, a_Name, a_Params) BS3_CMN_PROTO_INT(a_RetType, a_Name, a_Params) + +/** @def BS3_CMN_PROTO_NOSB + * Macro for prototyping all the variations of a common function without any + * near > far stub. + * + * @param a_RetType The return type. + * @param a_Name The function basename. + * @param a_Params The parameter list (in parentheses). + * @sa BS3_CMN_PROTO_STUB + */ +#define BS3_CMN_PROTO_NOSB(a_RetType, a_Name, a_Params) BS3_CMN_PROTO_INT(a_RetType, a_Name, a_Params) + +/** @def BS3_CMN_PROTO_FARSTUB + * Macro for prototyping all the variations of a common function with automatic + * far -> near stub. + * + * @param a_cbParam16 The size of the 16-bit parameter list in bytes. + * @param a_RetType The return type. + * @param a_Name The function basename. + * @param a_Params The parameter list (in parentheses). + * @sa BS3_CMN_PROTO_STUB + */ +#define BS3_CMN_PROTO_FARSTUB(a_cbParam16, a_RetType, a_Name, a_Params) BS3_CMN_PROTO_INT(a_RetType, a_Name, a_Params) + + +/** @def BS3_CMN_DEF + * Macro for defining a common function. + * + * This makes 16-bit common function far, while 32-bit and 64-bit are near. + * + * @param a_RetType The return type. + * @param a_Name The function basename. + * @param a_Params The parameter list (in parentheses). + */ +#if ARCH_BITS == 16 +# define BS3_CMN_DEF(a_RetType, a_Name, a_Params) \ + BS3_DECL_FAR(a_RetType) BS3_CMN_FAR_NM(a_Name) a_Params +#else +# define BS3_CMN_DEF(a_RetType, a_Name, a_Params) \ + BS3_DECL_NEAR(a_RetType) BS3_CMN_NM(a_Name) a_Params +#endif + +/** @def BS3_ASSERT + * Assert that an expression is true. + * + * Calls Bs3Panic if false and it's a strict build. Does nothing in + * non-strict builds. */ +#ifdef BS3_STRICT +# define BS3_ASSERT(a_Expr) do { if (!!(a_Expr)) { /* likely */ } else { Bs3Panic(); } } while (0) /**< @todo later */ +#else +# define BS3_ASSERT(a_Expr) do { } while (0) +#endif + +/** + * Panic, never return. + * + * The current implementation will only halt the CPU. + */ +BS3_CMN_PROTO_NOSB(DECL_NO_RETURN(void), Bs3Panic,(void)); +#if !defined(BS3_KIT_WITH_NO_RETURN) && defined(__WATCOMC__) +# pragma aux Bs3Panic_c16 __aborts +# pragma aux Bs3Panic_f16 __aborts +# pragma aux Bs3Panic_c32 __aborts +#endif + + +/** + * Translate a mode into a string. + * + * @returns Pointer to read-only mode name string. + * @param bMode The mode value (BS3_MODE_XXX). + */ +BS3_CMN_PROTO_STUB(const char BS3_FAR *, Bs3GetModeName,(uint8_t bMode)); + +/** + * Translate a mode into a short lower case string. + * + * @returns Pointer to read-only short mode name string. + * @param bMode The mode value (BS3_MODE_XXX). + */ +BS3_CMN_PROTO_STUB(const char BS3_FAR *, Bs3GetModeNameShortLower,(uint8_t bMode)); + +/** CPU vendors. */ +typedef enum BS3CPUVENDOR +{ + BS3CPUVENDOR_INVALID = 0, + BS3CPUVENDOR_INTEL, + BS3CPUVENDOR_AMD, + BS3CPUVENDOR_VIA, + BS3CPUVENDOR_CYRIX, + BS3CPUVENDOR_SHANGHAI, + BS3CPUVENDOR_HYGON, + BS3CPUVENDOR_UNKNOWN, + BS3CPUVENDOR_END +} BS3CPUVENDOR; + +/** + * Tries to detect the CPU vendor. + * + * @returns CPU vendor. + */ +BS3_CMN_PROTO_STUB(BS3CPUVENDOR, Bs3GetCpuVendor,(void)); + +/** + * Shutdown the system, never returns. + * + * This currently only works for VMs. When running on real systems it will + * just halt the CPU. + */ +BS3_CMN_PROTO_NOSB(void, Bs3Shutdown,(void)); + +/** + * Prints a 32-bit unsigned value as decimal to the screen. + * + * @param uValue The 32-bit value. + */ +BS3_CMN_PROTO_NOSB(void, Bs3PrintU32,(uint32_t uValue)); + +/** + * Prints a 32-bit unsigned value as hex to the screen. + * + * @param uValue The 32-bit value. + */ +BS3_CMN_PROTO_NOSB(void, Bs3PrintX32,(uint32_t uValue)); + +/** + * Formats and prints a string to the screen. + * + * See #Bs3StrFormatV for supported format types. + * + * @param pszFormat The format string. + * @param ... Format arguments. + */ +BS3_CMN_PROTO_STUB(size_t, Bs3Printf,(const char BS3_FAR *pszFormat, ...)); + +/** + * Formats and prints a string to the screen, va_list version. + * + * See #Bs3StrFormatV for supported format types. + * + * @param pszFormat The format string. + * @param va Format arguments. + */ +BS3_CMN_PROTO_STUB(size_t, Bs3PrintfV,(const char BS3_FAR *pszFormat, va_list BS3_FAR va)); + +/** + * Prints a string to the screen. + * + * @param pszString The string to print. + */ +BS3_CMN_PROTO_STUB(void, Bs3PrintStr,(const char BS3_FAR *pszString)); + +/** + * Prints a string to the screen. + * + * @param pszString The string to print. Any terminator charss will be printed. + * @param cchString The exact number of characters to print. + */ +BS3_CMN_PROTO_NOSB(void, Bs3PrintStrN,(const char BS3_FAR *pszString, size_t cchString)); + +/** + * Prints a char to the screen. + * + * @param ch The character to print. + */ +BS3_CMN_PROTO_NOSB(void, Bs3PrintChr,(char ch)); + + +/** + * An output function for #Bs3StrFormatV. + * + * @returns Number of characters written. + * @param ch The character to write. Zero in the final call. + * @param pvUser User argument supplied to #Bs3StrFormatV. + */ +typedef BS3_DECL_CALLBACK(size_t) FNBS3STRFORMATOUTPUT(char ch, void BS3_FAR *pvUser); +/** Pointer to an output function for #Bs3StrFormatV. */ +typedef FNBS3STRFORMATOUTPUT *PFNBS3STRFORMATOUTPUT; + +/** + * Formats a string, sending the output to @a pfnOutput. + * + * Supported types: + * - %RI8, %RI16, %RI32, %RI64 + * - %RU8, %RU16, %RU32, %RU64 + * - %RX8, %RX16, %RX32, %RX64 + * - %i, %d + * - %u + * - %x + * - %c + * - %p (far pointer) + * - %s (far pointer) + * + * @returns Sum of @a pfnOutput return values. + * @param pszFormat The format string. + * @param va Format arguments. + * @param pfnOutput The output function. + * @param pvUser The user argument for the output function. + */ +BS3_CMN_PROTO_STUB(size_t, Bs3StrFormatV,(const char BS3_FAR *pszFormat, va_list BS3_FAR va, + PFNBS3STRFORMATOUTPUT pfnOutput, void BS3_FAR *pvUser)); + +/** + * Formats a string into a buffer. + * + * See #Bs3StrFormatV for supported format types. + * + * @returns The length of the formatted string (excluding terminator). + * This will be higher or equal to @c cbBuf in case of an overflow. + * @param pszBuf The output buffer. + * @param cbBuf The size of the output buffer. + * @param pszFormat The format string. + * @param va Format arguments. + */ +BS3_CMN_PROTO_STUB(size_t, Bs3StrPrintfV,(char BS3_FAR *pszBuf, size_t cbBuf, const char BS3_FAR *pszFormat, va_list BS3_FAR va)); + +/** + * Formats a string into a buffer. + * + * See #Bs3StrFormatV for supported format types. + * + * @returns The length of the formatted string (excluding terminator). + * This will be higher or equal to @c cbBuf in case of an overflow. + * @param pszBuf The output buffer. + * @param cbBuf The size of the output buffer. + * @param pszFormat The format string. + * @param ... Format arguments. + */ +BS3_CMN_PROTO_STUB(size_t, Bs3StrPrintf,(char BS3_FAR *pszBuf, size_t cbBuf, const char BS3_FAR *pszFormat, ...)); + + +/** + * Finds the length of a zero terminated string. + * + * @returns String length in chars/bytes. + * @param pszString The string to examine. + */ +BS3_CMN_PROTO_STUB(size_t, Bs3StrLen,(const char BS3_FAR *pszString)); + +/** + * Finds the length of a zero terminated string, but with a max length. + * + * @returns String length in chars/bytes, or @a cchMax if no zero-terminator + * was found before we reached the limit. + * @param pszString The string to examine. + * @param cchMax The max length to examine. + */ +BS3_CMN_PROTO_STUB(size_t, Bs3StrNLen,(const char BS3_FAR *pszString, size_t cchMax)); + +/** + * CRT style unsafe strcpy. + * + * @returns pszDst. + * @param pszDst The destination buffer. Must be large enough to + * hold the source string. + * @param pszSrc The source string. + */ +BS3_CMN_PROTO_STUB(char BS3_FAR *, Bs3StrCpy,(char BS3_FAR *pszDst, const char BS3_FAR *pszSrc)); + +/** + * CRT style memcpy. + * + * @returns pvDst + * @param pvDst The destination buffer. + * @param pvSrc The source buffer. + * @param cbToCopy The number of bytes to copy. + */ +BS3_CMN_PROTO_STUB(void BS3_FAR *, Bs3MemCpy,(void BS3_FAR *pvDst, const void BS3_FAR *pvSrc, size_t cbToCopy)); + +/** + * GNU (?) style mempcpy. + * + * @returns pvDst + cbCopy + * @param pvDst The destination buffer. + * @param pvSrc The source buffer. + * @param cbToCopy The number of bytes to copy. + */ +BS3_CMN_PROTO_STUB(void BS3_FAR *, Bs3MemPCpy,(void BS3_FAR *pvDst, const void BS3_FAR *pvSrc, size_t cbToCopy)); + +/** + * CRT style memmove (overlapping buffers is fine). + * + * @returns pvDst + * @param pvDst The destination buffer. + * @param pvSrc The source buffer. + * @param cbToCopy The number of bytes to copy. + */ +BS3_CMN_PROTO_STUB(void BS3_FAR *, Bs3MemMove,(void BS3_FAR *pvDst, const void BS3_FAR *pvSrc, size_t cbToCopy)); + +/** + * BSD style bzero. + * + * @param pvDst The buffer to be zeroed. + * @param cbDst The number of bytes to zero. + */ +BS3_CMN_PROTO_NOSB(void, Bs3MemZero,(void BS3_FAR *pvDst, size_t cbDst)); + +/** + * CRT style memset. + * + * @param pvDst The buffer to be fill. + * @param bFiller The filler byte. + * @param cbDst The number of bytes to fill. + */ +BS3_CMN_PROTO_NOSB(void, Bs3MemSet,(void BS3_FAR *pvDst, uint8_t bFiller, size_t cbDst)); + +/** + * CRT style memchr. + * + * @param pvHaystack The memory to scan for @a bNeedle. + * @param bNeedle The byte to search for. + * @param cbHaystack The amount of memory to search. + */ +BS3_CMN_PROTO_NOSB(void BS3_FAR *, Bs3MemChr,(void const BS3_FAR *pvHaystack, uint8_t bNeedle, size_t cbHaystack)); + +/** + * CRT style memcmp. + * + * @returns 0 if equal. Negative if the left side is 'smaller' than the right + * side, and positive in the other case. + * @param pv1 The left hand memory. + * @param pv2 The right hand memory. + * @param cb The number of bytes to compare. + */ +BS3_CMN_PROTO_NOSB(int, Bs3MemCmp,(void const BS3_FAR *pv1, void const BS3_FAR *pv2, size_t cb)); + +BS3_CMN_PROTO_STUB(void, Bs3UInt64Div,(RTUINT64U uDividend, RTUINT64U uDivisor, RTUINT64U BS3_FAR *paQuotientReminder)); +BS3_CMN_PROTO_STUB(void, Bs3UInt32Div,(RTUINT32U uDividend, RTUINT32U uDivisor, RTUINT32U BS3_FAR *paQuotientReminder)); + + +/** + * Converts a protected mode 32-bit far pointer to a 32-bit flat address. + * + * @returns 32-bit flat address. + * @param off The segment offset. + * @param uSel The protected mode segment selector. + */ +BS3_CMN_PROTO_STUB(uint32_t, Bs3SelProtFar32ToFlat32,(uint32_t off, uint16_t uSel)); + +/** + * Converts a current mode 32-bit far pointer to a 32-bit flat address. + * + * @returns 32-bit flat address. + * @param off The segment offset. + * @param uSel The current mode segment selector. + */ +BS3_CMN_PROTO_STUB(uint32_t, Bs3SelFar32ToFlat32,(uint32_t off, uint16_t uSel)); + +/** + * Wrapper around Bs3SelFar32ToFlat32 that makes it easier to use in tight + * assembly spots. + * + * @returns 32-bit flat address. + * @param off The segment offset. + * @param uSel The current mode segment selector. + * @remarks All register are preserved, except return. + * @remarks No 20h scratch space required in 64-bit mode. + */ +BS3_CMN_PROTO_FARSTUB(6, uint32_t, Bs3SelFar32ToFlat32NoClobber,(uint32_t off, uint16_t uSel)); + +/** + * Converts a real mode code segment to a protected mode code segment selector. + * + * @returns protected mode segment selector. + * @param uRealSeg Real mode code segment. + * @remarks All register are preserved, except return and parameter. + */ +BS3_CMN_PROTO_NOSB(uint16_t, Bs3SelRealModeCodeToProtMode,(uint16_t uRealSeg)); + +/** + * Converts a real mode code segment to a protected mode code segment selector. + * + * @returns protected mode segment selector. + * @param uProtSel Real mode code segment. + * @remarks All register are preserved, except return and parameter. + */ +BS3_CMN_PROTO_NOSB(uint16_t, Bs3SelProtModeCodeToRealMode,(uint16_t uProtSel)); + +/** + * Converts a flat code address to a real mode segment and offset. + * + * @returns Far real mode address (high 16-bit is segment, low is offset). + * @param uFlatAddr Flat code address. + * @remarks All register are preserved, except return and parameter. + */ +BS3_CMN_PROTO_NOSB(uint32_t, Bs3SelFlatCodeToRealMode,(uint32_t uFlatAddr)); + +/** + * Converts a flat code address to a protected mode 16-bit far pointer (ring-0). + * + * @returns Far 16-bit protected mode address (high 16-bit is segment selector, + * low is segment offset). + * @param uFlatAddr Flat code address. + * @remarks All register are preserved, except return and parameter. + */ +BS3_CMN_PROTO_NOSB(uint32_t, Bs3SelFlatCodeToProtFar16,(uint32_t uFlatAddr)); + +/** + * Converts a far 16:16 real mode (code) address to a flat address. + * + * @returns 32-bit flat address. + * @param uFar1616 Far real mode address (high 16-bit is segment, low + * is offset). + * @remarks All register are preserved, except return. + * @remarks No 20h scratch space required in 64-bit mode. + * @remarks Exactly the same as Bs3SelRealModeDataToFlat, except for param. + */ +BS3_CMN_PROTO_FARSTUB(4, uint32_t, Bs3SelRealModeCodeToFlat,(PFNBS3FARADDRCONV uFar1616)); + +/** + * Converts a flat data address to a real mode segment and offset. + * + * @returns Far real mode address (high 16-bit is segment, low is offset) + * @param uFlatAddr Flat code address. + * @remarks All register are preserved, except return. + * @remarks No 20h scratch space required in 64-bit mode. + */ +BS3_CMN_PROTO_FARSTUB(4, uint32_t, Bs3SelFlatDataToRealMode,(uint32_t uFlatAddr)); + +/** + * Converts a flat data address to a real mode segment and offset. + * + * @returns Far 16-bit protected mode address (high 16-bit is segment selector, + * low is segment offset). + * @param uFlatAddr Flat code address. + * @remarks All register are preserved, except return. + * @remarks No 20h scratch space required in 64-bit mode. + */ +BS3_CMN_PROTO_FARSTUB(4, uint32_t, Bs3SelFlatDataToProtFar16,(uint32_t uFlatAddr)); + +/** + * Converts a far 16:16 data address to a real mode segment and offset. + * + * @returns Far real mode address (high 16-bit is segment, low is offset) + * @param uFar1616 Far 16-bit protected mode address (high 16-bit is + * segment selector, low is segment offset). + * @remarks All register are preserved, except return. + * @remarks No 20h scratch space required in 64-bit mode. + */ +BS3_CMN_PROTO_FARSTUB(4, uint32_t, Bs3SelProtFar16DataToRealMode,(uint32_t uFar1616)); + +/** + * Converts a far 16:16 real mode address to a 16-bit protected mode address. + * + * @returns Far real mode address (high 16-bit is segment, low is offset) + * @param uFar1616 Far real mode address (high 16-bit is segment, low + * is offset). + * @remarks All register are preserved, except return. + * @remarks No 20h scratch space required in 64-bit mode. + */ +BS3_CMN_PROTO_FARSTUB(4, uint32_t, Bs3SelRealModeDataToProtFar16,(uint32_t uFar1616)); + +/** + * Converts a far 16:16 data address to a flat 32-bit address. + * + * @returns 32-bit flat address. + * @param uFar1616 Far 16-bit protected mode address (high 16-bit is + * segment selector, low is segment offset). + * @remarks All register are preserved, except return. + * @remarks No 20h scratch space required in 64-bit mode. + */ +BS3_CMN_PROTO_FARSTUB(4, uint32_t, Bs3SelProtFar16DataToFlat,(uint32_t uFar1616)); + +/** + * Converts a far 16:16 real mode address to a flat address. + * + * @returns 32-bit flat address. + * @param uFar1616 Far real mode address (high 16-bit is segment, low + * is offset). + * @remarks All register are preserved, except return. + * @remarks No 20h scratch space required in 64-bit mode. + */ +BS3_CMN_PROTO_FARSTUB(4, uint32_t, Bs3SelRealModeDataToFlat,(uint32_t uFar1616)); + +/** + * Converts a link-time pointer to a current context pointer. + * + * @returns Converted pointer. + * @param pvLnkPtr The pointer the linker produced. + */ +BS3_CMN_PROTO_FARSTUB(4, void BS3_FAR *, Bs3SelLnkPtrToCurPtr,(void BS3_FAR *pvLnkPtr)); + +/** + * Converts a link-time pointer to a flat address. + * + * @returns 32-bit flag address. + * @param pvLnkPtr The pointer the linker produced. + */ +BS3_CMN_PROTO_FARSTUB(4, uint32_t, Bs3SelLnkPtrToFlat,(void BS3_FAR *pvLnkPtr)); + +/** + * Gets a flat address from a working poitner. + * + * @returns flat address (32-bit or 64-bit). + * @param pv Current context pointer. + */ +DECLINLINE(RTCCUINTXREG) Bs3SelPtrToFlat(void BS3_FAR *pv) +{ +#if ARCH_BITS == 16 + return BS3_CMN_FN_NM(Bs3SelFar32ToFlat32)(BS3_FP_OFF(pv), BS3_FP_SEG(pv)); +#else + return (uintptr_t)pv; +#endif +} + +/** + * Sets up a 16-bit read-write data selector with ring-3 access and 64KB limit. + * + * @param pDesc Pointer to the descriptor table entry. + * @param uBaseAddr The base address of the descriptor. + */ +BS3_CMN_PROTO_STUB(void, Bs3SelSetup16BitData,(X86DESC BS3_FAR *pDesc, uint32_t uBaseAddr)); + +/** + * Sets up a 16-bit execute-read selector with a 64KB limit. + * + * @param pDesc Pointer to the descriptor table entry. + * @param uBaseAddr The base address of the descriptor. + * @param bDpl The descriptor privilege level. + */ +BS3_CMN_PROTO_STUB(void, Bs3SelSetup16BitCode,(X86DESC BS3_FAR *pDesc, uint32_t uBaseAddr, uint8_t bDpl)); + +/** + * Sets up a 32-bit execute-read selector with a user specified limit. + * + * @param pDesc Pointer to the descriptor table entry. + * @param uBaseAddr The base address of the descriptor. + * @param uLimit The limit. (This is included here and not in the 16-bit + * functions because we're more likely to want to set it + * than for 16-bit selectors.) + * @param bDpl The descriptor privilege level. + */ +BS3_CMN_PROTO_STUB(void, Bs3SelSetup32BitCode,(X86DESC BS3_FAR *pDesc, uint32_t uBaseAddr, uint32_t uLimit, uint8_t bDpl)); + +/** + * Sets up a 16-bit or 32-bit gate descriptor. + * + * This can be used both for GDT/LDT and IDT. + * + * @param pDesc Pointer to the descriptor table entry. + * @param bType The gate type. + * @param bDpl The gate DPL. + * @param uSel The gate selector value. + * @param off The gate IP/EIP value. + * @param cParams Number of parameters to copy if call-gate. + */ +BS3_CMN_PROTO_STUB(void, Bs3SelSetupGate,(X86DESC BS3_FAR *pDesc, uint8_t bType, uint8_t bDpl, + uint16_t uSel, uint32_t off, uint8_t cParams)); + +/** + * Sets up a 64-bit gate descriptor. + * + * This can be used both for GDT/LDT and IDT. + * + * @param pDescPair Pointer to the _two_ descriptor table entries. + * @param bType The gate type. + * @param bDpl The gate DPL. + * @param uSel The gate selector value. + * @param off The gate IP/EIP value. + */ +BS3_CMN_PROTO_STUB(void, Bs3SelSetupGate64,(X86DESC BS3_FAR *pDescPair, uint8_t bType, uint8_t bDpl, uint16_t uSel, uint64_t off)); + + +/** + * Slab control structure list head. + * + * The slabs on the list must all have the same chunk size. + */ +typedef struct BS3SLABHEAD +{ + /** Pointer to the first slab. */ + BS3_XPTR_MEMBER(struct BS3SLABCTL, pFirst); + /** The allocation chunk size. */ + uint16_t cbChunk; + /** Number of slabs in the list. */ + uint16_t cSlabs; + /** Number of chunks in the list. */ + uint32_t cChunks; + /** Number of free chunks. */ + uint32_t cFreeChunks; +} BS3SLABHEAD; +AssertCompileSize(BS3SLABHEAD, 16); +/** Pointer to a slab list head. */ +typedef BS3SLABHEAD BS3_FAR *PBS3SLABHEAD; + +/** + * Allocation slab control structure. + * + * This may live at the start of the slab for 4KB slabs, while in a separate + * static location for the larger ones. + */ +typedef struct BS3SLABCTL +{ + /** Pointer to the next slab control structure in this list. */ + BS3_XPTR_MEMBER(struct BS3SLABCTL, pNext); + /** Pointer to the slab list head. */ + BS3_XPTR_MEMBER(BS3SLABHEAD, pHead); + /** The base address of the slab. */ + BS3_XPTR_MEMBER(uint8_t, pbStart); + /** Number of chunks in this slab. */ + uint16_t cChunks; + /** Number of currently free chunks. */ + uint16_t cFreeChunks; + /** The chunk size. */ + uint16_t cbChunk; + /** The shift count corresponding to cbChunk. + * This is for turning a chunk number into a byte offset and vice versa. */ + uint16_t cChunkShift; + /** Bitmap where set bits indicates allocated blocks (variable size, + * multiple of 4). */ + uint8_t bmAllocated[4]; +} BS3SLABCTL; +/** Pointer to a bs3kit slab control structure. */ +typedef BS3SLABCTL BS3_FAR *PBS3SLABCTL; + +/** The chunks must all be in the same 16-bit segment tile. */ +#define BS3_SLAB_ALLOC_F_SAME_TILE UINT16_C(0x0001) + +/** + * Initializes a slab. + * + * @param pSlabCtl The slab control structure to initialize. + * @param cbSlabCtl The size of the slab control structure. + * @param uFlatSlabPtr The base address of the slab. + * @param cbSlab The size of the slab. + * @param cbChunk The chunk size. + */ +BS3_CMN_PROTO_STUB(void, Bs3SlabInit,(PBS3SLABCTL pSlabCtl, size_t cbSlabCtl, uint32_t uFlatSlabPtr, + uint32_t cbSlab, uint16_t cbChunk)); + +/** + * Allocates one chunk from a slab. + * + * @returns Pointer to a chunk on success, NULL if we're out of chunks. + * @param pSlabCtl The slab control structure to allocate from. + */ +BS3_CMN_PROTO_STUB(void BS3_FAR *, Bs3SlabAlloc,(PBS3SLABCTL pSlabCtl)); + +/** + * Allocates one or more chunks rom a slab. + * + * @returns Pointer to the request number of chunks on success, NULL if we're + * out of chunks. + * @param pSlabCtl The slab control structure to allocate from. + * @param cChunks The number of contiguous chunks we want. + * @param fFlags Flags, see BS3_SLAB_ALLOC_F_XXX + */ +BS3_CMN_PROTO_STUB(void BS3_FAR *, Bs3SlabAllocEx,(PBS3SLABCTL pSlabCtl, uint16_t cChunks, uint16_t fFlags)); + +/** + * Frees one or more chunks from a slab. + * + * @returns Number of chunks actually freed. When correctly used, this will + * match the @a cChunks parameter, of course. + * @param pSlabCtl The slab control structure to free from. + * @param uFlatChunkPtr The flat address of the chunks to free. + * @param cChunks The number of contiguous chunks to free. + */ +BS3_CMN_PROTO_STUB(uint16_t, Bs3SlabFree,(PBS3SLABCTL pSlabCtl, uint32_t uFlatChunkPtr, uint16_t cChunks)); + + +/** + * Initializes the given slab list head. + * + * @param pHead The slab list head. + * @param cbChunk The chunk size. + */ +BS3_CMN_PROTO_STUB(void, Bs3SlabListInit,(PBS3SLABHEAD pHead, uint16_t cbChunk)); + +/** + * Adds an initialized slab control structure to the list. + * + * @param pHead The slab list head to add it to. + * @param pSlabCtl The slab control structure to add. + */ +BS3_CMN_PROTO_STUB(void, Bs3SlabListAdd,(PBS3SLABHEAD pHead, PBS3SLABCTL pSlabCtl)); + +/** + * Allocates one chunk. + * + * @returns Pointer to a chunk on success, NULL if we're out of chunks. + * @param pHead The slab list to allocate from. + */ +BS3_CMN_PROTO_STUB(void BS3_FAR *, Bs3SlabListAlloc,(PBS3SLABHEAD pHead)); + +/** + * Allocates one or more chunks. + * + * @returns Pointer to the request number of chunks on success, NULL if we're + * out of chunks. + * @param pHead The slab list to allocate from. + * @param cChunks The number of contiguous chunks we want. + * @param fFlags Flags, see BS3_SLAB_ALLOC_F_XXX + */ +BS3_CMN_PROTO_STUB(void BS3_FAR *, Bs3SlabListAllocEx,(PBS3SLABHEAD pHead, uint16_t cChunks, uint16_t fFlags)); + +/** + * Frees one or more chunks from a slab list. + * + * @param pHead The slab list to allocate from. + * @param pvChunks Pointer to the first chunk to free. + * @param cChunks The number of contiguous chunks to free. + */ +BS3_CMN_PROTO_STUB(void, Bs3SlabListFree,(PBS3SLABHEAD pHead, void BS3_FAR *pvChunks, uint16_t cChunks)); + +/** + * Allocation addressing constraints. + */ +typedef enum BS3MEMKIND +{ + /** Invalid zero type. */ + BS3MEMKIND_INVALID = 0, + /** Real mode addressable memory. */ + BS3MEMKIND_REAL, + /** Memory addressable using the 16-bit protected mode tiling. */ + BS3MEMKIND_TILED, + /** Memory addressable using 32-bit flat addressing. */ + BS3MEMKIND_FLAT32, + /** Memory addressable using 64-bit flat addressing. */ + BS3MEMKIND_FLAT64, + /** End of valid types. */ + BS3MEMKIND_END, +} BS3MEMKIND; + +/** + * Allocates low memory. + * + * @returns Pointer to a chunk on success, NULL if we're out of chunks. + * @param enmKind The kind of addressing constraints imposed on the + * allocation. + * @param cb How much to allocate. + */ +BS3_CMN_PROTO_STUB(void BS3_FAR *, Bs3MemAlloc,(BS3MEMKIND enmKind, size_t cb)); + +/** + * Allocates zero'ed memory. + * + * @param enmKind The kind of addressing constraints imposed on the + * allocation. + * @param cb How much to allocate. + */ +BS3_CMN_PROTO_STUB(void BS3_FAR *, Bs3MemAllocZ,(BS3MEMKIND enmKind, size_t cb)); + +/** + * Frees memory. + * + * @returns Pointer to a chunk on success, NULL if we're out of chunks. + * @param pv The memory to free (returned by #Bs3MemAlloc). + * @param cb The size of the allocation. + */ +BS3_CMN_PROTO_STUB(void, Bs3MemFree,(void BS3_FAR *pv, size_t cb)); + +/** + * Allocates a page with non-present pages on each side. + * + * @returns Pointer to the usable page. NULL on failure. Use + * Bs3MemGuardedTestPageFree to free the allocation. + * @param enmKind The kind of addressing constraints imposed on the + * allocation. + */ +BS3_CMN_PROTO_STUB(void BS3_FAR *, Bs3MemGuardedTestPageAlloc,(BS3MEMKIND enmKind)); + +/** + * Allocates a page with pages on each side to the @a fPte specification. + * + * @returns Pointer to the usable page. NULL on failure. Use + * Bs3MemGuardedTestPageFree to free the allocation. + * @param enmKind The kind of addressing constraints imposed on the + * allocation. + * @param fPte The page table entry specification for the guard pages. + */ +BS3_CMN_PROTO_STUB(void BS3_FAR *, Bs3MemGuardedTestPageAllocEx,(BS3MEMKIND enmKind, uint64_t fPte)); + +/** + * Frees guarded page allocated by Bs3MemGuardedTestPageAlloc or + * Bs3MemGuardedTestPageAllocEx. + * + * @param pvGuardedPage Pointer returned by Bs3MemGuardedTestPageAlloc or + * Bs3MemGuardedTestPageAllocEx. NULL is ignored. + */ +BS3_CMN_PROTO_STUB(void, Bs3MemGuardedTestPageFree,(void BS3_FAR *pvGuardedPage)); + +/** + * Print all heap info. + */ +BS3_CMN_PROTO_STUB(void, Bs3MemPrintInfo, (void)); + +/** The end RAM address below 4GB (approximately). */ +extern uint32_t g_uBs3EndOfRamBelow4G; +/** The end RAM address above 4GB, zero if no memory above 4GB. */ +extern uint64_t g_uBs3EndOfRamAbove4G; + + +/** + * Enables the A20 gate. + */ +BS3_CMN_PROTO_NOSB(void, Bs3A20Enable,(void)); + +/** + * Enables the A20 gate via the keyboard controller + */ +BS3_CMN_PROTO_NOSB(void, Bs3A20EnableViaKbd,(void)); + +/** + * Enables the A20 gate via the PS/2 control port A. + */ +BS3_CMN_PROTO_NOSB(void, Bs3A20EnableViaPortA,(void)); + +/** + * Disables the A20 gate. + */ +BS3_CMN_PROTO_NOSB(void, Bs3A20Disable,(void)); + +/** + * Disables the A20 gate via the keyboard controller + */ +BS3_CMN_PROTO_NOSB(void, Bs3A20DisableViaKbd,(void)); + +/** + * Disables the A20 gate via the PS/2 control port A. + */ +BS3_CMN_PROTO_NOSB(void, Bs3A20DisableViaPortA,(void)); + + +/** + * Initializes root page tables for page protected mode (PP16, PP32). + * + * @returns IPRT status code. + * @remarks Must not be called in real-mode! + */ +BS3_CMN_PROTO_STUB(int, Bs3PagingInitRootForPP,(void)); + +/** + * Initializes root page tables for PAE page protected mode (PAE16, PAE32). + * + * @returns IPRT status code. + * @remarks The default long mode page tables depends on the PAE ones. + * @remarks Must not be called in real-mode! + */ +BS3_CMN_PROTO_STUB(int, Bs3PagingInitRootForPAE,(void)); + +/** + * Initializes root page tables for long mode (LM16, LM32, LM64). + * + * @returns IPRT status code. + * @remarks The default long mode page tables depends on the PAE ones. + * @remarks Must not be called in real-mode! + */ +BS3_CMN_PROTO_STUB(int, Bs3PagingInitRootForLM,(void)); + +/** + * Maps all RAM above 4GB into the long mode page tables. + * + * This requires Bs3PagingInitRootForLM to have been called first. + * + * @returns IPRT status code. + * @retval VERR_WRONG_ORDER if Bs3PagingInitRootForLM wasn't called. + * @retval VINF_ALREADY_INITIALIZED if already called or someone mapped + * something else above 4GiB already. + * @retval VERR_OUT_OF_RANGE if too much RAM (more than 2^47 bytes). + * @retval VERR_NO_MEMORY if no more memory for paging structures. + * @retval VERR_UNSUPPORTED_ALIGNMENT if the bs3kit allocator malfunctioned and + * didn't give us page aligned memory as it should. + * + * @param puFailurePoint Where to return the address where we encountered + * a failure. Optional. + * + * @remarks Must be called in 32-bit or 64-bit mode as paging structures will be + * allocated using BS3MEMKIND_FLAT32, as there might not be sufficient + * BS3MEMKIND_TILED memory around. (Also, too it's simply too much of + * a bother to deal with 16-bit for something that's long-mode only.) + */ +BS3_CMN_PROTO_STUB(int, Bs3PagingMapRamAbove4GForLM,(uint64_t *puFailurePoint)); + +/** + * Modifies the page table protection of an address range. + * + * This only works on the lowest level of the page tables in the current mode. + * + * Since we generally use the largest pages available when setting up the + * initial page tables, this function will usually have to allocate and create + * more tables. This may fail if we're low on memory. + * + * @returns IPRT status code. + * @param uFlat The flat address of the first page in the range (rounded + * down nearest page boundrary). + * @param cb The range size from @a pv (rounded up to nearest page boundrary). + * @param fSet Mask of zero or more X86_PTE_XXX values to set for the range. + * @param fClear Mask of zero or more X86_PTE_XXX values to clear for the range. + */ +BS3_CMN_PROTO_STUB(int, Bs3PagingProtect,(uint64_t uFlat, uint64_t cb, uint64_t fSet, uint64_t fClear)); + +/** + * Modifies the page table protection of an address range. + * + * This only works on the lowest level of the page tables in the current mode. + * + * Since we generally use the largest pages available when setting up the + * initial page tables, this function will usually have to allocate and create + * more tables. This may fail if we're low on memory. + * + * @returns IPRT status code. + * @param pv The address of the first page in the range (rounded + * down nearest page boundrary). + * @param cb The range size from @a pv (rounded up to nearest page boundrary). + * @param fSet Mask of zero or more X86_PTE_XXX values to set for the range. + * @param fClear Mask of zero or more X86_PTE_XXX values to clear for the range. + */ +BS3_CMN_PROTO_STUB(int, Bs3PagingProtectPtr,(void BS3_FAR *pv, size_t cb, uint64_t fSet, uint64_t fClear)); + +/** + * Aliases (maps) one or more contiguous physical pages to a virtual range. + * + * @returns VBox status code. + * @retval VERR_INVALID_PARAMETER if we're in legacy paging mode and @a uDst or + * @a uPhysToAlias are not compatible with legacy paging. + * @retval VERR_OUT_OF_RANGE if we cannot traverse the page tables in this mode + * (typically real mode or v86, maybe 16-bit PE). + * @retval VERR_NO_MEMORY if we cannot allocate page tables for splitting up + * the necessary large pages. No aliasing was performed. + * + * @param uDst The virtual address to map it at. Rounded down + * to the nearest page (@a cbHowMuch is adjusted + * up). + * @param uPhysToAlias The physical address of the first page in the + * (contiguous) range to map. Chopped down to + * nearest page boundrary (@a cbHowMuch is not + * adjusted). + * @param cbHowMuch How much to map. Rounded up to nearest page. + * @param fPte The PTE flags. + */ +BS3_CMN_PROTO_STUB(int, Bs3PagingAlias,(uint64_t uDst, uint64_t uPhysToAlias, uint32_t cbHowMuch, uint64_t fPte)); + +/** + * Unaliases memory, i.e. restores the 1:1 mapping. + * + * @returns VBox status code. Cannot fail if @a uDst and @a cbHowMuch specify + * the range of a successful Bs3PagingAlias call, however it may run + * out of memory if it's breaking new ground. + * + * @param uDst The virtual address to restore to 1:1 mapping. + * Rounded down to the nearest page (@a cbHowMuch + * is adjusted up). + * @param cbHowMuch How much to restore. Rounded up to nearest page. + */ +BS3_CMN_PROTO_STUB(int, Bs3PagingUnalias,(uint64_t uDst, uint32_t cbHowMuch)); + +/** + * Get the pointer to the PTE for the given address. + * + * @returns Pointer to the PTE. + * @param uFlat The flat address of the page which PTE we want. + * @param prc Where to return additional error info. Optional. + */ +BS3_CMN_PROTO_STUB(void BS3_FAR *, Bs3PagingGetPte,(uint64_t uFlat, int *prc)); + +/** + * Paging information for an address. + */ +typedef struct BS3PAGINGINFO4ADDR +{ + /** The depth of the system's paging mode. + * This is always 2 for legacy, 3 for PAE and 4 for long mode. */ + uint8_t cEntries; + /** The size of the page structures (the entires). */ + uint8_t cbEntry; + /** Flags defined for future fun, currently zero. */ + uint16_t fFlags; + /** Union display different view on the entry pointers. */ + union + { + /** Pointer to the page structure entries, starting with the PTE as 0. + * If large pages are involved, the first entry will be NULL (first two if 1GB + * page). Same if the address is invalid on a higher level. */ + uint8_t BS3_FAR *apbEntries[4]; + /** Alternative view for legacy mode. */ + struct + { + X86PTE BS3_FAR *pPte; + X86PDE BS3_FAR *pPde; + void *pvUnused2; + void *pvUnused3; + } Legacy; + /** Alternative view for PAE and Long mode. */ + struct + { + X86PTEPAE BS3_FAR *pPte; + X86PDEPAE BS3_FAR *pPde; + X86PDPE BS3_FAR *pPdpe; + X86PML4E BS3_FAR *pPml4e; + } Pae; + } u; +} BS3PAGINGINFO4ADDR; +/** Pointer to paging information for and address. */ +typedef BS3PAGINGINFO4ADDR BS3_FAR *PBS3PAGINGINFO4ADDR; + +/** + * Queries paging information about the given virtual address. + * + * @returns VBox status code. + * @param uFlat The flat address to query information about. + * @param pPgInfo Where to return the information. + */ +BS3_CMN_PROTO_STUB(int, Bs3PagingQueryAddressInfo,(uint64_t uFlat, PBS3PAGINGINFO4ADDR pPgInfo)); + + +/** The physical / flat address of the buffer backing the canonical traps. + * This buffer is spread equally on each side of the 64-bit non-canonical + * address divide. Non-64-bit code can use this to setup trick shots and + * inspect their results. */ +extern uint32_t g_uBs3PagingCanonicalTrapsAddr; +/** The size of the buffer at g_uPagingCanonicalTraps (both sides). */ +extern uint16_t g_cbBs3PagingCanonicalTraps; +/** The size of one trap buffer (low or high). + * This is g_cbBs3PagingCanonicalTraps divided by two. */ +extern uint16_t g_cbBs3PagingOneCanonicalTrap; + +/** + * Sets up the 64-bit canonical address space trap buffers, if neceessary. + * + * @returns Pointer to the buffers (i.e. the first page of the low one) on + * success. NULL on failure. + */ +BS3_CMN_PROTO_STUB(void BS3_FAR *, Bs3PagingSetupCanonicalTraps,(void)); + +/** + * Waits for the keyboard controller to become ready. + */ +BS3_CMN_PROTO_NOSB(void, Bs3KbdWait,(void)); + +/** + * Sends a read command to the keyboard controller and gets the result. + * + * The caller is responsible for making sure the keyboard controller is ready + * for a command (call #Bs3KbdWait if unsure). + * + * @returns The value read is returned (in al). + * @param bCmd The read command. + */ +BS3_CMN_PROTO_NOSB(uint8_t, Bs3KbdRead,(uint8_t bCmd)); + +/** + * Sends a write command to the keyboard controller and then sends the data. + * + * The caller is responsible for making sure the keyboard controller is ready + * for a command (call #Bs3KbdWait if unsure). + * + * @param bCmd The write command. + * @param bData The data to write. + */ +BS3_CMN_PROTO_NOSB(void, Bs3KbdWrite,(uint8_t bCmd, uint8_t bData)); + + +/** + * Configures the PIC, once only. + * + * Subsequent calls to this function will not do anything. + * + * The PIC will be programmed to use IDT/IVT vectors 0x70 thru 0x7f, auto + * end-of-interrupt, and all IRQs masked. The individual PIC users will have to + * use #Bs3PicUpdateMask unmask their IRQ once they've got all the handlers + * installed. + * + * @param fForcedReInit Force a reinitialization. + */ +BS3_CMN_PROTO_STUB(void, Bs3PicSetup,(bool fForcedReInit)); + +/** + * Updates the PIC masks. + * + * @returns The new mask - master in low, slave in high byte. + * @param fAndMask Things to keep as-is. Master in low, slave in high byte. + * @param fOrMask Things to start masking. Ditto wrt bytes. + */ +BS3_CMN_PROTO_STUB(uint16_t, Bs3PicUpdateMask,(uint16_t fAndMask, uint16_t fOrMask)); + +/** + * Disables all IRQs on the PIC. + */ +BS3_CMN_PROTO_STUB(void, Bs3PicMaskAll,(void)); + + +/** + * Sets up the PIT for periodic callback. + * + * @param cHzDesired The desired Hz. Zero means max interval length + * (18.2Hz). Plase check the various PIT globals for + * the actual interval length. + */ +BS3_CMN_PROTO_STUB(void, Bs3PitSetupAndEnablePeriodTimer,(uint16_t cHzDesired)); + +/** + * Disables the PIT if active. + */ +BS3_CMN_PROTO_STUB(void, Bs3PitDisable,(void)); + +/** Nanoseconds (approx) since last the PIT timer was started. */ +extern uint64_t volatile g_cBs3PitNs; +/** Milliseconds seconds (very approx) since last the PIT timer was started. */ +extern uint64_t volatile g_cBs3PitMs; +/** Number of ticks since last the PIT timer was started. */ +extern uint32_t volatile g_cBs3PitTicks; +/** The current interval in nanoseconds. + * This is 0 if not yet started (cleared by Bs3PitDisable). */ +extern uint32_t g_cBs3PitIntervalNs; +/** The current interval in milliseconds (approximately). + * This is 0 if not yet started (cleared by Bs3PitDisable). */ +extern uint16_t g_cBs3PitIntervalMs; +/** The current PIT frequency (approximately). + * 0 if not yet started (cleared by Bs3PitDisable; used for checking the + * state internally). */ +extern uint16_t volatile g_cBs3PitIntervalHz; + + +/** + * Call 16-bit prot mode function from v8086 mode. + * + * This switches from v8086 mode to 16-bit protected mode (code) and executed + * @a fpfnCall with @a cbParams bytes of parameters pushed on the stack. + * Afterwards it switches back to v8086 mode and returns a 16-bit status code. + * + * @returns 16-bit status code if the function returned anything. + * @param fpfnCall Far real mode pointer to the function to call. + * @param cbParams The size of the parameter list, in bytes. + * @param ... The parameters. + * @sa Bs3SwitchTo32BitAndCallC + */ +BS3_CMN_PROTO_STUB(int, Bs3SwitchFromV86To16BitAndCallC,(FPFNBS3FAR fpfnCall, unsigned cbParams, ...)); + + +/** + * BS3 integer register. + */ +typedef union BS3REG +{ + /** 8-bit unsigned integer. */ + uint8_t u8; + /** 16-bit unsigned integer. */ + uint16_t u16; + /** 32-bit unsigned integer. */ + uint32_t u32; + /** 64-bit unsigned integer. */ + uint64_t u64; + /** Full unsigned integer. */ + uint64_t u; + /** High/low byte view. */ + struct + { + uint8_t bLo; + uint8_t bHi; + } b; + /** 8-bit view. */ + uint8_t au8[8]; + /** 16-bit view. */ + uint16_t au16[4]; + /** 32-bit view. */ + uint32_t au32[2]; + /** Unsigned integer, depending on compiler context. + * This generally follows ARCH_BITS. */ + RTCCUINTREG uCcReg; + /** Extended unsigned integer, depending on compiler context. + * This is 32-bit in 16-bit and 32-bit compiler contexts, and 64-bit in + * 64-bit. */ + RTCCUINTXREG uCcXReg; +} BS3REG; +/** Pointer to an integer register. */ +typedef BS3REG BS3_FAR *PBS3REG; +/** Pointer to a const integer register. */ +typedef BS3REG const BS3_FAR *PCBS3REG; + +/** + * Register context (without FPU). + */ +typedef struct BS3REGCTX +{ + BS3REG rax; /**< 0x00 */ + BS3REG rcx; /**< 0x08 */ + BS3REG rdx; /**< 0x10 */ + BS3REG rbx; /**< 0x18 */ + BS3REG rsp; /**< 0x20 */ + BS3REG rbp; /**< 0x28 */ + BS3REG rsi; /**< 0x30 */ + BS3REG rdi; /**< 0x38 */ + BS3REG r8; /**< 0x40 */ + BS3REG r9; /**< 0x48 */ + BS3REG r10; /**< 0x50 */ + BS3REG r11; /**< 0x58 */ + BS3REG r12; /**< 0x60 */ + BS3REG r13; /**< 0x68 */ + BS3REG r14; /**< 0x70 */ + BS3REG r15; /**< 0x78 */ + BS3REG rflags; /**< 0x80 */ + BS3REG rip; /**< 0x88 */ + uint16_t cs; /**< 0x90 */ + uint16_t ds; /**< 0x92 */ + uint16_t es; /**< 0x94 */ + uint16_t fs; /**< 0x96 */ + uint16_t gs; /**< 0x98 */ + uint16_t ss; /**< 0x9a */ + uint16_t tr; /**< 0x9c */ + uint16_t ldtr; /**< 0x9e */ + uint8_t bMode; /**< 0xa0: BS3_MODE_XXX. */ + uint8_t bCpl; /**< 0xa1: 0-3, 0 is used for real mode. */ + uint8_t fbFlags; /**< 0xa2: BS3REG_CTX_F_XXX */ + uint8_t abPadding[5]; /**< 0xa3 */ + BS3REG cr0; /**< 0xa8 */ + BS3REG cr2; /**< 0xb0 */ + BS3REG cr3; /**< 0xb8 */ + BS3REG cr4; /**< 0xc0 */ + uint64_t uUnused; /**< 0xc8 */ +} BS3REGCTX; +AssertCompileSize(BS3REGCTX, 0xd0); +/** Pointer to a register context. */ +typedef BS3REGCTX BS3_FAR *PBS3REGCTX; +/** Pointer to a const register context. */ +typedef BS3REGCTX const BS3_FAR *PCBS3REGCTX; + +/** @name BS3REG_CTX_F_XXX - BS3REGCTX::fbFlags masks. + * @{ */ +/** The CR0 is MSW (only low 16-bit). */ +#define BS3REG_CTX_F_NO_CR0_IS_MSW UINT8_C(0x01) +/** No CR2 and CR3 values. Not in CPL 0 or CPU too old for CR2 & CR3. */ +#define BS3REG_CTX_F_NO_CR2_CR3 UINT8_C(0x02) +/** No CR4 value. The CPU is too old for CR4. */ +#define BS3REG_CTX_F_NO_CR4 UINT8_C(0x04) +/** No TR and LDTR values. Context gathered in real mode or v8086 mode. */ +#define BS3REG_CTX_F_NO_TR_LDTR UINT8_C(0x08) +/** The context doesn't have valid values for AMD64 GPR extensions. */ +#define BS3REG_CTX_F_NO_AMD64 UINT8_C(0x10) +/** @} */ + +/** + * Saves the current register context. + * + * @param pRegCtx Where to store the register context. + */ +BS3_CMN_PROTO_NOSB(void, Bs3RegCtxSave,(PBS3REGCTX pRegCtx)); + +/** + * Switch to the specified CPU bitcount, reserve additional stack and save the + * CPU context. + * + * This is for writing more flexible test drivers that can test more than the + * CPU bitcount (16-bit, 32-bit, 64-bit, and virtual 8086) of the driver itself. + * For instance a 32-bit driver can do V86 and 16-bit testing, thus saving space + * by avoiding duplicate 16-bit driver code. + * + * @param pRegCtx Where to store the register context. + * @param bBitMode Bit mode to switch to, BS3_MODE_CODE_XXX. Only + * BS3_MODE_CODE_MASK is used, other bits are ignored + * to make it possible to pass a full mode value. + * @param cbExtraStack Number of bytes of additional stack to allocate. + */ +BS3_CMN_PROTO_FARSTUB(8, void, Bs3RegCtxSaveEx,(PBS3REGCTX pRegCtx, uint8_t bBitMode, uint16_t cbExtraStack)); + +/** + * This is Bs3RegCtxSaveEx with automatic Bs3RegCtxConvertV86ToRm thrown in. + * + * This is for simplifying writing 32-bit test drivers that covers real-mode as + * well as virtual 8086, 16-bit, 32-bit, and 64-bit modes. + * + * @param pRegCtx Where to store the register context. + * @param bMode The mode to get a context for. If this isn't + * BS3_MODE_RM, the BS3_MODE_SYS_MASK has to match the + * one of the current mode. + * @param cbExtraStack Number of bytes of additional stack to allocate. + */ +BS3_CMN_PROTO_STUB(void, Bs3RegCtxSaveForMode,(PBS3REGCTX pRegCtx, uint8_t bMode, uint16_t cbExtraStack)); + +/** + * Transforms a register context to a different ring. + * + * @param pRegCtx The register context. + * @param bRing The target ring (0..3). + * + * @note Do _NOT_ call this for creating real mode or v8086 contexts, because + * it will always output a protected mode context! + */ +BS3_CMN_PROTO_STUB(void, Bs3RegCtxConvertToRingX,(PBS3REGCTX pRegCtx, uint8_t bRing)); + +/** + * Transforms a V8086 register context to a real mode one. + * + * @param pRegCtx The register context. + * + * @note Will assert if called on a non-V8086 context. + */ +BS3_CMN_PROTO_STUB(void, Bs3RegCtxConvertV86ToRm,(PBS3REGCTX pRegCtx)); + +/** + * Restores a register context. + * + * @param pRegCtx The register context to be restored and resumed. + * @param fFlags BS3REGCTXRESTORE_F_XXX. + * + * @remarks Will switch to ring-0. + * @remarks Does not return. + */ +BS3_CMN_PROTO_NOSB(DECL_NO_RETURN(void), Bs3RegCtxRestore,(PCBS3REGCTX pRegCtx, uint16_t fFlags)); +#if !defined(BS3_KIT_WITH_NO_RETURN) && defined(__WATCOMC__) +# pragma aux Bs3RegCtxRestore_c16 "_Bs3RegCtxRestore_aborts_c16" __aborts +# pragma aux Bs3RegCtxRestore_f16 "_Bs3RegCtxRestore_aborts_f16" __aborts +# pragma aux Bs3RegCtxRestore_c32 "_Bs3RegCtxRestore_aborts_c32" __aborts +#endif + +/** @name Flags for Bs3RegCtxRestore + * @{ */ +/** Skip restoring the CRx registers. */ +#define BS3REGCTXRESTORE_F_SKIP_CRX UINT16_C(0x0001) +/** Sets g_fBs3TrapNoV86Assist. */ +#define BS3REGCTXRESTORE_F_NO_V86_ASSIST UINT16_C(0x0002) +/** @} */ + +/** + * Prints the register context. + * + * @param pRegCtx The register context to be printed. + */ +BS3_CMN_PROTO_STUB(void, Bs3RegCtxPrint,(PCBS3REGCTX pRegCtx)); + +/** + * Sets a GPR and segment register to point at the same location as @a uFlat. + * + * @param pRegCtx The register context. + * @param pGpr The general purpose register to set (points within + * @a pRegCtx). + * @param pSel The selector register (points within @a pRegCtx). + * @param uFlat Flat location address. + */ +BS3_CMN_PROTO_STUB(void, Bs3RegCtxSetGrpSegFromFlat,(PBS3REGCTX pRegCtx, PBS3REG pGpr, PRTSEL pSel, RTCCUINTXREG uFlat)); + +/** + * Sets a GPR and segment register to point at the same location as @a ovPtr. + * + * @param pRegCtx The register context. + * @param pGpr The general purpose register to set (points within + * @a pRegCtx). + * @param pSel The selector register (points within @a pRegCtx). + * @param pvPtr Current context pointer. + */ +BS3_CMN_PROTO_STUB(void, Bs3RegCtxSetGrpSegFromCurPtr,(PBS3REGCTX pRegCtx, PBS3REG pGpr, PRTSEL pSel, void BS3_FAR *pvPtr)); + +/** + * Sets a GPR and DS to point at the same location as @a pvPtr. + * + * @param pRegCtx The register context. + * @param pGpr The general purpose register to set (points within + * @a pRegCtx). + * @param pvPtr Current context pointer. + */ +BS3_CMN_PROTO_STUB(void, Bs3RegCtxSetGrpDsFromCurPtr,(PBS3REGCTX pRegCtx, PBS3REG pGpr, void BS3_FAR *pvPtr)); + +/** + * Sets CS:RIP to point at the same piece of code as @a uFlatCode. + * + * @param pRegCtx The register context. + * @param uFlatCode Flat code pointer + * @sa Bs3RegCtxSetRipCsFromLnkPtr, Bs3RegCtxSetRipCsFromCurPtr + */ +BS3_CMN_PROTO_STUB(void, Bs3RegCtxSetRipCsFromFlat,(PBS3REGCTX pRegCtx, RTCCUINTXREG uFlatCode)); + +/** + * Sets CS:RIP to point at the same piece of code as @a pfnCode. + * + * The 16-bit edition of this function expects a far 16:16 address as written by + * the linker (i.e. real mode). + * + * @param pRegCtx The register context. + * @param pfnCode Pointer to the code. In 32-bit and 64-bit mode this is a + * flat address, while in 16-bit it's a far 16:16 address + * as fixed up by the linker (real mode selector). This + * address is converted to match the mode of the context. + * @sa Bs3RegCtxSetRipCsFromCurPtr, Bs3RegCtxSetRipCsFromFlat + */ +BS3_CMN_PROTO_STUB(void, Bs3RegCtxSetRipCsFromLnkPtr,(PBS3REGCTX pRegCtx, FPFNBS3FAR pfnCode)); + +/** + * Sets CS:RIP to point at the same piece of code as @a pfnCode. + * + * @param pRegCtx The register context. + * @param pfnCode Pointer to the code. Current mode pointer. + * @sa Bs3RegCtxSetRipCsFromLnkPtr, Bs3RegCtxSetRipCsFromFlat + */ +BS3_CMN_PROTO_STUB(void, Bs3RegCtxSetRipCsFromCurPtr,(PBS3REGCTX pRegCtx, FPFNBS3FAR pfnCode)); + +/** + * Sets a GPR by number. + * + * @return true if @a iGpr is valid, false if not. + * @param pRegCtx The register context. + * @param iGpr The GPR number. + * @param uValue The new value. + * @param cbValue The size of the value: 1, 2, 4 or 8. + */ +BS3_CMN_PROTO_STUB(bool, Bs3RegCtxSetGpr,(PBS3REGCTX pRegCtx, uint8_t iGpr, uint64_t uValue, uint8_t cb)); + +/** + * Gets the stack pointer as a current context pointer. + * + * @return Pointer to the top of the stack. NULL on failure. + * @param pRegCtx The register context. + */ +BS3_CMN_PROTO_STUB(void BS3_FAR *, Bs3RegCtxGetRspSsAsCurPtr,(PBS3REGCTX pRegCtx)); + + +/** + * The method to be used to save and restore the extended context. + */ +typedef enum BS3EXTCTXMETHOD +{ + BS3EXTCTXMETHOD_INVALID = 0, + BS3EXTCTXMETHOD_ANCIENT, /**< Ancient fnsave/frstor format. */ + BS3EXTCTXMETHOD_FXSAVE, /**< fxsave/fxrstor format. */ + BS3EXTCTXMETHOD_XSAVE, /**< xsave/xrstor format. */ + BS3EXTCTXMETHOD_END, +} BS3EXTCTXMETHOD; + + +/** + * Extended CPU context (FPU, SSE, AVX, ++). + * + * @remarks Also in bs3kit.inc + */ +typedef struct BS3EXTCTX +{ + /** Dummy/magic value. */ + uint16_t u16Magic; + /** The size of the structure. */ + uint16_t cb; + /** The method used to save and restore the context (BS3EXTCTXMETHOD). */ + uint8_t enmMethod; + uint8_t abPadding0[3]; + /** Nominal XSAVE_C_XXX. */ + uint64_t fXcr0Nominal; + /** The saved XCR0 mask (restored after xrstor). */ + uint64_t fXcr0Saved; + + /** Explicit alignment padding. */ + uint8_t abPadding[64 - 2 - 2 - 1 - 3 - 8 - 8]; + + /** The context, variable size (see above). + * This must be aligned on a 64 byte boundrary. */ + union + { + /** fnsave/frstor. */ + X86FPUSTATE Ancient; + /** fxsave/fxrstor */ + X86FXSTATE x87; + /** xsave/xrstor */ + X86XSAVEAREA x; + /** Byte array view. */ + uint8_t ab[sizeof(X86XSAVEAREA)]; + } Ctx; +} BS3EXTCTX; +AssertCompileMemberAlignment(BS3EXTCTX, Ctx, 64); +/** Pointer to an extended CPU context. */ +typedef BS3EXTCTX BS3_FAR *PBS3EXTCTX; +/** Pointer to a const extended CPU context. */ +typedef BS3EXTCTX const BS3_FAR *PCBS3EXTCTX; + +/** Magic value for BS3EXTCTX. */ +#define BS3EXTCTX_MAGIC UINT16_C(0x1980) + +/** + * Allocates and initializes the extended CPU context structure. + * + * @returns The new extended CPU context structure. + * @param enmKind The kind of allocation to make. + */ +BS3_CMN_PROTO_STUB(PBS3EXTCTX, Bs3ExtCtxAlloc,(BS3MEMKIND enmKind)); + +/** + * Frees an extended CPU context structure. + * + * @param pExtCtx The extended CPU context (returned by + * Bs3ExtCtxAlloc). + */ +BS3_CMN_PROTO_STUB(void, Bs3ExtCtxFree,(PBS3EXTCTX pExtCtx)); + +/** + * Get the size required for a BS3EXTCTX structure. + * + * @returns size in bytes of the whole structure. + * @param pfFlags Where to return flags for Bs3ExtCtxInit. + * @note Use Bs3ExtCtxAlloc when possible. + */ +BS3_CMN_PROTO_STUB(uint16_t, Bs3ExtCtxGetSize,(uint64_t *pfFlags)); + +/** + * Initializes the extended CPU context structure. + * @returns pExtCtx + * @param pExtCtx The extended CPU context. + * @param cbExtCtx The size of the @a pExtCtx allocation. + * @param fFlags XSAVE_C_XXX flags. + */ +BS3_CMN_PROTO_STUB(PBS3EXTCTX, Bs3ExtCtxInit,(PBS3EXTCTX pExtCtx, uint16_t cbExtCtx, uint64_t fFlags)); + +/** + * Saves the extended CPU state to the given structure. + * + * @param pExtCtx The extended CPU context. + * @remarks All GPRs preserved. + */ +BS3_CMN_PROTO_FARSTUB(4, void, Bs3ExtCtxSave,(PBS3EXTCTX pExtCtx)); + +/** + * Saves the extended CPU state to the given structure, when in long mode this + * is done from 64-bit mode to capture YMM8 thru YMM15. + * + * This is for testing 64-bit code from a 32-bit test driver. + * + * @param pExtCtx The extended CPU context. + * @note Only safe to call from ring-0 at present. + * @remarks All GPRs preserved. + * @sa Bs3ExtCtxRestoreEx + */ +BS3_CMN_PROTO_FARSTUB(4, void, Bs3ExtCtxSaveEx,(PBS3EXTCTX pExtCtx)); + +/** + * Restores the extended CPU state from the given structure. + * + * @param pExtCtx The extended CPU context. + * @remarks All GPRs preserved. + */ +BS3_CMN_PROTO_FARSTUB(4, void, Bs3ExtCtxRestore,(PCBS3EXTCTX pExtCtx)); + +/** + * Restores the extended CPU state from the given structure and in long mode + * switch to 64-bit mode to do this so YMM8-YMM15 are also loaded. + * + * This is for testing 64-bit code from a 32-bit test driver. + * + * @param pExtCtx The extended CPU context. + * @note Only safe to call from ring-0 at present. + * @remarks All GPRs preserved. + * @sa Bs3ExtCtxSaveEx + */ +BS3_CMN_PROTO_FARSTUB(4, void, Bs3ExtCtxRestoreEx,(PCBS3EXTCTX pExtCtx)); + +/** + * Copies the state from one context to another. + * + * @returns pDst + * @param pDst The destination extended CPU context. + * @param pSrc The source extended CPU context. + */ +BS3_CMN_PROTO_STUB(PBS3EXTCTX, Bs3ExtCtxCopy,(PBS3EXTCTX pDst, PCBS3EXTCTX pSrc)); + +/** + * Gets the FCW register value from @a pExtCtx. + * + * @returns FCW value. + * @param pExtCtx The extended CPU context. + */ +BS3_CMN_PROTO_STUB(uint16_t, Bs3ExtCtxGetFcw,(PCBS3EXTCTX pExtCtx)); + +/** + * Sets the FCW register value in @a pExtCtx. + * + * @param pExtCtx The extended CPU context. + * @param uValue The new FCW value. + */ +BS3_CMN_PROTO_STUB(void, Bs3ExtCtxSetFcw,(PBS3EXTCTX pExtCtx, uint16_t uValue)); + +/** + * Gets the FSW register value from @a pExtCtx. + * + * @returns FSW value. + * @param pExtCtx The extended CPU context. + */ +BS3_CMN_PROTO_STUB(uint16_t, Bs3ExtCtxGetFsw,(PCBS3EXTCTX pExtCtx)); + +/** + * Sets the FSW register value in @a pExtCtx. + * + * @param pExtCtx The extended CPU context. + * @param uValue The new FSW value. + */ +BS3_CMN_PROTO_STUB(void, Bs3ExtCtxSetFsw,(PBS3EXTCTX pExtCtx, uint16_t uValue)); + +/** + * Gets the abridged FTW register value from @a pExtCtx. + * + * @returns FTW value. + * @param pExtCtx The extended CPU context. + */ +BS3_CMN_PROTO_STUB(uint16_t, Bs3ExtCtxGetAbridgedFtw,(PCBS3EXTCTX pExtCtx)); + +/** + * Sets the abridged FTW register value in @a pExtCtx. + * + * Currently this requires that the state stores teh abridged FTW, no conversion + * to the two-bit variant will be attempted. + * + * @returns true if set successfully, false if not. + * @param pExtCtx The extended CPU context. + * @param uValue The new FTW value. + */ +BS3_CMN_PROTO_STUB(bool, Bs3ExtCtxSetAbridgedFtw,(PBS3EXTCTX pExtCtx, uint16_t uValue)); + +/** + * Gets the MXCSR register value from @a pExtCtx. + * + * @returns MXCSR value, 0 if not part of context. + * @param pExtCtx The extended CPU context. + */ +BS3_CMN_PROTO_STUB(uint32_t, Bs3ExtCtxGetMxCsr,(PCBS3EXTCTX pExtCtx)); + +/** + * Sets the MXCSR register value in @a pExtCtx. + * + * @returns true if set, false if not supported by the format. + * @param pExtCtx The extended CPU context. + * @param uValue The new MXCSR value. + */ +BS3_CMN_PROTO_STUB(bool, Bs3ExtCtxSetMxCsr,(PBS3EXTCTX pExtCtx, uint32_t uValue)); + +/** + * Gets the MXCSR MASK value from @a pExtCtx. + * + * @returns MXCSR MASK value, 0 if not part of context. + * @param pExtCtx The extended CPU context. + */ +BS3_CMN_PROTO_STUB(uint32_t, Bs3ExtCtxGetMxCsrMask,(PCBS3EXTCTX pExtCtx)); + +/** + * Sets the MXCSR MASK value in @a pExtCtx. + * + * @returns true if set, false if not supported by the format. + * @param pExtCtx The extended CPU context. + * @param uValue The new MXCSR MASK value. + */ +BS3_CMN_PROTO_STUB(bool, Bs3ExtCtxSetMxCsrMask,(PBS3EXTCTX pExtCtx, uint32_t uValue)); + +/** + * Gets the value of MM register number @a iReg from @a pExtCtx. + * + * @returns The MM register value. + * @param pExtCtx The extended CPU context. + * @param iReg The register to get (0 thru 7). + */ +BS3_CMN_PROTO_STUB(uint64_t, Bs3ExtCtxGetMm,(PCBS3EXTCTX pExtCtx, uint8_t iReg)); + +/** What to do about the 16-bit above the MM QWORD. */ +typedef enum BS3EXTCTXTOPMM +{ + /** Invalid zero value. */ + BS3EXTCTXTOPMM_INVALID = 0, + /** Set to 0FFFFh like real CPUs typically does when updating an MM register. */ + BS3EXTCTXTOPMM_SET, + /** Set to zero. */ + BS3EXTCTXTOPMM_ZERO, + /** Don't change the value, leaving it as-is. */ + BS3EXTCTXTOPMM_AS_IS, + /** End of valid values. */ + BS3EXTCTXTOPMM_END +} BS3EXTCTXTOPMM; + +/** + * Sets the value of YMM register number @a iReg in @a pExtCtx to @a pValue. + * + * @returns True if set, false if not. + * @param pExtCtx The extended CPU context. + * @param iReg The register to set. + * @param uValue The new register value. + * @param enmTop What to do about the 16-bit value above the MM + * QWord. + */ +BS3_CMN_PROTO_STUB(bool, Bs3ExtCtxSetMm,(PBS3EXTCTX pExtCtx, uint8_t iReg, uint64_t uValue, BS3EXTCTXTOPMM enmTop)); + +/** + * Gets the value of XMM register number @a iReg from @a pExtCtx. + * + * @returns pValue + * @param pExtCtx The extended CPU context. + * @param iReg The register to get. + * @param pValue Where to return the value. Zeroed if the state + * doesn't support SSE or if @a iReg is invalid. + */ +BS3_CMN_PROTO_STUB(PRTUINT128U, Bs3ExtCtxGetXmm,(PCBS3EXTCTX pExtCtx, uint8_t iReg, PRTUINT128U pValue)); + +/** + * Sets the value of XMM register number @a iReg in @a pExtCtx to @a pValue. + * + * @returns True if set, false if not set (not supported by state format or + * invalid iReg). + * @param pExtCtx The extended CPU context. + * @param iReg The register to set. + * @param pValue The new register value. + */ +BS3_CMN_PROTO_STUB(bool, Bs3ExtCtxSetXmm,(PBS3EXTCTX pExtCtx, uint8_t iReg, PCRTUINT128U pValue)); + +/** + * Gets the value of YMM register number @a iReg from @a pExtCtx. + * + * @returns pValue + * @param pExtCtx The extended CPU context. + * @param iReg The register to get. + * @param pValue Where to return the value. Parts not in the + * extended state are zeroed. For absent or invalid + * @a iReg values this is set to zero. + */ +BS3_CMN_PROTO_STUB(PRTUINT256U, Bs3ExtCtxGetYmm,(PCBS3EXTCTX pExtCtx, uint8_t iReg, PRTUINT256U pValue)); + +/** + * Sets the value of YMM register number @a iReg in @a pExtCtx to @a pValue. + * + * @returns true if set (even if only partially). False if not set (not + * supported by state format, unsupported/invalid iReg). + * @param pExtCtx The extended CPU context. + * @param iReg The register to set. + * @param pValue The new register value. + * @param cbValue Number of bytes to take from @a pValue, either 16 or + * 32. If 16, the high part will be zeroed when present + * in the state. + */ +BS3_CMN_PROTO_STUB(bool, Bs3ExtCtxSetYmm,(PBS3EXTCTX pExtCtx, uint8_t iReg, PCRTUINT256U pValue, uint8_t cbValue)); + + +/** @name Debug register accessors for V8086 mode (works everwhere). + * @{ */ +BS3_CMN_PROTO_NOSB(RTCCUINTXREG, Bs3RegGetDr0,(void)); +BS3_CMN_PROTO_NOSB(RTCCUINTXREG, Bs3RegGetDr1,(void)); +BS3_CMN_PROTO_NOSB(RTCCUINTXREG, Bs3RegGetDr2,(void)); +BS3_CMN_PROTO_NOSB(RTCCUINTXREG, Bs3RegGetDr3,(void)); +BS3_CMN_PROTO_NOSB(RTCCUINTXREG, Bs3RegGetDr6,(void)); +BS3_CMN_PROTO_NOSB(RTCCUINTXREG, Bs3RegGetDr7,(void)); + +BS3_CMN_PROTO_NOSB(void, Bs3RegSetDr0,(RTCCUINTXREG uValue)); +BS3_CMN_PROTO_NOSB(void, Bs3RegSetDr1,(RTCCUINTXREG uValue)); +BS3_CMN_PROTO_NOSB(void, Bs3RegSetDr2,(RTCCUINTXREG uValue)); +BS3_CMN_PROTO_NOSB(void, Bs3RegSetDr3,(RTCCUINTXREG uValue)); +BS3_CMN_PROTO_NOSB(void, Bs3RegSetDr6,(RTCCUINTXREG uValue)); +BS3_CMN_PROTO_NOSB(void, Bs3RegSetDr7,(RTCCUINTXREG uValue)); + +BS3_CMN_PROTO_NOSB(RTCCUINTXREG, Bs3RegGetDrX,(uint8_t iReg)); +BS3_CMN_PROTO_NOSB(void, Bs3RegSetDrX,(uint8_t iReg, RTCCUINTXREG uValue)); +/** @} */ + + +/** @name Control register accessors for V8086 mode (works everwhere). + * @{ */ +BS3_CMN_PROTO_NOSB(RTCCUINTXREG, Bs3RegGetCr0,(void)); +BS3_CMN_PROTO_NOSB(RTCCUINTXREG, Bs3RegGetCr2,(void)); +BS3_CMN_PROTO_NOSB(RTCCUINTXREG, Bs3RegGetCr3,(void)); +BS3_CMN_PROTO_NOSB(RTCCUINTXREG, Bs3RegGetCr4,(void)); +BS3_CMN_PROTO_NOSB(uint16_t, Bs3RegGetTr,(void)); +BS3_CMN_PROTO_NOSB(uint16_t, Bs3RegGetLdtr,(void)); +BS3_CMN_PROTO_NOSB(uint64_t, Bs3RegGetXcr0,(void)); + +BS3_CMN_PROTO_NOSB(void, Bs3RegSetCr0,(RTCCUINTXREG uValue)); +BS3_CMN_PROTO_NOSB(void, Bs3RegSetCr2,(RTCCUINTXREG uValue)); +BS3_CMN_PROTO_NOSB(void, Bs3RegSetCr3,(RTCCUINTXREG uValue)); +BS3_CMN_PROTO_NOSB(void, Bs3RegSetCr4,(RTCCUINTXREG uValue)); +BS3_CMN_PROTO_NOSB(void, Bs3RegSetTr,(uint16_t uValue)); +BS3_CMN_PROTO_NOSB(void, Bs3RegSetLdtr,(uint16_t uValue)); +BS3_CMN_PROTO_NOSB(void, Bs3RegSetXcr0,(uint64_t uValue)); +/** @} */ + + +/** + * Trap frame. + */ +typedef struct BS3TRAPFRAME +{ + /** 0x00: Exception/interrupt number. */ + uint8_t bXcpt; + /** 0x01: The size of the IRET frame. */ + uint8_t cbIretFrame; + /** 0x02: The handler CS. */ + uint16_t uHandlerCs; + /** 0x04: The handler SS. */ + uint16_t uHandlerSs; + /** 0x06: Explicit alignment. */ + uint16_t usAlignment; + /** 0x08: The handler RSP (pointer to the iret frame, skipping ErrCd). */ + uint64_t uHandlerRsp; + /** 0x10: The handler RFLAGS value. */ + uint64_t fHandlerRfl; + /** 0x18: The error code (if applicable). */ + uint64_t uErrCd; + /** 0x20: The register context. */ + BS3REGCTX Ctx; +} BS3TRAPFRAME; +AssertCompileSize(BS3TRAPFRAME, 0x20 + 0xd0); +/** Pointer to a trap frame. */ +typedef BS3TRAPFRAME BS3_FAR *PBS3TRAPFRAME; +/** Pointer to a const trap frame. */ +typedef BS3TRAPFRAME const BS3_FAR *PCBS3TRAPFRAME; + + +/** + * Re-initializes the trap handling for the current mode. + * + * Useful after a test that messes with the IDT/IVT. + * + * @sa Bs3TrapInit + */ +BS3_CMN_PROTO_STUB(void, Bs3TrapReInit,(void)); + +/** + * Initializes real mode and v8086 trap handling. + * + * @remarks Does not install RM/V86 trap handling, just initializes the + * structures. + */ +BS3_CMN_PROTO_STUB(void, Bs3TrapRmV86Init,(void)); + +/** + * Initializes real mode and v8086 trap handling, extended version. + * + * @param f386Plus Set if the CPU is 80386 or later and + * extended registers should be saved. Once initialized + * with this parameter set to @a true, the effect cannot be + * reversed. + * + * @remarks Does not install RM/V86 trap handling, just initializes the + * structures. + */ +BS3_CMN_PROTO_STUB(void, Bs3TrapRmV86InitEx,(bool f386Plus)); + +/** + * Initializes 16-bit (protected mode) trap handling. + * + * @remarks Does not install 16-bit trap handling, just initializes the + * structures. + */ +BS3_CMN_PROTO_STUB(void, Bs3Trap16Init,(void)); + +/** + * Initializes 16-bit (protected mode) trap handling, extended version. + * + * @param f386Plus Set if the CPU is 80386 or later and + * extended registers should be saved. Once initialized + * with this parameter set to @a true, the effect cannot be + * reversed. + * + * @remarks Does not install 16-bit trap handling, just initializes the + * structures. + */ +BS3_CMN_PROTO_STUB(void, Bs3Trap16InitEx,(bool f386Plus)); + +/** + * Initializes 32-bit trap handling. + * + * @remarks Does not install 32-bit trap handling, just initializes the + * structures. + */ +BS3_CMN_PROTO_STUB(void, Bs3Trap32Init,(void)); + +/** + * Initializes 64-bit trap handling + * + * @remarks Does not install 64-bit trap handling, just initializes the + * structures. + */ +BS3_CMN_PROTO_STUB(void, Bs3Trap64Init,(void)); + +/** + * Initializes 64-bit trap handling, extended version. + * + * @remarks Does not install 64-bit trap handling, just initializes the + * structures. + * @param fMoreIstUsage Use the interrupt stacks for more CPU exceptions. + * Default (false) is to only IST1 for the double fault + * handler and the rest uses IST0. + */ +BS3_CMN_PROTO_STUB(void, Bs3Trap64InitEx,(bool fMoreIstUsage)); + +/** + * Modifies the real-mode / V86 IVT entry specified by @a iIvt. + * + * @param iIvt The index of the IDT entry to set. + * @param uSeg The handler real-mode segment. + * @param off The handler offset. + */ +BS3_CMN_PROTO_STUB(void, Bs3TrapRmV86SetGate,(uint8_t iIvt, uint16_t uSeg, uint16_t off)); + +/** + * Modifies the 16-bit IDT entry (protected mode) specified by @a iIdt. + * + * @param iIdt The index of the IDT entry to set. + * @param bType The gate type (X86_SEL_TYPE_SYS_XXX). + * @param bDpl The DPL. + * @param uSel The handler selector. + * @param off The handler offset (if applicable). + * @param cParams The parameter count (for call gates). + */ +BS3_CMN_PROTO_STUB(void, Bs3Trap16SetGate,(uint8_t iIdt, uint8_t bType, uint8_t bDpl, + uint16_t uSel, uint16_t off, uint8_t cParams)); + +/** The address of Bs3Trap16GenericEntries. + * Bs3Trap16GenericEntries is an array of interrupt/trap/whatever entry + * points, 8 bytes each, that will create a register frame and call the generic + * C compatible trap handlers. */ +extern uint32_t g_Bs3Trap16GenericEntriesFlatAddr; + +/** + * Modifies the 32-bit IDT entry specified by @a iIdt. + * + * @param iIdt The index of the IDT entry to set. + * @param bType The gate type (X86_SEL_TYPE_SYS_XXX). + * @param bDpl The DPL. + * @param uSel The handler selector. + * @param off The handler offset (if applicable). + * @param cParams The parameter count (for call gates). + */ +BS3_CMN_PROTO_STUB(void, Bs3Trap32SetGate,(uint8_t iIdt, uint8_t bType, uint8_t bDpl, + uint16_t uSel, uint32_t off, uint8_t cParams)); + +/** The address of Bs3Trap32GenericEntries. + * Bs3Trap32GenericEntries is an array of interrupt/trap/whatever entry + * points, 10 bytes each, that will create a register frame and call the generic + * C compatible trap handlers. */ +extern uint32_t g_Bs3Trap32GenericEntriesFlatAddr; + +/** + * Modifies the 64-bit IDT entry specified by @a iIdt. + * + * @param iIdt The index of the IDT entry to set. + * @param bType The gate type (X86_SEL_TYPE_SYS_XXX). + * @param bDpl The DPL. + * @param uSel The handler selector. + * @param off The handler offset (if applicable). + * @param bIst The interrupt stack to use. + */ +BS3_CMN_PROTO_STUB(void, Bs3Trap64SetGate,(uint8_t iIdt, uint8_t bType, uint8_t bDpl, uint16_t uSel, uint64_t off, uint8_t bIst)); + +/** The address of Bs3Trap64GenericEntries. + * Bs3Trap64GenericEntries is an array of interrupt/trap/whatever entry + * points, 8 bytes each, that will create a register frame and call the generic + * C compatible trap handlers. */ +extern uint32_t g_Bs3Trap64GenericEntriesFlatAddr; + +/** + * Adjusts the DPL the IDT entry specified by @a iIdt. + * + * The change is applied to the 16-bit, 32-bit and 64-bit IDTs. + * + * @returns Old DPL (from 64-bit IDT). + * @param iIdt The index of the IDT and IVT entry to set. + * @param bDpl The DPL. + */ +BS3_CMN_PROTO_STUB(uint8_t, Bs3TrapSetDpl,(uint8_t iIdt, uint8_t bDpl)); + +/** + * C-style trap handler. + * + * The caller will resume the context in @a pTrapFrame upon return. + * + * @param pTrapFrame The trap frame. Registers can be modified. + * @note The 16-bit versions must be in CGROUP16! + */ +typedef BS3_DECL_NEAR_CALLBACK(void) FNBS3TRAPHANDLER(PBS3TRAPFRAME pTrapFrame); +/** Pointer to a trap handler (current template context). */ +typedef FNBS3TRAPHANDLER *PFNBS3TRAPHANDLER; + +#if ARCH_BITS == 16 +/** @copydoc FNBS3TRAPHANDLER */ +typedef FNBS3FAR FNBS3TRAPHANDLER32; +/** @copydoc FNBS3TRAPHANDLER */ +typedef FNBS3FAR FNBS3TRAPHANDLER64; +#else +/** @copydoc FNBS3TRAPHANDLER */ +typedef FNBS3TRAPHANDLER FNBS3TRAPHANDLER32; +/** @copydoc FNBS3TRAPHANDLER */ +typedef FNBS3TRAPHANDLER FNBS3TRAPHANDLER64; +#endif +/** @copydoc PFNBS3TRAPHANDLER */ +typedef FNBS3TRAPHANDLER32 *PFNBS3TRAPHANDLER32; +/** @copydoc PFNBS3TRAPHANDLER */ +typedef FNBS3TRAPHANDLER64 *PFNBS3TRAPHANDLER64; + + +/** + * C-style trap handler, near 16-bit (CGROUP16). + * + * The caller will resume the context in @a pTrapFrame upon return. + * + * @param pTrapFrame The trap frame. Registers can be modified. + */ +typedef BS3_DECL_NEAR_CALLBACK(void) FNBS3TRAPHANDLER16(PBS3TRAPFRAME pTrapFrame); +/** Pointer to a trap handler (current template context). */ +typedef FNBS3TRAPHANDLER16 *PFNBS3TRAPHANDLER16; + +/** + * C-style trap handler, near 16-bit (CGROUP16). + * + * The caller will resume the context in @a pTrapFrame upon return. + * + * @param pTrapFrame The trap frame. Registers can be modified. + */ +typedef BS3_DECL_CALLBACK(void) FNBS3TRAPHANDLER3264(PBS3TRAPFRAME pTrapFrame); +/** Pointer to a trap handler (current template context). */ +typedef FNBS3TRAPHANDLER3264 *FPFNBS3TRAPHANDLER3264; + + +/** + * Sets a trap handler (C/C++/assembly) for the current bitcount. + * + * @returns Previous handler. + * @param iIdt The index of the IDT entry to set. + * @param pfnHandler Pointer to the handler. + * @sa Bs3TrapSetHandlerEx + */ +BS3_CMN_PROTO_STUB(PFNBS3TRAPHANDLER, Bs3TrapSetHandler,(uint8_t iIdt, PFNBS3TRAPHANDLER pfnHandler)); + +/** + * Sets a trap handler (C/C++/assembly) for all the bitcounts. + * + * @param iIdt The index of the IDT and IVT entry to set. + * @param pfnHandler16 Pointer to the 16-bit handler. (Assumes linker addresses.) + * @param pfnHandler32 Pointer to the 32-bit handler. (Assumes linker addresses.) + * @param pfnHandler64 Pointer to the 64-bit handler. (Assumes linker addresses.) + * @sa Bs3TrapSetHandler + */ +BS3_CMN_PROTO_STUB(void, Bs3TrapSetHandlerEx,(uint8_t iIdt, PFNBS3TRAPHANDLER16 pfnHandler16, + PFNBS3TRAPHANDLER32 pfnHandler32, PFNBS3TRAPHANDLER64 pfnHandler64)); + +/** + * Default C/C++ trap handler. + * + * This will check trap record and panic if no match was found. + * + * @param pTrapFrame Trap frame of the trap to handle. + */ +BS3_CMN_PROTO_STUB(void, Bs3TrapDefaultHandler,(PBS3TRAPFRAME pTrapFrame)); + +/** + * Prints the trap frame (to screen). + * @param pTrapFrame Trap frame to print. + */ +BS3_CMN_PROTO_STUB(void, Bs3TrapPrintFrame,(PCBS3TRAPFRAME pTrapFrame)); + +/** + * Sets up a long jump from a trap handler. + * + * The long jump will only be performed once, but will catch any kind of trap, + * fault, interrupt or irq. + * + * @retval true on the initial call. + * @retval false on trap return. + * @param pTrapFrame Where to store the trap information when + * returning @c false. + * @sa #Bs3TrapUnsetJmp + */ +BS3_CMN_PROTO_NOSB(DECL_RETURNS_TWICE(bool),Bs3TrapSetJmp,(PBS3TRAPFRAME pTrapFrame)); + +/** + * Combination of #Bs3TrapSetJmp and #Bs3RegCtxRestore. + * + * @param pCtxRestore The context to restore. + * @param pTrapFrame Where to store the trap information. + */ +BS3_CMN_PROTO_STUB(void, Bs3TrapSetJmpAndRestore,(PCBS3REGCTX pCtxRestore, PBS3TRAPFRAME pTrapFrame)); + +/** + * Variation of Bs3TrapSetJmpAndRestore that includes + * #Bs3TrapSetJmpAndRestoreInRm and calls is if pCtxRestore is a real mode + * context and we're not in real mode. + * + * This is useful for 32-bit test drivers running via #Bs3TestDoModesByOne using + * BS3TESTMODEBYONEENTRY_F_REAL_MODE_READY to allow them to test real-mode too. + * + * @param pCtxRestore The context to restore. + * @param pTrapFrame Where to store the trap information. + */ +BS3_CMN_PROTO_STUB(void, Bs3TrapSetJmpAndRestoreWithRm,(PCBS3REGCTX pCtxRestore, PBS3TRAPFRAME pTrapFrame)); + +/** + * Combination of #Bs3ExtCtxRestoreEx, #Bs3TrapSetJmp, #Bs3RegCtxRestore and + * #Bs3ExtCtxSaveEx. + * + * @param pCtxRestore The context to restore. + * @param pExtCtxRestore The extended context to restore. + * @param pTrapFrame Where to store the trap information. + * @param pExtCtxTrap Where to store the extended context after the trap. + * Note, the saving isn't done from the trap handler, + * but after #Bs3TrapSetJmp returns zero (i.e. for the + * 2nd time). + */ +BS3_CMN_PROTO_STUB(void, Bs3TrapSetJmpAndRestoreWithExtCtx,(PCBS3REGCTX pCtxRestore, PCBS3EXTCTX pExtCtxRestore, + PBS3TRAPFRAME pTrapFrame, PBS3EXTCTX pExtCtxTrap)); + +/** + * Variation of Bs3TrapSetJmpAndRestoreWithExtCtx that includes + * #Bs3TrapSetJmpAndRestoreInRm and calls is if pCtxRestore is a real mode + * context and we're not in real mode. + * + * This is useful for 32-bit test drivers running via #Bs3TestDoModesByOne using + * BS3TESTMODEBYONEENTRY_F_REAL_MODE_READY to allow them to test real-mode too. + * + * @param pCtxRestore The context to restore. + * @param pExtCtxRestore The extended context to restore. + * @param pTrapFrame Where to store the trap information. + * @param pExtCtxTrap Where to store the extended context after the trap. + * Note, the saving isn't done from the trap handler, + * but after #Bs3TrapSetJmp returns zero (i.e. for the + * 2nd time). + */ +BS3_CMN_PROTO_STUB(void, Bs3TrapSetJmpAndRestoreWithExtCtxAndRm,(PCBS3REGCTX pCtxRestore, PCBS3EXTCTX pExtCtxRestore, + PBS3TRAPFRAME pTrapFrame, PBS3EXTCTX pExtCtxTrap)); + +/** + * Combination of Bs3SwitchToRM, #Bs3TrapSetJmp and #Bs3RegCtxRestore. + * + * @param pCtxRestore The context to restore. Must be real-mode + * addressable. + * @param pTrapFrame Where to store the trap information. Must be + * real-mode addressable. + */ +BS3_CMN_PROTO_STUB(void, Bs3TrapSetJmpAndRestoreInRm,(PCBS3REGCTX pCtxRestore, PBS3TRAPFRAME pTrapFrame)); + +/** + * Disables a previous #Bs3TrapSetJmp call. + */ +BS3_CMN_PROTO_STUB(void, Bs3TrapUnsetJmp,(void)); + + +/** + * The current test step. + */ +extern uint16_t g_usBs3TestStep; + +/** + * Equivalent to RTTestCreate + RTTestBanner. + * + * @param pszTest The test name. + */ +BS3_CMN_PROTO_STUB(void, Bs3TestInit,(const char BS3_FAR *pszTest)); + + +/** + * Equivalent to RTTestSummaryAndDestroy. + */ +BS3_CMN_PROTO_STUB(void, Bs3TestTerm,(void)); + +/** + * Equivalent to RTTestISub. + */ +BS3_CMN_PROTO_STUB(void, Bs3TestSub,(const char BS3_FAR *pszSubTest)); + +/** + * Equivalent to RTTestIFailedF. + */ +BS3_CMN_PROTO_STUB(void, Bs3TestSubF,(const char BS3_FAR *pszFormat, ...)); + +/** + * Equivalent to RTTestISubV. + */ +BS3_CMN_PROTO_STUB(void, Bs3TestSubV,(const char BS3_FAR *pszFormat, va_list BS3_FAR va)); + +/** + * Equivalent to RTTestISubDone. + */ +BS3_CMN_PROTO_STUB(void, Bs3TestSubDone,(void)); + +/** + * Equivalent to RTTestIValue. + */ +BS3_CMN_PROTO_STUB(void, Bs3TestValue,(const char BS3_FAR *pszName, uint64_t u64Value, uint8_t bUnit)); + +/** + * Equivalent to RTTestSubErrorCount. + */ +BS3_CMN_PROTO_STUB(uint16_t, Bs3TestSubErrorCount,(void)); + +/** + * Get nanosecond host timestamp. + * + * This only works when testing is enabled and will not work in VMs configured + * with a 286, 186 or 8086/8088 CPU profile. + */ +BS3_CMN_PROTO_STUB(uint64_t, Bs3TestNow,(void)); + + +/** + * Queries an unsigned 8-bit configuration value. + * + * @returns Value. + * @param uCfg A VMMDEV_TESTING_CFG_XXX value. + */ +BS3_CMN_PROTO_STUB(uint8_t, Bs3TestQueryCfgU8,(uint16_t uCfg)); + +/** + * Queries an unsigned 8-bit configuration value. + * + * @returns Value. + * @param uCfg A VMMDEV_TESTING_CFG_XXX value. + */ +BS3_CMN_PROTO_STUB(bool, Bs3TestQueryCfgBool,(uint16_t uCfg)); + +/** + * Queries an unsigned 32-bit configuration value. + * + * @returns Value. + * @param uCfg A VMMDEV_TESTING_CFG_XXX value. + */ +BS3_CMN_PROTO_STUB(uint32_t, Bs3TestQueryCfgU32,(uint16_t uCfg)); + +/** + * Equivalent to RTTestIPrintf with RTTESTLVL_ALWAYS. + * + * @param pszFormat What to print, format string. Explicit newline char. + * @param ... String format arguments. + */ +BS3_CMN_PROTO_STUB(void, Bs3TestPrintf,(const char BS3_FAR *pszFormat, ...)); + +/** + * Equivalent to RTTestIPrintfV with RTTESTLVL_ALWAYS. + * + * @param pszFormat What to print, format string. Explicit newline char. + * @param va String format arguments. + */ +BS3_CMN_PROTO_STUB(void, Bs3TestPrintfV,(const char BS3_FAR *pszFormat, va_list BS3_FAR va)); + +/** + * Same as Bs3TestPrintf, except no guest screen echo. + * + * @param pszFormat What to print, format string. Explicit newline char. + * @param ... String format arguments. + */ +BS3_CMN_PROTO_STUB(void, Bs3TestHostPrintf,(const char BS3_FAR *pszFormat, ...)); + +/** + * Same as Bs3TestPrintfV, except no guest screen echo. + * + * @param pszFormat What to print, format string. Explicit newline char. + * @param va String format arguments. + */ +BS3_CMN_PROTO_STUB(void, Bs3TestHostPrintfV,(const char BS3_FAR *pszFormat, va_list BS3_FAR va)); + +/** + * Equivalent to RTTestIFailed. + * @returns false. + */ +BS3_CMN_PROTO_STUB(bool, Bs3TestFailed,(const char BS3_FAR *pszMessage)); + +/** + * Equivalent to RTTestIFailedF. + * @returns false. + */ +BS3_CMN_PROTO_STUB(bool, Bs3TestFailedF,(const char BS3_FAR *pszFormat, ...)); + +/** + * Equivalent to RTTestIFailedV. + * @returns false. + */ +BS3_CMN_PROTO_STUB(bool, Bs3TestFailedV,(const char BS3_FAR *pszFormat, va_list BS3_FAR va)); + +/** + * Equivalent to RTTestISkipped. + * + * @param pszWhy Optional reason why it's being skipped. + */ +BS3_CMN_PROTO_STUB(void, Bs3TestSkipped,(const char BS3_FAR *pszWhy)); + +/** + * Equivalent to RTTestISkippedF. + * + * @param pszFormat Optional reason why it's being skipped. + * @param ... Format arguments. + */ +BS3_CMN_PROTO_STUB(void, Bs3TestSkippedF,(const char BS3_FAR *pszFormat, ...)); + +/** + * Equivalent to RTTestISkippedV. + * + * @param pszFormat Optional reason why it's being skipped. + * @param va Format arguments. + */ +BS3_CMN_PROTO_STUB(void, Bs3TestSkippedV,(const char BS3_FAR *pszFormat, va_list BS3_FAR va)); + +/** + * Compares two register contexts, with PC and SP adjustments. + * + * Differences will be reported as test failures. + * + * @returns true if equal, false if not. + * @param pActualCtx The actual register context. + * @param pExpectedCtx Expected register context. + * @param cbPcAdjust Program counter adjustment (applied to @a pExpectedCtx). + * @param cbSpAdjust Stack pointer adjustment (applied to @a pExpectedCtx). + * @param fExtraEfl Extra EFLAGS to OR into @a pExepctedCtx. + * @param pszMode CPU mode or some other helpful text. + * @param idTestStep Test step identifier. + */ +BS3_CMN_PROTO_STUB(bool, Bs3TestCheckRegCtxEx,(PCBS3REGCTX pActualCtx, PCBS3REGCTX pExpectedCtx, uint16_t cbPcAdjust, + int16_t cbSpAdjust, uint32_t fExtraEfl, + const char BS3_FAR *pszMode, uint16_t idTestStep)); + +/** + * Compares two extended register contexts. + * + * Differences will be reported as test failures. + * + * @returns true if equal, false if not. + * @param pActualExtCtx The actual register context. + * @param pExpectedExtCtx Expected register context. + * @param fFlags Reserved, pass 0. + * @param pszMode CPU mode or some other helpful text. + * @param idTestStep Test step identifier. + */ +BS3_CMN_PROTO_STUB(bool, Bs3TestCheckExtCtx,(PCBS3EXTCTX pActualExtCtx, PCBS3EXTCTX pExpectedExtCtx, uint16_t fFlags, + const char BS3_FAR *pszMode, uint16_t idTestStep)); + +/** + * Performs the testing for the given mode. + * + * This is called with the CPU already switch to that mode. + * + * @returns 0 on success or directly Bs3TestFailed calls, non-zero to indicate + * where the test when wrong. Special value BS3TESTDOMODE_SKIPPED + * should be returned to indicate that the test has been skipped. + * @param bMode The current CPU mode. + */ +typedef BS3_DECL_CALLBACK(uint8_t) FNBS3TESTDOMODE(uint8_t bMode); +/** Pointer (far) to a test (for 32-bit and 64-bit code, will be flatten). */ +typedef FNBS3TESTDOMODE *PFNBS3TESTDOMODE; + +/** Special FNBS3TESTDOMODE return code for indicating a skipped mode test. */ +#define BS3TESTDOMODE_SKIPPED UINT8_MAX + +/** + * Mode sub-test entry. + * + * This can only be passed around to functions with the same bit count, as it + * contains function pointers. In 16-bit mode, the 16-bit pointers are near and + * implies BS3TEXT16, whereas the 32-bit and 64-bit pointers are far real mode + * addresses that will be converted to flat address prior to calling them. + * Similarly, in 32-bit and 64-bit the addresses are all flat and the 16-bit + * ones will be converted to BS3TEXT16 based addresses prior to calling. + */ +typedef struct BS3TESTMODEENTRY +{ + /** The sub-test name to be passed to Bs3TestSub if not NULL. */ + const char * BS3_FAR pszSubTest; + + PFNBS3TESTDOMODE pfnDoRM; + + PFNBS3TESTDOMODE pfnDoPE16; + PFNBS3TESTDOMODE pfnDoPE16_32; + PFNBS3TESTDOMODE pfnDoPE16_V86; + PFNBS3TESTDOMODE pfnDoPE32; + PFNBS3TESTDOMODE pfnDoPE32_16; + PFNBS3TESTDOMODE pfnDoPEV86; + + PFNBS3TESTDOMODE pfnDoPP16; + PFNBS3TESTDOMODE pfnDoPP16_32; + PFNBS3TESTDOMODE pfnDoPP16_V86; + PFNBS3TESTDOMODE pfnDoPP32; + PFNBS3TESTDOMODE pfnDoPP32_16; + PFNBS3TESTDOMODE pfnDoPPV86; + + PFNBS3TESTDOMODE pfnDoPAE16; + PFNBS3TESTDOMODE pfnDoPAE16_32; + PFNBS3TESTDOMODE pfnDoPAE16_V86; + PFNBS3TESTDOMODE pfnDoPAE32; + PFNBS3TESTDOMODE pfnDoPAE32_16; + PFNBS3TESTDOMODE pfnDoPAEV86; + + PFNBS3TESTDOMODE pfnDoLM16; + PFNBS3TESTDOMODE pfnDoLM32; + PFNBS3TESTDOMODE pfnDoLM64; + +} BS3TESTMODEENTRY; +/** Pointer to a mode sub-test entry. */ +typedef BS3TESTMODEENTRY const *PCBS3TESTMODEENTRY; + +/** @def BS3TESTMODEENTRY_CMN + * Produces a BS3TESTMODEENTRY initializer for common (c16,c32,c64) test + * functions. */ +#define BS3TESTMODEENTRY_CMN(a_szTest, a_BaseNm) \ + { /*pszSubTest =*/ a_szTest, \ + /*RM*/ RT_CONCAT(a_BaseNm, _c16), \ + /*PE16*/ RT_CONCAT(a_BaseNm, _c16), \ + /*PE16_32*/ RT_CONCAT(a_BaseNm, _c32), \ + /*PE16_V86*/ RT_CONCAT(a_BaseNm, _c16), \ + /*PE32*/ RT_CONCAT(a_BaseNm, _c32), \ + /*PE32_16*/ RT_CONCAT(a_BaseNm, _c16), \ + /*PEV86*/ RT_CONCAT(a_BaseNm, _c16), \ + /*PP16*/ RT_CONCAT(a_BaseNm, _c16), \ + /*PP16_32*/ RT_CONCAT(a_BaseNm, _c32), \ + /*PP16_V86*/ RT_CONCAT(a_BaseNm, _c16), \ + /*PP32*/ RT_CONCAT(a_BaseNm, _c32), \ + /*PP32_16*/ RT_CONCAT(a_BaseNm, _c16), \ + /*PPV86*/ RT_CONCAT(a_BaseNm, _c16), \ + /*PAE16*/ RT_CONCAT(a_BaseNm, _c16), \ + /*PAE16_32*/ RT_CONCAT(a_BaseNm, _c32), \ + /*PAE16_V86*/ RT_CONCAT(a_BaseNm, _c16), \ + /*PAE32*/ RT_CONCAT(a_BaseNm, _c32), \ + /*PAE32_16*/ RT_CONCAT(a_BaseNm, _c16), \ + /*PAEV86*/ RT_CONCAT(a_BaseNm, _c16), \ + /*LM16*/ RT_CONCAT(a_BaseNm, _c16), \ + /*LM32*/ RT_CONCAT(a_BaseNm, _c32), \ + /*LM64*/ RT_CONCAT(a_BaseNm, _c64), \ + } + +/** @def BS3TESTMODE_PROTOTYPES_CMN + * A set of standard protypes to go with #BS3TESTMODEENTRY_CMN. */ +#define BS3TESTMODE_PROTOTYPES_CMN(a_BaseNm) \ + FNBS3TESTDOMODE /*BS3_FAR_CODE*/ RT_CONCAT(a_BaseNm, _c16); \ + FNBS3TESTDOMODE /*BS3_FAR_CODE*/ RT_CONCAT(a_BaseNm, _c32); \ + FNBS3TESTDOMODE /*BS3_FAR_CODE*/ RT_CONCAT(a_BaseNm, _c64) + +/** @def BS3TESTMODEENTRY_CMN_64 + * Produces a BS3TESTMODEENTRY initializer for common 64-bit test functions. */ +#define BS3TESTMODEENTRY_CMN_64(a_szTest, a_BaseNm) \ + { /*pszSubTest =*/ a_szTest, \ + /*RM*/ NULL, \ + /*PE16*/ NULL, \ + /*PE16_32*/ NULL, \ + /*PE16_V86*/ NULL, \ + /*PE32*/ NULL, \ + /*PE32_16*/ NULL, \ + /*PEV86*/ NULL, \ + /*PP16*/ NULL, \ + /*PP16_32*/ NULL, \ + /*PP16_V86*/ NULL, \ + /*PP32*/ NULL, \ + /*PP32_16*/ NULL, \ + /*PPV86*/ NULL, \ + /*PAE16*/ NULL, \ + /*PAE16_32*/ NULL, \ + /*PAE16_V86*/ NULL, \ + /*PAE32*/ NULL, \ + /*PAE32_16*/ NULL, \ + /*PAEV86*/ NULL, \ + /*LM16*/ NULL, \ + /*LM32*/ NULL, \ + /*LM64*/ RT_CONCAT(a_BaseNm, _c64), \ + } + +/** @def BS3TESTMODE_PROTOTYPES_CMN + * Standard protype to go with #BS3TESTMODEENTRY_CMN_64. */ +#define BS3TESTMODE_PROTOTYPES_CMN_64(a_BaseNm) \ + FNBS3TESTDOMODE /*BS3_FAR_CODE*/ RT_CONCAT(a_BaseNm, _c64) + +/** @def BS3TESTMODEENTRY_MODE + * Produces a BS3TESTMODEENTRY initializer for a full set of mode test + * functions. */ +#define BS3TESTMODEENTRY_MODE(a_szTest, a_BaseNm) \ + { /*pszSubTest =*/ a_szTest, \ + /*RM*/ RT_CONCAT(a_BaseNm, _rm), \ + /*PE16*/ RT_CONCAT(a_BaseNm, _pe16), \ + /*PE16_32*/ RT_CONCAT(a_BaseNm, _pe16_32), \ + /*PE16_V86*/ RT_CONCAT(a_BaseNm, _pe16_v86), \ + /*PE32*/ RT_CONCAT(a_BaseNm, _pe32), \ + /*PE32_16*/ RT_CONCAT(a_BaseNm, _pe32_16), \ + /*PEV86*/ RT_CONCAT(a_BaseNm, _pev86), \ + /*PP16*/ RT_CONCAT(a_BaseNm, _pp16), \ + /*PP16_32*/ RT_CONCAT(a_BaseNm, _pp16_32), \ + /*PP16_V86*/ RT_CONCAT(a_BaseNm, _pp16_v86), \ + /*PP32*/ RT_CONCAT(a_BaseNm, _pp32), \ + /*PP32_16*/ RT_CONCAT(a_BaseNm, _pp32_16), \ + /*PPV86*/ RT_CONCAT(a_BaseNm, _ppv86), \ + /*PAE16*/ RT_CONCAT(a_BaseNm, _pae16), \ + /*PAE16_32*/ RT_CONCAT(a_BaseNm, _pae16_32), \ + /*PAE16_V86*/ RT_CONCAT(a_BaseNm, _pae16_v86), \ + /*PAE32*/ RT_CONCAT(a_BaseNm, _pae32), \ + /*PAE32_16*/ RT_CONCAT(a_BaseNm, _pae32_16), \ + /*PAEV86*/ RT_CONCAT(a_BaseNm, _paev86), \ + /*LM16*/ RT_CONCAT(a_BaseNm, _lm16), \ + /*LM32*/ RT_CONCAT(a_BaseNm, _lm32), \ + /*LM64*/ RT_CONCAT(a_BaseNm, _lm64), \ + } + +/** @def BS3TESTMODE_PROTOTYPES_MODE + * A set of standard protypes to go with #BS3TESTMODEENTRY_MODE. */ +#define BS3TESTMODE_PROTOTYPES_MODE(a_BaseNm) \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _rm); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pe16); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pe16_32); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pe16_v86); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pe32); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pe32_16); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pev86); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pp16); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pp16_32); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pp16_v86); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pp32); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pp32_16); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _ppv86); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pae16); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pae16_32); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pae16_v86); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pae32); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pae32_16); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _paev86); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _lm16); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _lm32); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _lm64) + + +/** + * Mode sub-test entry, max bit-count driven + * + * This is an alternative to BS3TESTMODEENTRY where a few workers (test drivers) + * does all the work, using faster 32-bit and 64-bit code where possible. This + * avoids executing workers in V8086 mode. It allows for modifying and checking + * 64-bit register content when testing LM16 and LM32. + * + * The 16-bit workers are only used for real mode and 16-bit protected mode. + * So, the 16-bit version of the code template can be stripped of anything + * related to paging and/or v8086, saving code space. + */ +typedef struct BS3TESTMODEBYMAXENTRY +{ + /** The sub-test name to be passed to Bs3TestSub if not NULL. */ + const char * BS3_FAR pszSubTest; + + PFNBS3TESTDOMODE pfnDoRM; + PFNBS3TESTDOMODE pfnDoPE16; + PFNBS3TESTDOMODE pfnDoPE16_32; + PFNBS3TESTDOMODE pfnDoPE32; + PFNBS3TESTDOMODE pfnDoPP16_32; + PFNBS3TESTDOMODE pfnDoPP32; + PFNBS3TESTDOMODE pfnDoPAE16_32; + PFNBS3TESTDOMODE pfnDoPAE32; + PFNBS3TESTDOMODE pfnDoLM64; + + bool fDoRM : 1; + + bool fDoPE16 : 1; + bool fDoPE16_32 : 1; + bool fDoPE16_V86 : 1; + bool fDoPE32 : 1; + bool fDoPE32_16 : 1; + bool fDoPEV86 : 1; + + bool fDoPP16 : 1; + bool fDoPP16_32 : 1; + bool fDoPP16_V86 : 1; + bool fDoPP32 : 1; + bool fDoPP32_16 : 1; + bool fDoPPV86 : 1; + + bool fDoPAE16 : 1; + bool fDoPAE16_32 : 1; + bool fDoPAE16_V86 : 1; + bool fDoPAE32 : 1; + bool fDoPAE32_16 : 1; + bool fDoPAEV86 : 1; + + bool fDoLM16 : 1; + bool fDoLM32 : 1; + bool fDoLM64 : 1; + +} BS3TESTMODEBYMAXENTRY; +/** Pointer to a mode-by-max sub-test entry. */ +typedef BS3TESTMODEBYMAXENTRY const *PCBS3TESTMODEBYMAXENTRY; + +/** @def BS3TESTMODEBYMAXENTRY_CMN + * Produces a BS3TESTMODEBYMAXENTRY initializer for common (c16,c32,c64) test + * functions. */ +#define BS3TESTMODEBYMAXENTRY_CMN(a_szTest, a_BaseNm) \ + { /*pszSubTest =*/ a_szTest, \ + /*RM*/ RT_CONCAT(a_BaseNm, _c16), \ + /*PE16*/ RT_CONCAT(a_BaseNm, _c16), \ + /*PE16_32*/ RT_CONCAT(a_BaseNm, _c32), \ + /*PE32*/ RT_CONCAT(a_BaseNm, _c32), \ + /*PP16_32*/ RT_CONCAT(a_BaseNm, _c32), \ + /*PP32*/ RT_CONCAT(a_BaseNm, _c32), \ + /*PAE16_32*/ RT_CONCAT(a_BaseNm, _c32), \ + /*PAE32*/ RT_CONCAT(a_BaseNm, _c32), \ + /*LM64*/ RT_CONCAT(a_BaseNm, _c64), \ + /*fDoRM*/ true, \ + /*fDoPE16*/ true, \ + /*fDoPE16_32*/ true, \ + /*fDoPE16_V86*/ true, \ + /*fDoPE32*/ true, \ + /*fDoPE32_16*/ true, \ + /*fDoPEV86*/ true, \ + /*fDoPP16*/ true, \ + /*fDoPP16_32*/ true, \ + /*fDoPP16_V86*/ true, \ + /*fDoPP32*/ true, \ + /*fDoPP32_16*/ true, \ + /*fDoPPV86*/ true, \ + /*fDoPAE16*/ true, \ + /*fDoPAE16_32*/ true, \ + /*fDoPAE16_V86*/ true, \ + /*fDoPAE32*/ true, \ + /*fDoPAE32_16*/ true, \ + /*fDoPAEV86*/ true, \ + /*fDoLM16*/ true, \ + /*fDoLM32*/ true, \ + /*fDoLM64*/ true, \ + } + +/** @def BS3TESTMODEBYMAX_PROTOTYPES_CMN + * A set of standard protypes to go with #BS3TESTMODEBYMAXENTRY_CMN. */ +#define BS3TESTMODEBYMAX_PROTOTYPES_CMN(a_BaseNm) \ + FNBS3TESTDOMODE /*BS3_FAR_CODE*/ RT_CONCAT(a_BaseNm, _c16); \ + FNBS3TESTDOMODE /*BS3_FAR_CODE*/ RT_CONCAT(a_BaseNm, _c32); \ + FNBS3TESTDOMODE /*BS3_FAR_CODE*/ RT_CONCAT(a_BaseNm, _c64) + + +/** @def BS3TESTMODEBYMAXENTRY_MODE + * Produces a BS3TESTMODEBYMAXENTRY initializer for a full set of mode test + * functions. */ +#define BS3TESTMODEBYMAXENTRY_MODE(a_szTest, a_BaseNm) \ + { /*pszSubTest =*/ a_szTest, \ + /*RM*/ RT_CONCAT(a_BaseNm, _rm), \ + /*PE16*/ RT_CONCAT(a_BaseNm, _pe16), \ + /*PE16_32*/ RT_CONCAT(a_BaseNm, _pe16_32), \ + /*PE32*/ RT_CONCAT(a_BaseNm, _pe32), \ + /*PP16_32*/ RT_CONCAT(a_BaseNm, _pp16_32), \ + /*PP32*/ RT_CONCAT(a_BaseNm, _pp32), \ + /*PAE16_32*/ RT_CONCAT(a_BaseNm, _pae16_32), \ + /*PAE32*/ RT_CONCAT(a_BaseNm, _pae32), \ + /*LM64*/ RT_CONCAT(a_BaseNm, _lm64), \ + /*fDoRM*/ true, \ + /*fDoPE16*/ true, \ + /*fDoPE16_32*/ true, \ + /*fDoPE16_V86*/ true, \ + /*fDoPE32*/ true, \ + /*fDoPE32_16*/ true, \ + /*fDoPEV86*/ true, \ + /*fDoPP16*/ true, \ + /*fDoPP16_32*/ true, \ + /*fDoPP16_V86*/ true, \ + /*fDoPP32*/ true, \ + /*fDoPP32_16*/ true, \ + /*fDoPPV86*/ true, \ + /*fDoPAE16*/ true, \ + /*fDoPAE16_32*/ true, \ + /*fDoPAE16_V86*/ true, \ + /*fDoPAE32*/ true, \ + /*fDoPAE32_16*/ true, \ + /*fDoPAEV86*/ true, \ + /*fDoLM16*/ true, \ + /*fDoLM32*/ true, \ + /*fDoLM64*/ true, \ + } + +/** @def BS3TESTMODEBYMAX_PROTOTYPES_MODE + * A set of standard protypes to go with #BS3TESTMODEBYMAXENTRY_MODE. */ +#define BS3TESTMODEBYMAX_PROTOTYPES_MODE(a_BaseNm) \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _rm); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pe16); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pe16_32); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pe32); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pp16_32); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pp32); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pae16_32); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _pae32); \ + FNBS3TESTDOMODE RT_CONCAT(a_BaseNm, _lm64) + + +/** + * One worker drives all modes. + * + * This is an alternative to BS3TESTMODEENTRY where one worker, typically + * 16-bit, does all the test driver work. It's called repeatedly from all + * the modes being tested. + */ +typedef struct BS3TESTMODEBYONEENTRY +{ + const char * BS3_FAR pszSubTest; + PFNBS3TESTDOMODE pfnWorker; + /** BS3TESTMODEBYONEENTRY_F_XXX. */ + uint32_t fFlags; +} BS3TESTMODEBYONEENTRY; +/** Pointer to a mode-by-one sub-test entry. */ +typedef BS3TESTMODEBYONEENTRY const *PCBS3TESTMODEBYONEENTRY; + +/** @name BS3TESTMODEBYONEENTRY_F_XXX - flags. + * @{ */ +/** Only test modes that has paging enabled. */ +#define BS3TESTMODEBYONEENTRY_F_ONLY_PAGING RT_BIT_32(0) +/** Minimal mode selection. */ +#define BS3TESTMODEBYONEENTRY_F_MINIMAL RT_BIT_32(1) +/** The 32-bit worker is ready to handle real-mode by mode switching. */ +#define BS3TESTMODEBYONEENTRY_F_REAL_MODE_READY RT_BIT_32(2) +/** @} */ + + +/** + * Sets the full GDTR register. + * + * @param cbLimit The limit. + * @param uBase The base address - 24, 32 or 64 bit depending on the + * CPU mode. + */ +BS3_CMN_PROTO_NOSB(void, Bs3UtilSetFullGdtr,(uint16_t cbLimit, uint64_t uBase)); + +/** + * Sets the full IDTR register. + * + * @param cbLimit The limit. + * @param uBase The base address - 24, 32 or 64 bit depending on the + * CPU mode. + */ +BS3_CMN_PROTO_NOSB(void, Bs3UtilSetFullIdtr,(uint16_t cbLimit, uint64_t uBase)); + + +/** @} */ + + +/** + * Initializes all of boot sector kit \#3. + */ +BS3_DECL(void) Bs3InitAll_rm(void); + +/** + * Initializes the REAL and TILED memory pools. + * + * For proper operation on OLDer CPUs, call #Bs3CpuDetect_mmm first. + */ +BS3_DECL_FAR(void) Bs3InitMemory_rm_far(void); + +/** + * Initializes the X0TEXT16 and X1TEXT16 GDT entries. + */ +BS3_DECL_FAR(void) Bs3InitGdt_rm_far(void); + + + +/** @defgroup grp_bs3kit_mode Mode Specific Functions and Data + * + * The mode specific functions come in bit count variations and CPU mode + * variations. The bs3kit-template-header.h/mac defines the BS3_NM macro to + * mangle a function or variable name according to the target CPU mode. In + * non-templated code, it's common to spell the name out in full. + * + * @{ + */ + + +/** @def BS3_MODE_PROTO_INT + * Internal macro for emitting prototypes for mode functions. + * + * @param a_RetType The return type. + * @param a_Name The function basename. + * @param a_Params The parameter list (in parentheses). + * @sa BS3_MODE_PROTO_STUB, BS3_MODE_PROTO_NOSB + */ +#define BS3_MODE_PROTO_INT(a_RetType, a_Name, a_Params) \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_rm) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_pe16) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_pe16_32) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_pe16_v86) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_pe32) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_pe32_16) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_pev86) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_pp16) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_pp16_32) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_pp16_v86) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_pp32) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_pp32_16) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_ppv86) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_pae16) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_pae16_32) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_pae16_v86) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_pae32) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_pae32_16) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_paev86) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_lm16) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_lm32) a_Params; \ + BS3_DECL_NEAR(a_RetType) RT_CONCAT(a_Name,_lm64) a_Params; \ + BS3_DECL_FAR(a_RetType) RT_CONCAT(a_Name,_rm_far) a_Params; \ + BS3_DECL_FAR(a_RetType) RT_CONCAT(a_Name,_pe16_far) a_Params; \ + BS3_DECL_FAR(a_RetType) RT_CONCAT(a_Name,_pe16_v86_far) a_Params; \ + BS3_DECL_FAR(a_RetType) RT_CONCAT(a_Name,_pe32_16_far) a_Params; \ + BS3_DECL_FAR(a_RetType) RT_CONCAT(a_Name,_pev86_far) a_Params; \ + BS3_DECL_FAR(a_RetType) RT_CONCAT(a_Name,_pp16_far) a_Params; \ + BS3_DECL_FAR(a_RetType) RT_CONCAT(a_Name,_pp16_v86_far) a_Params; \ + BS3_DECL_FAR(a_RetType) RT_CONCAT(a_Name,_pp32_16_far) a_Params; \ + BS3_DECL_FAR(a_RetType) RT_CONCAT(a_Name,_ppv86_far) a_Params; \ + BS3_DECL_FAR(a_RetType) RT_CONCAT(a_Name,_pae16_far) a_Params; \ + BS3_DECL_FAR(a_RetType) RT_CONCAT(a_Name,_pae16_v86_far)a_Params; \ + BS3_DECL_FAR(a_RetType) RT_CONCAT(a_Name,_pae32_16_far) a_Params; \ + BS3_DECL_FAR(a_RetType) RT_CONCAT(a_Name,_paev86_far) a_Params; \ + BS3_DECL_FAR(a_RetType) RT_CONCAT(a_Name,_lm16_far) a_Params + +/** @def BS3_MODE_PROTO_STUB + * Macro for prototyping all the variations of a mod function with automatic + * near -> far stub. + * + * @param a_RetType The return type. + * @param a_Name The function basename. + * @param a_Params The parameter list (in parentheses). + * @sa BS3_MODE_PROTO_STUB, BS3_MODE_PROTO_NOSB + */ +#define BS3_MODE_PROTO_STUB(a_RetType, a_Name, a_Params) BS3_MODE_PROTO_INT(a_RetType, a_Name, a_Params) + +/** @def BS3_MODE_PROTO_STUB + * Macro for prototyping all the variations of a mod function without any + * near -> far stub. + * + * @param a_RetType The return type. + * @param a_Name The function basename. + * @param a_Params The parameter list (in parentheses). + * @sa BS3_MODE_PROTO_STUB, BS3_MODE_PROTO_NOSB + */ +#define BS3_MODE_PROTO_NOSB(a_RetType, a_Name, a_Params) BS3_MODE_PROTO_INT(a_RetType, a_Name, a_Params) + + +/** + * Macro for reducing typing. + * + * Doxygen knows how to expand this, well, kind of. + * + * @remarks Variables instantiated in assembly code should define two labels, + * with and without leading underscore. Variables instantiated from + * C/C++ code doesn't need to as the object file convert does this for + * 64-bit object files. + */ +#define BS3_MODE_EXPAND_EXTERN_DATA16(a_VarType, a_VarName, a_Suffix) \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_rm) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_pe16) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_pe16_32) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_pe16_v86) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_pe32) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_pe32_16) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_pev86) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_pp16) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_pp16_32) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_pp16_v86) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_pp32) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_pp32_16) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_ppv86) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_pae16) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_pae16_32) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_pae16_v86)a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_pae32) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_pae32_16) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_paev86) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_lm16) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_lm32) a_Suffix; \ + extern a_VarType BS3_FAR_DATA RT_CONCAT(a_VarName,_lm64) a_Suffix + + +/** The TMPL_MODE_STR value for each mode. + * These are all in DATA16 so they can be accessed from any code. */ +BS3_MODE_EXPAND_EXTERN_DATA16(const char, g_szBs3ModeName, []); +/** The TMPL_MODE_LNAME value for each mode. + * These are all in DATA16 so they can be accessed from any code. */ +BS3_MODE_EXPAND_EXTERN_DATA16(const char, g_szBs3ModeNameShortLower, []); + + +/** + * Basic CPU detection. + * + * This sets the #g_uBs3CpuDetected global variable to the return value. + * + * @returns BS3CPU_XXX value with the BS3CPU_F_CPUID flag set depending on + * capabilities. + */ +BS3_MODE_PROTO_NOSB(uint8_t, Bs3CpuDetect,(void)); + +/** @name BS3CPU_XXX - CPU detected by BS3CpuDetect_c16() and friends. + * @{ */ +#define BS3CPU_8086 UINT16_C(0x0001) /**< Both 8086 and 8088. */ +#define BS3CPU_V20 UINT16_C(0x0002) /**< Both NEC V20, V30 and relatives. */ +#define BS3CPU_80186 UINT16_C(0x0003) /**< Both 80186 and 80188. */ +#define BS3CPU_80286 UINT16_C(0x0004) +#define BS3CPU_80386 UINT16_C(0x0005) +#define BS3CPU_80486 UINT16_C(0x0006) +#define BS3CPU_Pentium UINT16_C(0x0007) +#define BS3CPU_PPro UINT16_C(0x0008) +#define BS3CPU_PProOrNewer UINT16_C(0x0009) +/** CPU type mask. This is a full byte so it's possible to use byte access + * without and AND'ing to get the type value. */ +#define BS3CPU_TYPE_MASK UINT16_C(0x00ff) +/** Flag indicating that the CPUID instruction is supported by the CPU. */ +#define BS3CPU_F_CPUID UINT16_C(0x0100) +/** Flag indicating that extend CPUID leaves are available (at least two). */ +#define BS3CPU_F_CPUID_EXT_LEAVES UINT16_C(0x0200) +/** Flag indicating that the CPU supports PAE. */ +#define BS3CPU_F_PAE UINT16_C(0x0400) +/** Flag indicating that the CPU supports the page size extension (4MB pages). */ +#define BS3CPU_F_PSE UINT16_C(0x0800) +/** Flag indicating that the CPU supports long mode. */ +#define BS3CPU_F_LONG_MODE UINT16_C(0x1000) +/** Flag indicating that the CPU supports NX. */ +#define BS3CPU_F_NX UINT16_C(0x2000) +/** @} */ + +/** The return value of #Bs3CpuDetect_mmm. (Initial value is BS3CPU_TYPE_MASK.) */ +extern uint16_t g_uBs3CpuDetected; + +/** + * Call 32-bit prot mode C function. + * + * This switches to 32-bit mode and calls the 32-bit @a fpfnCall C code with @a + * cbParams on the stack, then returns in the original mode. When called in + * real mode, this will switch to PE32. + * + * @returns 32-bit status code if the function returned anything. + * @param fpfnCall Address of the 32-bit C function to call. When + * called from 16-bit code, this is a far real mode + * function pointer, i.e. as fixed up by the linker. + * In 32-bit and 64-bit code, this is a flat address. + * @param cbParams The size of the parameter list, in bytes. + * @param ... The parameters. + * @sa Bs3SwitchFromV86To16BitAndCallC + * + * @remarks WARNING! This probably doesn't work in 64-bit mode yet. + * Only tested for 16-bit real mode. + */ +BS3_MODE_PROTO_STUB(int32_t, Bs3SwitchTo32BitAndCallC,(FPFNBS3FAR fpfnCall, unsigned cbParams, ...)); + +/** + * Initializes trap handling for the current system. + * + * Calls the appropriate Bs3Trap16Init, Bs3Trap32Init or Bs3Trap64Init function. + */ +BS3_MODE_PROTO_STUB(void, Bs3TrapInit,(void)); + +/** + * Executes the array of tests in every possibly mode. + * + * @param paEntries The mode sub-test entries. + * @param cEntries The number of sub-test entries. + */ +BS3_MODE_PROTO_NOSB(void, Bs3TestDoModes,(PCBS3TESTMODEENTRY paEntries, size_t cEntries)); + +/** + * Executes the array of tests in every possibly mode, unified driver. + * + * This requires much less code space than Bs3TestDoModes as there is only one + * instace of each sub-test driver code, instead of 3 (cmn) or 22 (per-mode) + * copies. + * + * @param paEntries The mode sub-test-by-one entries. + * @param cEntries The number of sub-test-by-one entries. + * @param fFlags BS3TESTMODEBYONEENTRY_F_XXX. + */ +BS3_MODE_PROTO_NOSB(void, Bs3TestDoModesByOne,(PCBS3TESTMODEBYONEENTRY paEntries, size_t cEntries, uint32_t fFlags)); + +/** + * Executes the array of tests in every possibly mode, using the max bit-count + * worker for each. + * + * @param paEntries The mode sub-test entries. + * @param cEntries The number of sub-test entries. + */ +BS3_MODE_PROTO_NOSB(void, Bs3TestDoModesByMax,(PCBS3TESTMODEBYMAXENTRY paEntries, size_t cEntries)); + +/** @} */ + + +/** @defgroup grp_bs3kit_bios_int15 BIOS - int 15h + * @{ */ + +/** An INT15E820 data entry. */ +typedef struct INT15E820ENTRY +{ + uint64_t uBaseAddr; + uint64_t cbRange; + /** Memory type this entry describes, see INT15E820_TYPE_XXX. */ + uint32_t uType; + /** Optional. */ + uint32_t fAcpi3; +} INT15E820ENTRY; +AssertCompileSize(INT15E820ENTRY,24); + + +/** @name INT15E820_TYPE_XXX - Memory types returned by int 15h function 0xe820. + * @{ */ +#define INT15E820_TYPE_USABLE 1 /**< Usable RAM. */ +#define INT15E820_TYPE_RESERVED 2 /**< Reserved by the system, unusable. */ +#define INT15E820_TYPE_ACPI_RECLAIMABLE 3 /**< ACPI reclaimable memory, whatever that means. */ +#define INT15E820_TYPE_ACPI_NVS 4 /**< ACPI non-volatile storage? */ +#define INT15E820_TYPE_BAD 5 /**< Bad memory, unusable. */ +/** @} */ + + +/** + * Performs an int 15h function 0xe820 call. + * + * @returns Success indicator. + * @param pEntry The return buffer. + * @param pcbEntry Input: The size of the buffer (min 20 bytes); + * Output: The size of the returned data. + * @param puContinuationValue Where to get and return the continuation value (EBX) + * Set to zero the for the first call. Returned as zero + * after the last entry. + */ +BS3_MODE_PROTO_STUB(bool, Bs3BiosInt15hE820,(INT15E820ENTRY BS3_FAR *pEntry, uint32_t BS3_FAR *pcbEntry, + uint32_t BS3_FAR *puContinuationValue)); + +/** + * Performs an int 15h function 0x88 call. + * + * @returns UINT32_MAX on failure, number of KBs above 1MB otherwise. + */ +#if ARCH_BITS != 16 || !defined(BS3_BIOS_INLINE_RM) +BS3_MODE_PROTO_STUB(uint32_t, Bs3BiosInt15h88,(void)); +#else +BS3_DECL(uint32_t) Bs3BiosInt15h88(void); +# pragma aux Bs3BiosInt15h88 = \ + ".286" \ + "clc" \ + "mov ax, 08800h" \ + "int 15h" \ + "jc failed" \ + "xor dx, dx" \ + "jmp done" \ + "failed:" \ + "xor ax, ax" \ + "dec ax" \ + "mov dx, ax" \ + "done:" \ + value [ax dx] \ + modify exact [ax bx cx dx es]; +#endif + +/** @} */ + + +/** @} */ + +RT_C_DECLS_END + + +/* + * Include default function symbol mangling. + */ +#include "bs3kit-mangling-code.h" + +/* + * Change 16-bit text segment if requested. + */ +#if defined(BS3_USE_ALT_16BIT_TEXT_SEG) && ARCH_BITS == 16 && !defined(BS3_DONT_CHANGE_TEXT_SEG) +# if (defined(BS3_USE_RM_TEXT_SEG) + defined(BS3_USE_X0_TEXT_SEG) + defined(BS3_USE_X1_TEXT_SEG)) != 1 +# error "Cannot set more than one alternative 16-bit text segment!" +# elif defined(BS3_USE_RM_TEXT_SEG) +# pragma code_seg("BS3RMTEXT16", "BS3CLASS16RMCODE") +# elif defined(BS3_USE_X0_TEXT_SEG) +# pragma code_seg("BS3X0TEXT16", "BS3CLASS16X0CODE") +# elif defined(BS3_USE_X1_TEXT_SEG) +# pragma code_seg("BS3X1TEXT16", "BS3CLASS16X1CODE") +# else +# error "Huh? Which alternative text segment did you want again?" +# endif +#endif + +#endif /* !BS3KIT_INCLUDED_bs3kit_h */ + diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit.mac b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit.mac new file mode 100644 index 00000000..0bd451b1 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit.mac @@ -0,0 +1,1767 @@ +; $Id: bs3kit.mac $ +;; @file +; BS3Kit - structures, symbols, macros and stuff. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + +%ifndef ___bs3kit_mac___ +%define ___bs3kit_mac___ + +; +; Before we can include anything, we need to override NAME and switch section. +; If we don't do the latter we end up with an unused 'text' section. +; + +; Drop the asmdefs-first.mac header for native bs3kit files. +%undef RT_ASMDEFS_INC_FIRST_FILE + +;; +; Macro for setting register aliases according to the bit count given by %1. +; +%macro BS3_SET_REG_ALIASES 1 + ; + ; Register aliases. + ; + %if %1 == 64 + %define xCB 8 + %define xDEF dq + %define xRES resq + %define xPRE qword + %define xSP rsp + %define xBP rbp + %define xAX rax + %define xBX rbx + %define xCX rcx + %define xDX rdx + %define xDI rdi + %define xSI rsi + %define xWrtRIP wrt rip + %define xPUSHF pushfq + %define xPOPF popfq + %define xRETF o64 retf + %elif %1 == 32 + %define xCB 4 + %define xDEF dd + %define xRES resd + %define xPRE dword + %define xSP esp + %define xBP ebp + %define xAX eax + %define xBX ebx + %define xCX ecx + %define xDX edx + %define xDI edi + %define xSI esi + %define xWrtRIP + %define xPUSHF pushfd + %define xPOPF popfd + %define xRETF retf + %elif %1 == 16 + %define xCB 2 + %define xDEF dw + %define xRES resw + %define xPRE word + %define xSP sp + %define xBP bp + %define xAX ax + %define xBX bx + %define xCX cx + %define xDX dx + %define xDI di + %define xSI si + %define xWrtRIP + %define xPUSHF pushf + %define xPOPF popf + %define xRETF retf + %else + %error "Invalid BS3_SET_REG_ALIASES argument:" %1 + %endif + + + ; + ; Register names corresponding to the max size for pop/push <reg>. + ; + ; 16-bit can push both 32-bit and 16-bit registers. This 's' prefixed variant + ; is used when 16-bit should use the 32-bit register. + ; + %if %1 == 64 + %define sCB 8 + %define sDEF dq + %define sRES resq + %define sPRE qword + %define sSP rsp + %define sBP rbp + %define sAX rax + %define sBX rbx + %define sCX rcx + %define sDX rdx + %define sDI rdi + %define sSI rsi + %define sPUSHF pushfq + %define sPOPF popfq + %else + %define sCB 4 + %define sDEF dd + %define sRES resd + %define sPRE dword + %define sSP esp + %define sBP ebp + %define sAX eax + %define sBX ebx + %define sCX ecx + %define sDX edx + %define sDI edi + %define sSI esi + %define sPUSHF pushfd + %define sPOPF popfd + %endif +%endmacro + +;; +; Redefines macros that follows __BITS__. +%macro BS3_SET_BITS_MACROS 1 + ;; Emulate the __BITS__ macro in NASM 2.0+. Follows BS3_SET_BITS. + %ifdef __YASM__ + %undef __BITS__ + %define __BITS__ %1 + %endif + + ;; Mostly internal macro. Follows BS3_SET_BITS. + %undef BS3_NAME_UNDERSCORE + %define BS3_NAME_UNDERSCORE _ + + ;; For segment overrides and stuff. Follows BS3_SET_BITS. + %undef BS3_ONLY_16BIT + %if %1 == 16 + %define BS3_ONLY_16BIT(a_Expr) a_Expr + %else + %define BS3_ONLY_16BIT(a_Expr) + %endif + + ;; For odd 64-bit stuff. Follows BS3_SET_BITS. + %undef BS3_ONLY_64BIT + %if %1 == 64 + %define BS3_ONLY_64BIT(a_Expr) a_Expr + %else + %define BS3_ONLY_64BIT(a_Expr) + %endif + + ;; For segment overrides and stuff. Follows BS3_SET_BITS. + %undef BS3_NOT_64BIT + %if %1 == 64 + %define BS3_NOT_64BIT(a_Expr) + %else + %define BS3_NOT_64BIT(a_Expr) a_Expr + %endif + + ;; For stack cleanups and similar where each bit mode is different. Follows BS3_SET_BITS. + %undef BS3_IF_16_32_64BIT + %if %1 == 16 + %define BS3_IF_16_32_64BIT(a_16BitExpr, a_32BitExpr, a_64BitExpr) a_16BitExpr + %elif %1 == 32 + %define BS3_IF_16_32_64BIT(a_16BitExpr, a_32BitExpr, a_64BitExpr) a_32BitExpr + %else + %define BS3_IF_16_32_64BIT(a_16BitExpr, a_32BitExpr, a_64BitExpr) a_64BitExpr + %endif + + ;; For RIP relative addressing in 64-bit mode and absolute addressing in + ; other modes. Follows BS3_SET_BITS. + %undef BS3_WRT_RIP + %if %1 == 64 + %define BS3_WRT_RIP(a_Sym) rel a_Sym + %else + %define BS3_WRT_RIP(a_Sym) a_Sym + %endif + + %undef BS3_LEA_MOV_WRT_RIP + %if %1 == 64 + %define BS3_LEA_MOV_WRT_RIP(a_DstReg, a_Sym) lea a_DstReg, [BS3_WRT_RIP(a_Sym)] + %else + %define BS3_LEA_MOV_WRT_RIP(a_DstReg, a_Sym) mov a_DstReg, a_Sym + %endif + + ;; @def BS3_DATA16_WRT + ; For accessing BS3DATA16 correctly. + ; @param a_Var The BS3DATA16 variable. + %undef BS3_DATA16_WRT + %if %1 == 16 + %define BS3_DATA16_WRT(a_Var) a_Var wrt BS3KIT_GRPNM_DATA16 + %elif %1 == 32 + %define BS3_DATA16_WRT(a_Var) a_Var wrt FLAT + %else + %define BS3_DATA16_WRT(a_Var) BS3_WRT_RIP(a_Var) wrt FLAT + %endif + + ;; @def BS3_TEXT16_WRT + ; For accessing BS3DATA16 correctly. + ; @param a_Label The BS3TEXT16 label. + %undef BS3_TEXT16_WRT + %if %1 == 16 + %define BS3_TEXT16_WRT(a_Label) a_Label wrt CGROUP16 + %elif %1 == 32 + %define BS3_TEXT16_WRT(a_Label) a_Label wrt FLAT + %else + %define BS3_TEXT16_WRT(a_Label) BS3_WRT_RIP(a_Label) wrt FLAT + %endif + + %undef BS3_IF_16BIT_OTHERWISE + %if %1 == 16 + %define BS3_IF_16BIT_OTHERWISE(a_16BitExpr, a_OtherwiseExpr) a_16BitExpr + %else + %define BS3_IF_16BIT_OTHERWISE(a_16BitExpr, a_OtherwiseExpr) a_OtherwiseExpr + %endif + + %undef BS3_IF_32BIT_OTHERWISE + %if %1 == 32 + %define BS3_IF_32BIT_OTHERWISE(a_32BitExpr, a_OtherwiseExpr) a_32BitExpr + %else + %define BS3_IF_32BIT_OTHERWISE(a_32BitExpr, a_OtherwiseExpr) a_OtherwiseExpr + %endif + + %undef BS3_IF_64BIT_OTHERWISE + %if %1 == 64 + %define BS3_IF_64BIT_OTHERWISE(a_64BitExpr, a_OtherwiseExpr) a_64BitExpr + %else + %define BS3_IF_64BIT_OTHERWISE(a_64BitExpr, a_OtherwiseExpr) a_OtherwiseExpr + %endif + + ;; + ; Same as BS3_CMN_NM except in 16-bit mode, it will generate the far name. + ; (16-bit code generally have both near and far callable symbols, so we won't + ; be restricted to 64KB test code.) + %if %1 == 16 + %define BS3_CMN_NM_FAR(a_Name) BS3_NAME_UNDERSCORE %+ a_Name %+ _f %+ __BITS__ + %else + %define BS3_CMN_NM_FAR(a_Name) BS3_CMN_NM(a_Name) + %endif + +%endmacro + +; Default to register aliases for ARCH_BITS. +BS3_SET_REG_ALIASES ARCH_BITS + +; Define macros for ARCH_BITS. +BS3_SET_BITS_MACROS ARCH_BITS + + +;; Wrapper around BITS. +; Updates __BITS__ (built-in variable in nasm, we work it for yasm) as well +; a number of convenient macros and register aliases. +; +; @param %1 The CPU bit count: 16, 32 or 64 +; @remarks ARCH_BITS is not modified and will remain what it was on the +; assembler command line. +%macro BS3_SET_BITS 1 + BITS %1 + BS3_SET_BITS_MACROS %1 + BS3_SET_REG_ALIASES %1 +%endmacro + +;; +; For instruction that should only be emitted in 16-bit mode. Follows BS3_SET_BITS. +; BONLY16 normally goes in column 1. +%macro BONLY16 1+ + %if __BITS__ == 16 + %1 + %endif +%endmacro + +;; +; For instruction that should only be emitted in 32-bit mode. Follows BS3_SET_BITS. +; BONLY32 normally goes in column 1. +%macro BONLY32 1+ + %if __BITS__ == 32 + %1 + %endif +%endmacro + +;; +; For instruction that should only be emitted in 64-bit mode. Follows BS3_SET_BITS. +; BONLY64 normally goes in column 1. +%macro BONLY64 1+ + %if __BITS__ == 64 + %1 + %endif +%endmacro + + + +;; @name Segment definitions. +;; @{ + +%ifndef ASM_FORMAT_BIN +; !!HACK ALERT!! +; +; To make FLAT actually be flat, i.e. have a base of 0 rather than the same as +; the target (?) segment, we tweak it a little bit here. We associate a segment +; with it so that we can get at it in the class/segment ordering directives +; we pass to the linker. The segment does not contain any data or anything, it +; is just an empty one which we assign the address of zero. +; +; Look for 'clname BS3FLAT segaddr=0x0000' and 'segment BS3FLAT segaddr=0x0000' +; in the makefile. +; +; !!HACK ALERT!! +segment BS3FLAT use32 class=BS3FLAT +GROUP FLAT BS3FLAT +%endif + + +;; +; Changes to the BS3TEXT16 segment, defining it if necessary. +; @param %1 The bitcount to invoke BS3_SET_BITS with, default is 16. +%macro BS3_BEGIN_TEXT16 0-1 16 + %ifndef BS3_BEGIN_TEXT16_NOT_FIRST + %define BS3_BEGIN_TEXT16_NOT_FIRST + section BS3TEXT16 align=2 CLASS=BS3CLASS16CODE PUBLIC USE16 + %ifndef BS3_BEGIN_TEXT16_WITHOUT_GROUP ; bs3-first-common.mac trick. + %ifndef BS3_BEGIN_TEXT16_NEARSTUBS_NOT_FIRST + %define BS3_BEGIN_TEXT16_NEARSTUBS_NOT_FIRST + section BS3TEXT16_NEARSTUBS align=1 CLASS=BS3CLASS16CODE PUBLIC USE16 + %endif + %ifndef BS3_BEGIN_TEXT16_FARSTUBS_NOT_FIRST + %define BS3_BEGIN_TEXT16_FARSTUBS_NOT_FIRST + section BS3TEXT16_FARSTUBS align=1 CLASS=BS3CLASS16CODE PUBLIC USE16 + %endif + GROUP CGROUP16 BS3TEXT16 BS3TEXT16_NEARSTUBS BS3TEXT16_FARSTUBS + section BS3TEXT16 + %endif + %else + section BS3TEXT16 + %endif + %undef BS3_CUR_SEG_BEGIN_MACRO + %xdefine BS3_CUR_SEG_BEGIN_MACRO BS3_BEGIN_TEXT16 + BS3_SET_BITS %1 +%endmacro + +%macro BS3_BEGIN_TEXT16_NEARSTUBS 0 + %ifndef BS3_BEGIN_TEXT16_NEARSTUBS_NOT_FIRST + %define BS3_BEGIN_TEXT16_NEARSTUBS_NOT_FIRST + section BS3TEXT16_NEARSTUBS align=1 CLASS=BS3CLASS16CODE PUBLIC USE16 + %else + section BS3TEXT16_NEARSTUBS + %endif + %undef BS3_CUR_SEG_BEGIN_MACRO + %xdefine BS3_CUR_SEG_BEGIN_MACRO BS3_BEGIN_TEXT16_NEARSTUBS + BS3_SET_BITS 16 +%endmacro + +%macro BS3_BEGIN_TEXT16_FARSTUBS 0 + %ifndef BS3_BEGIN_TEXT16_FARSTUBS_NOT_FIRST + %define BS3_BEGIN_TEXT16_FARSTUBS_NOT_FIRST + section BS3TEXT16_FARSTUBS align=1 CLASS=BS3CLASS16CODE PUBLIC USE16 + %else + section BS3TEXT16_FARSTUBS + %endif + %undef BS3_CUR_SEG_BEGIN_MACRO + %xdefine BS3_CUR_SEG_BEGIN_MACRO BS3_BEGIN_TEXT16_FARSTUBS + BS3_SET_BITS 16 +%endmacro + +%macro BS3_BEGIN_RMTEXT16 0-1 2 + %ifndef BS3_BEGIN_RMTEXT16_NOT_FIRST + %define BS3_BEGIN_RMTEXT16_NOT_FIRST + section BS3RMTEXT16 align=%1 CLASS=BS3CLASS16RMCODE PUBLIC USE16 + %ifndef BS3_BEGIN_RMTEXT16_WITHOUT_GROUP ; bs3-first-common.mac trick. + GROUP BS3GROUPRMTEXT16 BS3RMTEXT16 + %endif + %else + section BS3RMTEXT16 + %endif + %undef BS3_CUR_SEG_BEGIN_MACRO + %xdefine BS3_CUR_SEG_BEGIN_MACRO BS3_BEGIN_RMTEXT16 + BS3_SET_BITS 16 +%endmacro + +%macro BS3_BEGIN_X0TEXT16 0-1 2 + %ifndef BS3_BEGIN_X0TEXT16_NOT_FIRST + %define BS3_BEGIN_X0TEXT16_NOT_FIRST + section BS3X0TEXT16 align=%1 CLASS=BS3CLASS16X0CODE PUBLIC USE16 + %ifndef BS3_BEGIN_X0TEXT16_WITHOUT_GROUP ; bs3-first-common.mac trick. + GROUP BS3GROUPX0TEXT16 BS3X0TEXT16 + %endif + %else + section BS3X0TEXT16 + %endif + %undef BS3_CUR_SEG_BEGIN_MACRO + %xdefine BS3_CUR_SEG_BEGIN_MACRO BS3_BEGIN_X0TEXT16 + BS3_SET_BITS 16 +%endmacro + +%macro BS3_BEGIN_X1TEXT16 0-1 2 + %ifndef BS3_BEGIN_X1TEXT16_NOT_FIRST + %define BS3_BEGIN_X1TEXT16_NOT_FIRST + section BS3X1TEXT16 align=%1 CLASS=BS3CLASS16X1CODE PUBLIC USE16 + %ifndef BS3_BEGIN_X1TEXT16_WITHOUT_GROUP ; bs3-first-common.mac trick. + GROUP BS3GROUPX1TEXT16 BS3X1TEXT16 + %endif + %else + section BS3X1TEXT16 + %endif + %undef BS3_CUR_SEG_BEGIN_MACRO + %xdefine BS3_CUR_SEG_BEGIN_MACRO BS3_BEGIN_X1TEXT16 + BS3_SET_BITS 16 +%endmacro + + +%macro BS3_BEGIN_DATA16 0-1 2 + %ifndef BS3_BEGIN_DATA16_NOT_FIRST + %define BS3_BEGIN_DATA16_NOT_FIRST + section BS3DATA16 align=%1 CLASS=BS3KIT_CLASS_DATA16 PUBLIC USE16 + %ifndef BS3_BEGIN_DATA16_WITHOUT_GROUP ; bs3-first-common.mac trick. + GROUP BS3KIT_GRPNM_DATA16 BS3DATA16 + %endif + %else + section BS3DATA16 + %endif + %undef BS3_CUR_SEG_BEGIN_MACRO + %xdefine BS3_CUR_SEG_BEGIN_MACRO BS3_BEGIN_DATA16 + BS3_SET_BITS 16 +%endmacro + +%macro BS3_BEGIN_TEXT32 0-1 2 + %ifndef BS3_BEGIN_TEXT32_NOT_FIRST + %define BS3_BEGIN_TEXT32_NOT_FIRST + section BS3TEXT32 align=%1 CLASS=BS3CLASS32CODE PUBLIC USE32 FLAT + %else + section BS3TEXT32 + %endif + %undef BS3_CUR_SEG_BEGIN_MACRO + %xdefine BS3_CUR_SEG_BEGIN_MACRO BS3_BEGIN_TEXT32 + BS3_SET_BITS 32 +%endmacro + +%macro BS3_BEGIN_DATA32 0-1 16 + %ifndef BS3_BEGIN_DATA32_NOT_FIRST + %define BS3_BEGIN_DATA32_NOT_FIRST + section BS3DATA32 align=%1 CLASS=FAR_DATA PUBLIC USE32 ;FLAT - compiler doesn't make data flat. + %else + section BS3DATA32 + %endif + %undef BS3_CUR_SEG_BEGIN_MACRO + %xdefine BS3_CUR_SEG_BEGIN_MACRO BS3_BEGIN_DATA32 + BS3_SET_BITS 32 +%endmacro + +%macro BS3_BEGIN_TEXT64 0-1 2 + %ifndef BS3_BEGIN_TEXT64_NOT_FIRST + %define BS3_BEGIN_TEXT64_NOT_FIRST + section BS3TEXT64 align=%1 CLASS=BS3CLASS64CODE PUBLIC USE32 FLAT + %else + section BS3TEXT64 + %endif + %undef BS3_CUR_SEG_BEGIN_MACRO + %xdefine BS3_CUR_SEG_BEGIN_MACRO BS3_BEGIN_TEXT64 + BS3_SET_BITS 64 +%endmacro + +%macro BS3_BEGIN_DATA64 0-1 16 + %ifndef BS3_BEGIN_DATA64_NOT_FIRST + %define BS3_BEGIN_DATA64_NOT_FIRST + section BS3DATA64 align=%1 CLASS=FAR_DATA PUBLIC USE32 ;FLAT (see DATA32) + %else + section BS3DATA64 + %endif + %undef BS3_CUR_SEG_BEGIN_MACRO + %xdefine BS3_CUR_SEG_BEGIN_MACRO BS3_BEGIN_DATA64 + BS3_SET_BITS 64 +%endmacro + +;; The system data segment containing the GDT, TSSes and IDTs. +%macro BS3_BEGIN_SYSTEM16 0-1 16 + %ifndef BS3_BEGIN_SYSTEM16_NOT_FIRST + %define BS3_BEGIN_SYSTEM16_NOT_FIRST + section BS3SYSTEM16 align=%1 CLASS=BS3SYSTEM16 PUBLIC USE16 + %else + section BS3SYSTEM16 + %endif + %undef BS3_CUR_SEG_BEGIN_MACRO + %xdefine BS3_CUR_SEG_BEGIN_MACRO BS3_BEGIN_SYSTEM16 + BS3_SET_BITS 16 +%endmacro + +;; Default text section. +%macro BS3_BEGIN_DEFAULT_TEXT 0 + %if ARCH_BITS == 16 + BS3_BEGIN_TEXT16 + %elif ARCH_BITS == 32 + BS3_BEGIN_TEXT32 + %elif ARCH_BITS == 64 + BS3_BEGIN_TEXT64 + %else + %error "ARCH_BITS must be defined as either 16, 32, or 64!" + INVALID_ARCH_BITS + %endif +%endmacro + +;; @} + + +; +; Now, ditch the default 'text' section and define our own NAME macro. +; +%ifndef ASM_FORMAT_BIN + BS3_BEGIN_DEFAULT_TEXT + BS3_BEGIN_DEFAULT_TEXT ; stupid nasm automagically repeats the segment attributes. +%endif + +;; When using watcom + OMF, we're using __cdecl by default, which +; get an underscore added in front. +%define NAME(name) _ %+ NAME_OVERLOAD(name) + + +; +; Include the standard headers from iprt. +; + + +%include "iprt/asmdefs.mac" +%include "iprt/x86.mac" + + +;; +; Extern macro which mangles the name using NAME(). +%macro EXTERN 1 + extern NAME(%1) +%endmacro + +;; +; Mangles a common name according to the current cpu bit count. +; @remarks Requires the use of the BS3_SET_BITS macro instead of the BITS directive. +%define BS3_CMN_NM(a_Name) BS3_NAME_UNDERSCORE %+ a_Name %+ _c %+ __BITS__ + +;; +; Extern macro which mangles the common name correctly, redefining the unmangled +; name to the mangled one for ease of use. +; +; @param %1 The unmangled common name. +; +; @remarks Must enter the segment in which this name is defined. +; +%macro BS3_EXTERN_CMN 1 + extern BS3_CMN_NM(%1) + %undef %1 + %define %1 BS3_CMN_NM(%1) +%endmacro + +;; +; Same as BS3_EXTERN_CMN except it picks the far variant in 16-bit code. +; +; @param %1 The unmangled common name. +; +; @remarks Must enter the segment in which this name is defined. +; +%macro BS3_EXTERN_CMN_FAR 1 + extern BS3_CMN_NM_FAR(%1) + %undef %1 + %define %1 BS3_CMN_NM_FAR(%1) +%endmacro + +;; @def BS3_EXTERN_TMPL +; Mangles the given name into a template specific one. For ease of use, the +; name is redefined to the mangled one, just like BS3_EXTERN_CMN does. +; @note Segment does not change. +%macro BS3_EXTERN_TMPL 1 + extern TMPL_NM(%1) + %undef %1 + %define %1 TMPL_NM(%1) +%endmacro + + +;; +; Mangles a 16-bit and 32-bit accessible data name. +; @remarks Requires the use of the BS3_SET_BITS macro instead of the BITS directive. +%define BS3_DATA_NM(a_Name) _ %+ a_Name + +;; +; Extern macro which mangles a DATA16 symbol correctly, redefining the +; unmangled name to the mangled one for ease of use. +; +; @param %1 The unmangled common name. +; +; @remarks Will change to the DATA16 segment, use must switch back afterwards! +; +%macro BS3_EXTERN_DATA16 1 + BS3_BEGIN_DATA16 + extern _ %+ %1 + %undef %1 + %define %1 _ %+ %1 +%endmacro + +;; +; Extern macro which mangles a BS3SYSTEM16 symbol correctly, redefining the +; unmangled name to the mangled one for ease of use. +; +; @param %1 The unmangled common name. +; +; @remarks Will change to the SYSTEM16 segment, use must switch back afterwards! +; +%macro BS3_EXTERN_SYSTEM16 1 + BS3_BEGIN_SYSTEM16 + extern _ %+ %1 + %undef %1 + %define %1 _ %+ %1 +%endmacro + + +;; +; Global name with ELF attributes and size. +; +; This differs from GLOBALNAME_EX in that it expects a mangled symbol name, +; and allows for nasm style symbol size expressions. +; +; @param %1 The mangled name. +; @param %2 Symbol attributes. +; @param %3 The size expression. +; +%macro BS3_GLOBAL_NAME_EX 3 +global %1 +%1: +%undef BS3_LAST_LABEL +%xdefine BS3_LAST_LABEL %1 +%endmacro + +;; +; Global local label. +; +; This should be used when switching segments and jumping to it via a local lable. +; It makes the lable visible to the debugger and map file. +; +%macro BS3_GLOBAL_LOCAL_LABEL 1 +global RT_CONCAT(BS3_LAST_LABEL,%1) +%1: +%endmacro + +;; +; Global data unmangled label. +; +; @param %1 The unmangled name. +; @param %2 The size (0 is fine). +; +%macro BS3_GLOBAL_DATA 2 +BS3_GLOBAL_NAME_EX BS3_DATA_NM(%1), , %2 +%endmacro + +;; +; Starts a procedure. +; +; This differs from BEGINPROC in that it expects a mangled symbol name and +; does the NASM symbol size stuff. +; +; @param %1 The mangled name. +; +%macro BS3_PROC_BEGIN 1 +BS3_GLOBAL_NAME_EX %1, function, (%1 %+ _EndProc - %1) +%endmacro + +;; +; Ends a procedure. +; +; Counter part to BS3_PROC_BEGIN. +; +; @param %1 The mangled name. +; +%macro BS3_PROC_END 1 +BS3_GLOBAL_NAME_EX %1 %+ _EndProc, function hidden, (%1 %+ _EndProc - %1) + int3 ; handy and avoids overlapping labels. +%endmacro + + +;; @name BS3_PBC_XXX - For use as the 2nd parameter to BS3_PROC_BEGIN_CMN and BS3_PROC_BEGIN_MODE. +;; @{ +%define BS3_PBC_NEAR 1 ;;< Only near. +%define BS3_PBC_FAR 2 ;;< Only far. +%define BS3_PBC_HYBRID 3 ;;< Hybrid near/far procedure, trashing AX. Use BS3_HYBRID_RET to return. +%define BS3_PBC_HYBRID_SAFE 4 ;;< Hybrid near/far procedure, no trashing but slower. Use BS3_HYBRID_RET to return. +%define BS3_PBC_HYBRID_0_ARGS 5 ;;< Hybrid near/far procedure, no parameters so separate far stub, no trashing, fast near calls. +;; @} + +;; Internal begin procedure macro. +; +; @param 1 The near name. +; @param 2 The far name +; @param 3 BS3_PBC_XXX. +%macro BS3_PROC_BEGIN_INT 3 + ;%warning "BS3_PROC_BEGIN_INT:" 1=%1 2=%2 3=%3 + %undef BS3_CUR_PROC_FLAGS + %if __BITS__ == 16 + %if %3 == BS3_PBC_NEAR + %xdefine BS3_CUR_PROC_FLAGS BS3_PBC_NEAR + %xdefine cbCurRetAddr 2 + BS3_PROC_BEGIN %1 + + %elif %3 == BS3_PBC_FAR + %xdefine BS3_CUR_PROC_FLAGS BS3_PBC_FAR + %xdefine cbCurRetAddr 4 + BS3_PROC_BEGIN %2 + + %elif %3 == BS3_PBC_HYBRID + %xdefine BS3_CUR_PROC_FLAGS BS3_PBC_HYBRID + %xdefine cbCurRetAddr 4 + BS3_GLOBAL_NAME_EX %1, function, 3 + pop ax + push cs + push ax + BS3_PROC_BEGIN %2 + + %elif %3 == BS3_PBC_HYBRID_SAFE + %xdefine BS3_CUR_PROC_FLAGS BS3_PBC_HYBRID_SAFE + %xdefine cbCurRetAddr 4 + BS3_GLOBAL_NAME_EX %1, function, 3 + extern Bs3CreateHybridFarRet_c16 + call Bs3CreateHybridFarRet_c16 + BS3_PROC_BEGIN %2 + + %elif %3 == BS3_PBC_HYBRID_0_ARGS + %xdefine BS3_CUR_PROC_FLAGS BS3_PBC_NEAR + %xdefine cbCurRetAddr 2 + %xdefine TMP_BEGIN_PREV_SEG BS3_CUR_SEG_BEGIN_MACRO + + BS3_BEGIN_TEXT16_FARSTUBS + BS3_PROC_BEGIN %2 + call %1 + retf + BS3_PROC_END %2 + + TMP_BEGIN_PREV_SEG + BS3_PROC_BEGIN %1 + %undef TMP_BEGIN_PREV_SEG + + %else + %error BS3_PROC_BEGIN_CMN parameter 2 value %3 is not recognized. + + %xdefine BS3_CUR_PROC_FLAGS BS3_PBC_NEAR + %xdefine cbCurRetAddr 4 + BS3_PROC_BEGIN %1 + %endif + %else + %xdefine BS3_CUR_PROC_FLAGS BS3_PBC_NEAR + %xdefine cbCurRetAddr xCB + BS3_PROC_BEGIN %1 + %endif +%endmacro + +;; Internal end procedure macro +; +; @param 1 The near name. +; @param 2 The far name +; +%macro BS3_PROC_END_INT 2 + %if __BITS__ == 16 + %if BS3_CUR_PROC_FLAGS == BS3_PBC_NEAR + BS3_PROC_END %1 + %else + BS3_PROC_END %2 + %endif + %else + BS3_PROC_END %1 + %endif + %undef BS3_CUR_PROC_FLAGS + %undef cbCurRetAddr +%endmacro + + +;; Convenience macro for defining common procedures. +; This will emit both near and far 16-bit symbols according to parameter %2 (BS3_PBC_XXX). +%macro BS3_PROC_BEGIN_CMN 2 + BS3_PROC_BEGIN_INT BS3_CMN_NM(%1), BS3_CMN_NM_FAR(%1), %2 +%endmacro + +;; Convenience macro for defining common procedures. +%macro BS3_PROC_END_CMN 1 + BS3_PROC_END_INT BS3_CMN_NM(%1), BS3_CMN_NM_FAR(%1) +%endmacro + +;; +; Generate a safe 16-bit far stub for function %1, shuffling %2 bytes of parameters. +; +; This does absolutely nothing in 32-bit and 64-bit mode. +; +; @param 1 The function basename. +; @param 2 The number of bytes of parameters on the stack, must be a multiple of 2. +; @remarks Changes the segment to TEXT16. +; +%macro BS3_CMN_FAR_STUB 2 + %if %2 <= 1 || (%2 & 1) + %error Invalid parameter frame size passed to BS3_CMN_FAR_STUB: %2 + %endif + %if __BITS__ == 16 +BS3_BEGIN_TEXT16_FARSTUBS +BS3_PROC_BEGIN_CMN %1, BS3_PBC_FAR + CPU 8086 + inc bp ; Odd bp is far call indicator. + push bp + mov bp, sp + %assign offParam %2 + %rep %2/2 + push word [bp + xCB + cbCurRetAddr + offParam - 2] + %assign offParam offParam - 2 + %endrep + call BS3_CMN_NM(%1) + add sp, %2 + pop bp + dec bp + retf +BS3_PROC_END_CMN %1 +BS3_BEGIN_TEXT16 + %endif +%endmacro + + +;; Convenience macro for defining mode specific procedures. +%macro BS3_PROC_BEGIN_MODE 2 + ;%warning "BS3_PROC_BEGIN_MODE: 1=" %1 "2=" %2 + BS3_PROC_BEGIN_INT TMPL_NM(%1), TMPL_FAR_NM(%1), %2 +%endmacro + +;; Convenience macro for defining mode specific procedures. +%macro BS3_PROC_END_MODE 1 + BS3_PROC_END_INT TMPL_NM(%1), TMPL_FAR_NM(%1) +%endmacro + +;; Does a far return in 16-bit code, near return in 32-bit and 64-bit. +; This is for use with BS3_PBC_XXX +%macro BS3_HYBRID_RET 0-1 + %if __BITS__ == 16 + %if %0 > 0 + %if BS3_CUR_PROC_FLAGS == BS3_PBC_NEAR || BS3_CUR_PROC_FLAGS == BS3_PBC_HYBRID_0_ARGS + ret %1 + %else + retf %1 + %endif + %else + %if BS3_CUR_PROC_FLAGS == BS3_PBC_NEAR || BS3_CUR_PROC_FLAGS == BS3_PBC_HYBRID_0_ARGS + ret + %else + retf + %endif + %endif + %else + %if BS3_CUR_PROC_FLAGS != BS3_PBC_NEAR + %error Expected BS3_CUR_PROC_FLAGS to be BS3_PBC_NEAR in non-16-bit code. + %endif + %if %0 > 0 + ret %1 + %else + ret + %endif + %endif +%endmacro + + +;; +; Prologue hacks for 64-bit code. +; +; This saves the four register parameters onto the stack so we can pretend +; the calling convention is stack based. The 64-bit calling convension is +; the microsoft one, so this is straight forward. +; +; Pairs with BS3_CALL_CONV_EPILOG. +; +; @param %1 The number of parameters. +; +; @remarks Must be invoked before any stack changing instructions are emitted. +; +%macro BS3_CALL_CONV_PROLOG 1 + %undef BS3_CALL_CONV_PROLOG_PARAMS + %define BS3_CALL_CONV_PROLOG_PARAMS %1 + %if __BITS__ == 64 + %if %1 >= 1 + mov [rsp + 008h], rcx + %elifdef BS3_STRICT + and qword [rsp + 008h], 1 + %endif + %if %1 >= 2 + mov [rsp + 010h], rdx + %elifdef BS3_STRICT + and qword [rsp + 010h], 2 + %endif + %if %1 >= 3 + mov [rsp + 018h], r8 + %elifdef BS3_STRICT + and qword [rsp + 018h], 3 + %endif + %if %1 >= 4 + mov [rsp + 020h], r9 + %elifdef BS3_STRICT + and qword [rsp + 020h], 4 + %endif + %endif +%endmacro + +;; +; Epilogue hacks for 64-bit code. +; +; Counter part to BS3_CALL_CONV_PROLOG. +; +; @param %1 The number of parameters. +; +; @remarks Must be invoked right before the return instruction as it uses RSP. +; +%macro BS3_CALL_CONV_EPILOG 1 + %if BS3_CALL_CONV_PROLOG_PARAMS != %1 + %error "BS3_CALL_CONV_EPILOG argument differs from BS3_CALL_CONV_PROLOG." + %endif + %if __BITS__ == 64 + %ifdef BS3_STRICT + mov dword [rsp + 008h], 31h + mov dword [rsp + 010h], 32h + mov dword [rsp + 018h], 33h + mov dword [rsp + 020h], 34h + %endif + %endif +%endmacro + +;; +; Wrapper for the call instruction that hides calling convension differences. +; +; This always calls %1. +; In 64-bit code, it will load up to 4 parameters into register. +; +; @param %1 The function to call (mangled). +; @param %2 The number of parameters. +; +%macro BS3_CALL 2 + %if __BITS__ == 64 + %if %2 >= 1 + mov rcx, [rsp] + %ifdef BS3_STRICT + and qword [rsp], 11h + %endif + %endif + %if %2 >= 2 + mov rdx, [rsp + 008h] + %ifdef BS3_STRICT + and qword [rsp + 008h], 12h + %endif + %endif + %if %2 >= 3 + mov r8, [rsp + 010h] + %ifdef BS3_STRICT + and qword [rsp + 010h], 13h + %endif + %endif + %if %2 >= 4 + mov r9, [rsp + 018h] + %ifdef BS3_STRICT + and qword [rsp + 018h], 14h + %endif + %endif + %endif + call %1 +%endmacro + + +;; @name Execution Modes +; @{ +%define BS3_MODE_INVALID 000h +%define BS3_MODE_RM 001h ;;< real mode. +%define BS3_MODE_PE16 011h ;;< 16-bit protected mode kernel+tss, running 16-bit code, unpaged. +%define BS3_MODE_PE16_32 012h ;;< 16-bit protected mode kernel+tss, running 32-bit code, unpaged. +%define BS3_MODE_PE16_V86 018h ;;< 16-bit protected mode kernel+tss, running virtual 8086 mode code, unpaged. +%define BS3_MODE_PE32 022h ;;< 32-bit protected mode kernel+tss, running 32-bit code, unpaged. +%define BS3_MODE_PE32_16 021h ;;< 32-bit protected mode kernel+tss, running 16-bit code, unpaged. +%define BS3_MODE_PEV86 028h ;;< 32-bit protected mode kernel+tss, running virtual 8086 mode code, unpaged. +%define BS3_MODE_PP16 031h ;;< 16-bit protected mode kernel+tss, running 16-bit code, paged. +%define BS3_MODE_PP16_32 032h ;;< 16-bit protected mode kernel+tss, running 32-bit code, paged. +%define BS3_MODE_PP16_V86 038h ;;< 16-bit protected mode kernel+tss, running virtual 8086 mode code, paged. +%define BS3_MODE_PP32 042h ;;< 32-bit protected mode kernel+tss, running 32-bit code, paged. +%define BS3_MODE_PP32_16 041h ;;< 32-bit protected mode kernel+tss, running 16-bit code, paged. +%define BS3_MODE_PPV86 048h ;;< 32-bit protected mode kernel+tss, running virtual 8086 mode code, paged. +%define BS3_MODE_PAE16 051h ;;< 16-bit protected mode kernel+tss, running 16-bit code, PAE paging. +%define BS3_MODE_PAE16_32 052h ;;< 16-bit protected mode kernel+tss, running 32-bit code, PAE paging. +%define BS3_MODE_PAE16_V86 058h ;;< 16-bit protected mode kernel+tss, running virtual 8086 mode, PAE paging. +%define BS3_MODE_PAE32 062h ;;< 32-bit protected mode kernel+tss, running 32-bit code, PAE paging. +%define BS3_MODE_PAE32_16 061h ;;< 32-bit protected mode kernel+tss, running 16-bit code, PAE paging. +%define BS3_MODE_PAEV86 068h ;;< 32-bit protected mode kernel+tss, running virtual 8086 mode, PAE paging. +%define BS3_MODE_LM16 071h ;;< 16-bit long mode (paged), kernel+tss always 64-bit. +%define BS3_MODE_LM32 072h ;;< 32-bit long mode (paged), kernel+tss always 64-bit. +%define BS3_MODE_LM64 074h ;;< 64-bit long mode (paged), kernel+tss always 64-bit. + +%define BS3_MODE_CODE_MASK 00fh ;;< Running code mask. +%define BS3_MODE_CODE_16 001h ;;< Running 16-bit code. +%define BS3_MODE_CODE_32 002h ;;< Running 32-bit code. +%define BS3_MODE_CODE_64 004h ;;< Running 64-bit code. +%define BS3_MODE_CODE_V86 008h ;;< Running 16-bit virtual 8086 code. + +%define BS3_MODE_SYS_MASK 0f0h ;;< kernel+tss mask. +%define BS3_MODE_SYS_RM 000h ;;< Real mode kernel+tss. +%define BS3_MODE_SYS_PE16 010h ;;< 16-bit protected mode kernel+tss. +%define BS3_MODE_SYS_PE32 020h ;;< 32-bit protected mode kernel+tss. +%define BS3_MODE_SYS_PP16 030h ;;< 16-bit paged protected mode kernel+tss. +%define BS3_MODE_SYS_PP32 040h ;;< 32-bit paged protected mode kernel+tss. +%define BS3_MODE_SYS_PAE16 050h ;;< 16-bit PAE paged protected mode kernel+tss. +%define BS3_MODE_SYS_PAE32 060h ;;< 32-bit PAE paged protected mode kernel+tss. +%define BS3_MODE_SYS_LM 070h ;;< 64-bit (paged) long mode protected mode kernel+tss. + +;; Whether the mode has paging enabled. +%define BS3_MODE_IS_PAGED(a_fMode) ((a_fMode) >= BS3_MODE_PP16) + +;; Whether the mode is running v8086 code. +%define BS3_MODE_IS_V86(a_fMode) (((a_fMode) & BS3_MODE_CODE_MASK) == BS3_MODE_CODE_V86) +;; Whether the we're executing in real mode or v8086 mode. +%define BS3_MODE_IS_RM_OR_V86(a_fMode) ((a_fMode) == BS3_MODE_RM || BS3_MODE_IS_V86(a_fMode)) +;; Whether the mode is running 16-bit code, except v8086. +%define BS3_MODE_IS_16BIT_CODE_NO_V86(a_fMode) (((a_fMode) & BS3_MODE_CODE_MASK) == BS3_MODE_CODE_16) +;; Whether the mode is running 16-bit code (includes v8086). +%define BS3_MODE_IS_16BIT_CODE(a_fMode) (BS3_MODE_IS_16BIT_CODE_NO_V86(a_fMode) || BS3_MODE_IS_V86(a_fMode)) +;; Whether the mode is running 32-bit code. +%define BS3_MODE_IS_32BIT_CODE(a_fMode) (((a_fMode) & BS3_MODE_CODE_MASK) == BS3_MODE_CODE_32) +;; Whether the mode is running 64-bit code. +%define BS3_MODE_IS_64BIT_CODE(a_fMode) (((a_fMode) & BS3_MODE_CODE_MASK) == BS3_MODE_CODE_64) + +;; Whether the system is in real mode. +%define BS3_MODE_IS_RM_SYS(a_fMode) (((a_fMode) & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_RM) +;; Whether the system is some 16-bit mode that isn't real mode. +%define BS3_MODE_IS_16BIT_SYS_NO_RM(a_fMode) ( ((a_fMode) & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PE16 \ + || ((a_fMode) & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PP16 \ + || ((a_fMode) & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PAE16) +;; Whether the system is some 16-bit mode (includes real mode). +%define BS3_MODE_IS_16BIT_SYS(a_fMode) (BS3_MODE_IS_16BIT_SYS_NO_RM(a_fMode) || BS3_MODE_IS_RM_SYS(a_fMode)) +;; Whether the system is some 32-bit mode. +%define BS3_MODE_IS_32BIT_SYS(a_fMode) ( ((a_fMode) & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PE32 \ + || ((a_fMode) & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PP32 \ + || ((a_fMode) & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_PAE32) +;; Whether the system is long mode. +%define BS3_MODE_IS_64BIT_SYS(a_fMode) (((a_fMode) & BS3_MODE_SYS_MASK) == BS3_MODE_SYS_LM) + +;; @} + +;; @name For mode specfic lookups: +;; %[BS3_MODE_NM %+ BS3_MODE_PE32](SomeBaseName) +;; %[BS3_MODE_LNAME_ %+ TMPL_MODE] +;; @{ +%define BS3_MODE_NM_001h(a_Name) _ %+ a_Name %+ _rm +%define BS3_MODE_NM_011h(a_Name) _ %+ a_Name %+ _pe16 +%define BS3_MODE_NM_012h(a_Name) _ %+ a_Name %+ _pe16_32 +%define BS3_MODE_NM_018h(a_Name) _ %+ a_Name %+ _pe16_v86 +%define BS3_MODE_NM_022h(a_Name) _ %+ a_Name %+ _pe32 +%define BS3_MODE_NM_021h(a_Name) _ %+ a_Name %+ _pe32_16 +%define BS3_MODE_NM_028h(a_Name) _ %+ a_Name %+ _pev86 +%define BS3_MODE_NM_031h(a_Name) _ %+ a_Name %+ _pp16 +%define BS3_MODE_NM_032h(a_Name) _ %+ a_Name %+ _pp16_32 +%define BS3_MODE_NM_038h(a_Name) _ %+ a_Name %+ _pp16_v86 +%define BS3_MODE_NM_042h(a_Name) _ %+ a_Name %+ _pp32 +%define BS3_MODE_NM_041h(a_Name) _ %+ a_Name %+ _pp32_16 +%define BS3_MODE_NM_048h(a_Name) _ %+ a_Name %+ _ppv86 +%define BS3_MODE_NM_051h(a_Name) _ %+ a_Name %+ _pae16 +%define BS3_MODE_NM_052h(a_Name) _ %+ a_Name %+ _pae16_32 +%define BS3_MODE_NM_058h(a_Name) _ %+ a_Name %+ _pae16_v86 +%define BS3_MODE_NM_062h(a_Name) _ %+ a_Name %+ _pae32 +%define BS3_MODE_NM_061h(a_Name) _ %+ a_Name %+ _pae32_16 +%define BS3_MODE_NM_068h(a_Name) _ %+ a_Name %+ _paev86 +%define BS3_MODE_NM_071h(a_Name) _ %+ a_Name %+ _lm16 +%define BS3_MODE_NM_072h(a_Name) _ %+ a_Name %+ _lm32 +%define BS3_MODE_NM_074h(a_Name) _ %+ a_Name %+ _lm64 + +%define BS3_MODE_LNAME_001h rm +%define BS3_MODE_LNAME_011h pe16 +%define BS3_MODE_LNAME_012h pe16_32 +%define BS3_MODE_LNAME_018h pe16_v86 +%define BS3_MODE_LNAME_022h pe32 +%define BS3_MODE_LNAME_021h pe32_16 +%define BS3_MODE_LNAME_028h pev86 +%define BS3_MODE_LNAME_031h pp16 +%define BS3_MODE_LNAME_032h pp16_32 +%define BS3_MODE_LNAME_038h pp16_v86 +%define BS3_MODE_LNAME_042h pp32 +%define BS3_MODE_LNAME_041h pp32_16 +%define BS3_MODE_LNAME_048h ppv86 +%define BS3_MODE_LNAME_051h pae16 +%define BS3_MODE_LNAME_052h pae16_32 +%define BS3_MODE_LNAME_058h pae16_v86 +%define BS3_MODE_LNAME_062h pae32 +%define BS3_MODE_LNAME_061h pae32_16 +%define BS3_MODE_LNAME_068h paev86 +%define BS3_MODE_LNAME_071h lm16 +%define BS3_MODE_LNAME_072h lm32 +%define BS3_MODE_LNAME_074h lm64 + +%define BS3_MODE_UNAME_001h RM +%define BS3_MODE_UNAME_011h PE16 +%define BS3_MODE_UNAME_012h PE16_32 +%define BS3_MODE_UNAME_018h PE16_V86 +%define BS3_MODE_UNAME_022h PE32 +%define BS3_MODE_UNAME_021h PE32_16 +%define BS3_MODE_UNAME_028h PEV86 +%define BS3_MODE_UNAME_031h PP16 +%define BS3_MODE_UNAME_032h PP16_32 +%define BS3_MODE_UNAME_038h PP16_V86 +%define BS3_MODE_UNAME_042h PP32 +%define BS3_MODE_UNAME_041h PP32_16 +%define BS3_MODE_UNAME_048h PPV86 +%define BS3_MODE_UNAME_051h PAE16 +%define BS3_MODE_UNAME_052h PAE16_32 +%define BS3_MODE_UNAME_058h PAE16_V86 +%define BS3_MODE_UNAME_062h PAE32 +%define BS3_MODE_UNAME_061h PAE32_16 +%define BS3_MODE_UNAME_068h PAEV86 +%define BS3_MODE_UNAME_071h LM16 +%define BS3_MODE_UNAME_072h LM32 +%define BS3_MODE_UNAME_074h LM64 + +%define BS3_MODE_UNDERSCORE_001h _ +%define BS3_MODE_UNDERSCORE_011h _ +%define BS3_MODE_UNDERSCORE_012h _ +%define BS3_MODE_UNDERSCORE_018h _ +%define BS3_MODE_UNDERSCORE_022h _ +%define BS3_MODE_UNDERSCORE_021h _ +%define BS3_MODE_UNDERSCORE_028h _ +%define BS3_MODE_UNDERSCORE_031h _ +%define BS3_MODE_UNDERSCORE_032h _ +%define BS3_MODE_UNDERSCORE_038h _ +%define BS3_MODE_UNDERSCORE_042h _ +%define BS3_MODE_UNDERSCORE_041h _ +%define BS3_MODE_UNDERSCORE_048h _ +%define BS3_MODE_UNDERSCORE_051h _ +%define BS3_MODE_UNDERSCORE_052h _ +%define BS3_MODE_UNDERSCORE_058h _ +%define BS3_MODE_UNDERSCORE_062h _ +%define BS3_MODE_UNDERSCORE_061h _ +%define BS3_MODE_UNDERSCORE_068h _ +%define BS3_MODE_UNDERSCORE_071h _ +%define BS3_MODE_UNDERSCORE_072h _ +%define BS3_MODE_UNDERSCORE_074h _ + +%define BS3_MODE_CNAME_001h c16 +%define BS3_MODE_CNAME_011h c16 +%define BS3_MODE_CNAME_012h c32 +%define BS3_MODE_CNAME_018h c16 +%define BS3_MODE_CNAME_022h c32 +%define BS3_MODE_CNAME_021h c16 +%define BS3_MODE_CNAME_028h c16 +%define BS3_MODE_CNAME_031h c16 +%define BS3_MODE_CNAME_032h c32 +%define BS3_MODE_CNAME_038h c16 +%define BS3_MODE_CNAME_042h c32 +%define BS3_MODE_CNAME_041h c16 +%define BS3_MODE_CNAME_048h c16 +%define BS3_MODE_CNAME_051h c16 +%define BS3_MODE_CNAME_052h c32 +%define BS3_MODE_CNAME_058h c16 +%define BS3_MODE_CNAME_062h c32 +%define BS3_MODE_CNAME_061h c16 +%define BS3_MODE_CNAME_068h c16 +%define BS3_MODE_CNAME_071h c16 +%define BS3_MODE_CNAME_072h c32 +%define BS3_MODE_CNAME_074h c64 +;; @} + +;; @name For getting the ring-0 mode for v86 modes: %[BS3_MODE_R0_NM_001h %+ TMPL_MODE](Bs3SwitchToRM) +;; @{ +%define BS3_MODE_R0_NM_001h(a_Name) _ %+ a_Name %+ _rm +%define BS3_MODE_R0_NM_011h(a_Name) _ %+ a_Name %+ _pe16 +%define BS3_MODE_R0_NM_012h(a_Name) _ %+ a_Name %+ _pe16_32 +%define BS3_MODE_R0_NM_018h(a_Name) _ %+ a_Name %+ _pe16 +%define BS3_MODE_R0_NM_022h(a_Name) _ %+ a_Name %+ _pe32 +%define BS3_MODE_R0_NM_021h(a_Name) _ %+ a_Name %+ _pe32_16 +%define BS3_MODE_R0_NM_028h(a_Name) _ %+ a_Name %+ _pe32_16 +%define BS3_MODE_R0_NM_031h(a_Name) _ %+ a_Name %+ _pp16 +%define BS3_MODE_R0_NM_032h(a_Name) _ %+ a_Name %+ _pp16_32 +%define BS3_MODE_R0_NM_038h(a_Name) _ %+ a_Name %+ _pp16 +%define BS3_MODE_R0_NM_042h(a_Name) _ %+ a_Name %+ _pp32 +%define BS3_MODE_R0_NM_041h(a_Name) _ %+ a_Name %+ _pp32_16 +%define BS3_MODE_R0_NM_048h(a_Name) _ %+ a_Name %+ _pp32_16 +%define BS3_MODE_R0_NM_051h(a_Name) _ %+ a_Name %+ _pae16 +%define BS3_MODE_R0_NM_052h(a_Name) _ %+ a_Name %+ _pae16_32 +%define BS3_MODE_R0_NM_058h(a_Name) _ %+ a_Name %+ _pae16 +%define BS3_MODE_R0_NM_062h(a_Name) _ %+ a_Name %+ _pae32 +%define BS3_MODE_R0_NM_061h(a_Name) _ %+ a_Name %+ _pae32_16 +%define BS3_MODE_R0_NM_068h(a_Name) _ %+ a_Name %+ _pae32_16 +%define BS3_MODE_R0_NM_071h(a_Name) _ %+ a_Name %+ _lm16 +%define BS3_MODE_R0_NM_072h(a_Name) _ %+ a_Name %+ _lm32 +%define BS3_MODE_R0_NM_074h(a_Name) _ %+ a_Name %+ _lm64 +;; @} + + +;; +; Includes the file %1 with TMPL_MODE set to all possible value. +; @param 1 Double quoted include file name. +%macro BS3_INSTANTIATE_TEMPLATE_WITH_WEIRD_ONES 1 + %define BS3_INSTANTIATING_MODE + %define BS3_INSTANTIATING_ALL_MODES + + %define TMPL_MODE BS3_MODE_RM + %include %1 + + %define TMPL_MODE BS3_MODE_PE16 + %include %1 + %define TMPL_MODE BS3_MODE_PE16_32 + %include %1 + %define TMPL_MODE BS3_MODE_PE16_V86 + %include %1 + + %define TMPL_MODE BS3_MODE_PE32 + %include %1 + %define TMPL_MODE BS3_MODE_PE32_16 + %include %1 + %define TMPL_MODE BS3_MODE_PEV86 + %include %1 + + %define TMPL_MODE BS3_MODE_PP16 + %include %1 + %define TMPL_MODE BS3_MODE_PP16_32 + %include %1 + %define TMPL_MODE BS3_MODE_PP16_V86 + %include %1 + + %define TMPL_MODE BS3_MODE_PP32 + %include %1 + %define TMPL_MODE BS3_MODE_PP32_16 + %include %1 + %define TMPL_MODE BS3_MODE_PPV86 + %include %1 + + %define TMPL_MODE BS3_MODE_PAE16 + %include %1 + %define TMPL_MODE BS3_MODE_PAE16_32 + %include %1 + %define TMPL_MODE BS3_MODE_PAE16_V86 + %include %1 + + %define TMPL_MODE BS3_MODE_PAE32 + %include %1 + %define TMPL_MODE BS3_MODE_PAE32_16 + %include %1 + %define TMPL_MODE BS3_MODE_PAEV86 + %include %1 + + %define TMPL_MODE BS3_MODE_LM16 + %include %1 + %define TMPL_MODE BS3_MODE_LM32 + %include %1 + %define TMPL_MODE BS3_MODE_LM64 + %include %1 + + %undef BS3_INSTANTIATING_MODE + %undef BS3_INSTANTIATING_ALL_MODES +%endmacro + + +;; +; Includes the file %1 with TMPL_MODE set to all but the "weird" value. +; @param 1 Double quoted include file name. +%macro BS3_INSTANTIATE_TEMPLATE_ESSENTIALS 1 + %define BS3_INSTANTIATING_MODE + %define BS3_INSTANTIATING_ESSENTIAL_MODES + + %define TMPL_MODE BS3_MODE_RM + %include %1 + + %define TMPL_MODE BS3_MODE_PE16 + %include %1 + + %define TMPL_MODE BS3_MODE_PE32 + %include %1 + %define TMPL_MODE BS3_MODE_PEV86 + %include %1 + + %define TMPL_MODE BS3_MODE_PP16 + %include %1 + + %define TMPL_MODE BS3_MODE_PP32 + %include %1 + %define TMPL_MODE BS3_MODE_PPV86 + %include %1 + + %define TMPL_MODE BS3_MODE_PAE16 + %include %1 + + %define TMPL_MODE BS3_MODE_PAE32 + %include %1 + %define TMPL_MODE BS3_MODE_PAEV86 + %include %1 + + %define TMPL_MODE BS3_MODE_LM16 + %include %1 + %define TMPL_MODE BS3_MODE_LM32 + %include %1 + %define TMPL_MODE BS3_MODE_LM64 + %include %1 + + %undef BS3_INSTANTIATING_MODE + %undef BS3_INSTANTIATING_ESSENTIAL_MODES +%endmacro + +;; +; Includes the file %1 with TMPL_MODE set to a 16-bit, a 32-bit and a 64-bit value. +; @param 1 Double quoted include file name. +%macro BS3_INSTANTIATE_COMMON_TEMPLATE 1 + %define BS3_INSTANTIATING_CMN + + %define TMPL_MODE BS3_MODE_RM + %include %1 + %define TMPL_MODE BS3_MODE_PE32 + %include %1 + %define TMPL_MODE BS3_MODE_LM64 + %include %1 + + %undef BS3_INSTANTIATING_CMN +%endmacro + + +;; @name Static Memory Allocation +; @{ +;; The flat load address for the code after the bootsector. +%define BS3_ADDR_LOAD 010000h +;; Where we save the boot registers during init. +; Located right before the code. +%define BS3_ADDR_REG_SAVE (BS3_ADDR_LOAD - BS3REGCTX_size - 8) +;; Where the stack starts (initial RSP value). +; Located 16 bytes (assumed by boot sector) before the saved registers. SS.BASE=0. +%define BS3_ADDR_STACK (BS3_ADDR_REG_SAVE - 16) +;; The ring-0 stack (8KB) for ring transitions. +%define BS3_ADDR_STACK_R0 006000h +;; The ring-1 stack (8KB) for ring transitions. +%define BS3_ADDR_STACK_R1 004000h +;; The ring-2 stack (8KB) for ring transitions. +%define BS3_ADDR_STACK_R2 002000h +;; IST1 ring-0 stack for long mode (4KB), used for double faults elsewhere. +%define BS3_ADDR_STACK_R0_IST1 009000h +;; IST2 ring-0 stack for long mode (3KB), used for spare 0 stack elsewhere. +%define BS3_ADDR_STACK_R0_IST2 008000h +;; IST3 ring-0 stack for long mode (1KB). +%define BS3_ADDR_STACK_R0_IST3 007400h +;; IST4 ring-0 stack for long mode (1KB), used for spare 1 stack elsewhere. +%define BS3_ADDR_STACK_R0_IST4 007000h +;; IST5 ring-0 stack for long mode (1KB). +%define BS3_ADDR_STACK_R0_IST5 006c00h +;; IST6 ring-0 stack for long mode (1KB). +%define BS3_ADDR_STACK_R0_IST6 006800h +;; IST7 ring-0 stack for long mode (1KB). +%define BS3_ADDR_STACK_R0_IST7 006400h + +;; The base address of the BS3TEXT16 segment (same as BS3_LOAD_ADDR). +;; @sa BS3_SEL_TEXT16 +%define BS3_ADDR_BS3TEXT16 010000h +;; The base address of the BS3SYSTEM16 segment. +;; @sa BS3_SEL_SYSTEM16 +%define BS3_ADDR_BS3SYSTEM16 020000h +;; The base address of the BS3DATA16/BS3KIT_GRPNM_DATA16 segment. +;; @sa BS3_SEL_DATA16 +%define BS3_ADDR_BS3DATA16 029000h +;; @} + + +;; +; BS3 register context. Used by traps and such. +; +struc BS3REGCTX + .rax resq 1 ; BS3REG rax; /**< 0x00 */ + .rcx resq 1 ; BS3REG rcx; /**< 0x08 */ + .rdx resq 1 ; BS3REG rdx; /**< 0x10 */ + .rbx resq 1 ; BS3REG rbx; /**< 0x18 */ + .rsp resq 1 ; BS3REG rsp; /**< 0x20 */ + .rbp resq 1 ; BS3REG rbp; /**< 0x28 */ + .rsi resq 1 ; BS3REG rsi; /**< 0x30 */ + .rdi resq 1 ; BS3REG rdi; /**< 0x38 */ + .r8 resq 1 ; BS3REG r8; /**< 0x40 */ + .r9 resq 1 ; BS3REG r9; /**< 0x48 */ + .r10 resq 1 ; BS3REG r10; /**< 0x50 */ + .r11 resq 1 ; BS3REG r11; /**< 0x58 */ + .r12 resq 1 ; BS3REG r12; /**< 0x60 */ + .r13 resq 1 ; BS3REG r13; /**< 0x68 */ + .r14 resq 1 ; BS3REG r14; /**< 0x70 */ + .r15 resq 1 ; BS3REG r15; /**< 0x78 */ + .rflags resq 1 ; BS3REG rflags; /**< 0x80 */ + .rip resq 1 ; BS3REG rip; /**< 0x88 */ + .cs resw 1 ; uint16_t cs; /**< 0x90 */ + .ds resw 1 ; uint16_t ds; /**< 0x92 */ + .es resw 1 ; uint16_t es; /**< 0x94 */ + .fs resw 1 ; uint16_t fs; /**< 0x96 */ + .gs resw 1 ; uint16_t gs; /**< 0x98 */ + .ss resw 1 ; uint16_t ss; /**< 0x9a */ + .tr resw 1 ; uint16_t tr; /**< 0x9c */ + .ldtr resw 1 ; uint16_t ldtr; /**< 0x9e */ + .bMode resb 1 ; uint8_t bMode; /**< 0xa0: BS3_MODE_XXX. */ + .bCpl resb 1 ; uint8_t bCpl; /**< 0xa1: 0-3, 0 is used for real mode. */ + .fbFlags resb 1 ; uint8_t fbFlags; /**< 0xa2: BS3REG_CTX_F_XXX */ + .abPadding resb 5 ; uint8_t abPadding[5]; /**< 0xa4 */ + .cr0 resq 1 ; BS3REG cr0; /**< 0xa8 */ + .cr2 resq 1 ; BS3REG cr2; /**< 0xb0 */ + .cr3 resq 1 ; BS3REG cr3; /**< 0xb8 */ + .cr4 resq 1 ; BS3REG cr4; /**< 0xc0 */ + .uUnused resq 1 ; BS3REG uUnused; /**< 0xc8 */ +endstruc +AssertCompileSize(BS3REGCTX, 0xd0) + +;; @name BS3REG_CTX_F_XXX - BS3REGCTX::fbFlags masks. +; @{ +;; The CR0 is MSW (only low 16-bit). */ +%define BS3REG_CTX_F_NO_CR0_IS_MSW 0x01 +;; No CR2 and CR3 values. Not in CPL 0 or CPU too old for CR2 & CR3. +%define BS3REG_CTX_F_NO_CR2_CR3 0x02 +;; No CR4 value. The CPU is too old for CR4. +%define BS3REG_CTX_F_NO_CR4 0x04 +;; No TR and LDTR values. Context gathered in real mode or v8086 mode. +%define BS3REG_CTX_F_NO_TR_LDTR 0x08 +;; The context doesn't have valid values for AMD64 GPR extensions. +%define BS3REG_CTX_F_NO_AMD64 0x10 +;; @} + + +;; @name Flags for Bs3RegCtxRestore +; @{ +;; Skip restoring the CRx registers. +%define BS3REGCTXRESTORE_F_SKIP_CRX 1 +;; Sets g_fBs3TrapNoV86Assist. +%define BS3REGCTXRESTORE_F_NO_V86_ASSIST 2 +;; @} + + +;; +; BS3 extended register context (FPU, SSE, AVX, ++) +; +struc BS3EXTCTX + .u16Magic resw 1 ; uint16_t u16Magic; + .cb resw 1 ; uint16_t cb; + .enmMethod resb 1 ; uint8_t enmMethod; + alignb 8 + .fXcr0Nominal resq 1 ; uint64_t fXcr0Nominal; + .fXcr0Saved resq 1 ; uint64_t fXcr0Saved; + alignb 64 + .Ctx resb 512 +endstruc +%define BS3EXTCTXMETHOD_ANCIENT 1 +%define BS3EXTCTXMETHOD_FXSAVE 2 +%define BS3EXTCTXMETHOD_XSAVE 3 + +;; +; BS3 Trap Frame. +; +struc BS3TRAPFRAME + .bXcpt resb 1 + .cbIretFrame resb 1 + .uHandlerCs resw 1 + .uHandlerSs resw 1 + .usAlignment resw 1 + .uHandlerRsp resq 1 + .fHandlerRfl resq 1 + .uErrCd resq 1 + .Ctx resb BS3REGCTX_size +endstruc +AssertCompileSize(BS3TRAPFRAME, 0x20 + 0xd0) + +;; +; Trap record. +; +struc BS3TRAPREC + ;; The trap location relative to the base address given at + ; registration time. + .offWhere resd 1 + ;; What to add to .offWhere to calculate the resume address. + .offResumeAddend resb 1 + ;; The trap number. + .u8TrapNo resb 1 + ;; The error code if the trap takes one. + .u16ErrCd resw 1 +endstruc + +;; The size shift. +%define BS3TRAPREC_SIZE_SHIFT 3 + + +;; The system call vector. +%define BS3_TRAP_SYSCALL 20h + +;; @name System call numbers (ax) +;; @note Pointers are always passed in cx:xDI. +;; @{ +;; Print char (cl). +%define BS3_SYSCALL_PRINT_CHR 0001h +;; Print string (pointer in cx:xDI, length in xDX). +%define BS3_SYSCALL_PRINT_STR 0002h +;; Switch to ring-0. +%define BS3_SYSCALL_TO_RING0 0003h +;; Switch to ring-1. +%define BS3_SYSCALL_TO_RING1 0004h +;; Switch to ring-2. +%define BS3_SYSCALL_TO_RING2 0005h +;; Switch to ring-3. +%define BS3_SYSCALL_TO_RING3 0006h +;; Restore context (pointer in cx:xDI, flags in dx). +%define BS3_SYSCALL_RESTORE_CTX 0007h +;; Set DRx register (value in ESI, register number in dl). +%define BS3_SYSCALL_SET_DRX 0008h +;; GET DRx register (register number in dl, value returned in ax:dx). +%define BS3_SYSCALL_GET_DRX 0009h +;; Set CRx register (value in ESI, register number in dl). +%define BS3_SYSCALL_SET_CRX 000ah +;; Get CRx register (register number in dl, value returned in ax:dx). +%define BS3_SYSCALL_GET_CRX 000bh +;; Set the task register (value in dx). */ +%define BS3_SYSCALL_SET_TR 000ch +;; Get the task register (value returned in ax). +%define BS3_SYSCALL_GET_TR 000dh +;; Set the LDT register (value in dx). +%define BS3_SYSCALL_SET_LDTR 000eh +;; Get the LDT register (value returned in ax). +%define BS3_SYSCALL_GET_LDTR 000fh +;; Set XCR0 register (value in edx:esi). +%define BS3_SYSCALL_SET_XCR0 0010h +;; Get XCR0 register (value returned in edx:eax). +%define BS3_SYSCALL_GET_XCR0 0011h +;; The last system call value. +%define BS3_SYSCALL_LAST BS3_SYSCALL_GET_XCR0 +;; @} + + + +;; @name BS3_SEL_XXX - GDT selectors +;; @{ + +%define BS3_SEL_LDT 0010h ;;< The LDT selector (requires setting up). +%define BS3_SEL_TSS16 0020h ;;< The 16-bit TSS selector. +%define BS3_SEL_TSS16_DF 0028h ;;< The 16-bit TSS selector for double faults. +%define BS3_SEL_TSS16_SPARE0 0030h ;;< The 16-bit TSS selector for testing. +%define BS3_SEL_TSS16_SPARE1 0038h ;;< The 16-bit TSS selector for testing. +%define BS3_SEL_TSS32 0040h ;;< The 32-bit TSS selector. +%define BS3_SEL_TSS32_DF 0048h ;;< The 32-bit TSS selector for double faults. +%define BS3_SEL_TSS32_SPARE0 0050h ;;< The 32-bit TSS selector for testing. +%define BS3_SEL_TSS32_SPARE1 0058h ;;< The 32-bit TSS selector for testing. +%define BS3_SEL_TSS32_IOBP_IRB 0060h ;;< The 32-bit TSS selector with I/O permission and interrupt redirection bitmaps. +%define BS3_SEL_TSS32_IRB 0068h ;;< The 32-bit TSS selector with only interrupt redirection bitmap (IOPB stripped by limit). +%define BS3_SEL_TSS64 0070h ;;< The 64-bit TSS selector. +%define BS3_SEL_TSS64_SPARE0 0080h ;;< The 64-bit TSS selector. +%define BS3_SEL_TSS64_SPARE1 0090h ;;< The 64-bit TSS selector. +%define BS3_SEL_TSS64_IOBP 00a0h ;;< The 64-bit TSS selector. + +%define BS3_SEL_RMTEXT16_CS 00e0h ;;< Conforming code selector for accessing the BS3RMTEXT16 segment. Runtime config. +%define BS3_SEL_X0TEXT16_CS 00e8h ;;< Conforming code selector for accessing the BS3X0TEXT16 segment. Runtime config. +%define BS3_SEL_X1TEXT16_CS 00f0h ;;< Conforming code selector for accessing the BS3X1TEXT16 segment. Runtime config. +%define BS3_SEL_VMMDEV_MMIO16 00f8h ;;< Selector for accessing the VMMDev MMIO segment at 0100000h from 16-bit code. + +%define BS3_SEL_RING_SHIFT 8 ;;< For the formula: BS3_SEL_R0_XXX + ((cs & 3) << BS3_SEL_RING_SHIFT) + +%define BS3_SEL_R0_FIRST 0100h ;;< The first selector in the ring-0 block. +%define BS3_SEL_R0_CS16 0100h ;;< ring-0: 16-bit code selector, base 0x10000. +%define BS3_SEL_R0_DS16 0108h ;;< ring-0: 16-bit data selector, base 0x23000. +%define BS3_SEL_R0_SS16 0110h ;;< ring-0: 16-bit stack selector, base 0x00000. +%define BS3_SEL_R0_CS32 0118h ;;< ring-0: 32-bit flat code selector. +%define BS3_SEL_R0_DS32 0120h ;;< ring-0: 32-bit flat data selector. +%define BS3_SEL_R0_SS32 0128h ;;< ring-0: 32-bit flat stack selector. +%define BS3_SEL_R0_CS64 0130h ;;< ring-0: 64-bit flat code selector. +%define BS3_SEL_R0_DS64 0138h ;;< ring-0: 64-bit flat data & stack selector. +%define BS3_SEL_R0_CS16_EO 0140h ;;< ring-0: 16-bit execute-only code selector, not accessed, 0xfffe limit, CS16 base. +%define BS3_SEL_R0_CS16_CNF 0148h ;;< ring-0: 16-bit conforming code selector, not accessed, 0xfffe limit, CS16 base. +%define BS3_SEL_R0_CS16_CNF_EO 0150h ;;< ring-0: 16-bit execute-only conforming code selector, not accessed, 0xfffe limit, CS16 base. +%define BS3_SEL_R0_CS32_EO 0158h ;;< ring-0: 32-bit execute-only code selector, not accessed, flat. +%define BS3_SEL_R0_CS32_CNF 0160h ;;< ring-0: 32-bit conforming code selector, not accessed, flat. +%define BS3_SEL_R0_CS32_CNF_EO 0168h ;;< ring-0: 32-bit execute-only conforming code selector, not accessed, flat. +%define BS3_SEL_R0_CS64_EO 0170h ;;< ring-0: 64-bit execute-only code selector, not accessed, flat. +%define BS3_SEL_R0_CS64_CNF 0178h ;;< ring-0: 64-bit conforming code selector, not accessed, flat. +%define BS3_SEL_R0_CS64_CNF_EO 0180h ;;< ring-0: 64-bit execute-only conforming code selector, not accessed, flat. + +%define BS3_SEL_R1_FIRST 0200h ;;< The first selector in the ring-1 block. +%define BS3_SEL_R1_CS16 0200h ;;< ring-1: 16-bit code selector, base 0x10000. +%define BS3_SEL_R1_DS16 0208h ;;< ring-1: 16-bit data selector, base 0x23000. +%define BS3_SEL_R1_SS16 0210h ;;< ring-1: 16-bit stack selector, base 0x00000. +%define BS3_SEL_R1_CS32 0218h ;;< ring-1: 32-bit flat code selector. +%define BS3_SEL_R1_DS32 0220h ;;< ring-1: 32-bit flat data selector. +%define BS3_SEL_R1_SS32 0228h ;;< ring-1: 32-bit flat stack selector. +%define BS3_SEL_R1_CS64 0230h ;;< ring-1: 64-bit flat code selector. +%define BS3_SEL_R1_DS64 0238h ;;< ring-1: 64-bit flat data & stack selector. +%define BS3_SEL_R1_CS16_EO 0240h ;;< ring-1: 16-bit execute-only code selector, not accessed, 0xfffe limit, CS16 base. +%define BS3_SEL_R1_CS16_CNF 0248h ;;< ring-1: 16-bit conforming code selector, not accessed, 0xfffe limit, CS16 base. +%define BS3_SEL_R1_CS16_CNF_EO 0250h ;;< ring-1: 16-bit execute-only conforming code selector, not accessed, 0xfffe limit, CS16 base. +%define BS3_SEL_R1_CS32_EO 0258h ;;< ring-1: 32-bit execute-only code selector, not accessed, flat. +%define BS3_SEL_R1_CS32_CNF 0260h ;;< ring-1: 32-bit conforming code selector, not accessed, flat. +%define BS3_SEL_R1_CS32_CNF_EO 0268h ;;< ring-1: 32-bit execute-only conforming code selector, not accessed, flat. +%define BS3_SEL_R1_CS64_EO 0270h ;;< ring-1: 64-bit execute-only code selector, not accessed, flat. +%define BS3_SEL_R1_CS64_CNF 0278h ;;< ring-1: 64-bit conforming code selector, not accessed, flat. +%define BS3_SEL_R1_CS64_CNF_EO 0280h ;;< ring-1: 64-bit execute-only conforming code selector, not accessed, flat. + +%define BS3_SEL_R2_FIRST 0300h ;;< The first selector in the ring-2 block. +%define BS3_SEL_R2_CS16 0300h ;;< ring-2: 16-bit code selector, base 0x10000. +%define BS3_SEL_R2_DS16 0308h ;;< ring-2: 16-bit data selector, base 0x23000. +%define BS3_SEL_R2_SS16 0310h ;;< ring-2: 16-bit stack selector, base 0x00000. +%define BS3_SEL_R2_CS32 0318h ;;< ring-2: 32-bit flat code selector. +%define BS3_SEL_R2_DS32 0320h ;;< ring-2: 32-bit flat data selector. +%define BS3_SEL_R2_SS32 0328h ;;< ring-2: 32-bit flat stack selector. +%define BS3_SEL_R2_CS64 0330h ;;< ring-2: 64-bit flat code selector. +%define BS3_SEL_R2_DS64 0338h ;;< ring-2: 64-bit flat data & stack selector. +%define BS3_SEL_R2_CS16_EO 0340h ;;< ring-2: 16-bit execute-only code selector, not accessed, 0xfffe limit, CS16 base. +%define BS3_SEL_R2_CS16_CNF 0348h ;;< ring-2: 16-bit conforming code selector, not accessed, 0xfffe limit, CS16 base. +%define BS3_SEL_R2_CS16_CNF_EO 0350h ;;< ring-2: 16-bit execute-only conforming code selector, not accessed, 0xfffe limit, CS16 base. +%define BS3_SEL_R2_CS32_EO 0358h ;;< ring-2: 32-bit execute-only code selector, not accessed, flat. +%define BS3_SEL_R2_CS32_CNF 0360h ;;< ring-2: 32-bit conforming code selector, not accessed, flat. +%define BS3_SEL_R2_CS32_CNF_EO 0368h ;;< ring-2: 32-bit execute-only conforming code selector, not accessed, flat. +%define BS3_SEL_R2_CS64_EO 0370h ;;< ring-2: 64-bit execute-only code selector, not accessed, flat. +%define BS3_SEL_R2_CS64_CNF 0378h ;;< ring-2: 64-bit conforming code selector, not accessed, flat. +%define BS3_SEL_R2_CS64_CNF_EO 0380h ;;< ring-2: 64-bit execute-only conforming code selector, not accessed, flat. + +%define BS3_SEL_R3_FIRST 0400h ;;< The first selector in the ring-3 block. +%define BS3_SEL_R3_CS16 0400h ;;< ring-3: 16-bit code selector, base 0x10000. +%define BS3_SEL_R3_DS16 0408h ;;< ring-3: 16-bit data selector, base 0x23000. +%define BS3_SEL_R3_SS16 0410h ;;< ring-3: 16-bit stack selector, base 0x00000. +%define BS3_SEL_R3_CS32 0418h ;;< ring-3: 32-bit flat code selector. +%define BS3_SEL_R3_DS32 0420h ;;< ring-3: 32-bit flat data selector. +%define BS3_SEL_R3_SS32 0428h ;;< ring-3: 32-bit flat stack selector. +%define BS3_SEL_R3_CS64 0430h ;;< ring-3: 64-bit flat code selector. +%define BS3_SEL_R3_DS64 0438h ;;< ring-3: 64-bit flat data & stack selector. +%define BS3_SEL_R3_CS16_EO 0440h ;;< ring-3: 16-bit execute-only code selector, not accessed, 0xfffe limit, CS16 base. +%define BS3_SEL_R3_CS16_CNF 0448h ;;< ring-3: 16-bit conforming code selector, not accessed, 0xfffe limit, CS16 base. +%define BS3_SEL_R3_CS16_CNF_EO 0450h ;;< ring-3: 16-bit execute-only conforming code selector, not accessed, 0xfffe limit, CS16 base. +%define BS3_SEL_R3_CS32_EO 0458h ;;< ring-3: 32-bit execute-only code selector, not accessed, flat. +%define BS3_SEL_R3_CS32_CNF 0460h ;;< ring-3: 32-bit conforming code selector, not accessed, flat. +%define BS3_SEL_R3_CS32_CNF_EO 0468h ;;< ring-3: 32-bit execute-only conforming code selector, not accessed, flat. +%define BS3_SEL_R3_CS64_EO 0470h ;;< ring-3: 64-bit execute-only code selector, not accessed, flat. +%define BS3_SEL_R3_CS64_CNF 0478h ;;< ring-3: 64-bit conforming code selector, not accessed, flat. +%define BS3_SEL_R3_CS64_CNF_EO 0480h ;;< ring-3: 64-bit execute-only conforming code selector, not accessed, flat. + +%define BS3_SEL_SPARE_FIRST 0500h ;;< The first selector in the spare block +%define BS3_SEL_SPARE_00 0500h ;;< Spare selector number 00h. +%define BS3_SEL_SPARE_01 0508h ;;< Spare selector number 01h. +%define BS3_SEL_SPARE_02 0510h ;;< Spare selector number 02h. +%define BS3_SEL_SPARE_03 0518h ;;< Spare selector number 03h. +%define BS3_SEL_SPARE_04 0520h ;;< Spare selector number 04h. +%define BS3_SEL_SPARE_05 0528h ;;< Spare selector number 05h. +%define BS3_SEL_SPARE_06 0530h ;;< Spare selector number 06h. +%define BS3_SEL_SPARE_07 0538h ;;< Spare selector number 07h. +%define BS3_SEL_SPARE_08 0540h ;;< Spare selector number 08h. +%define BS3_SEL_SPARE_09 0548h ;;< Spare selector number 09h. +%define BS3_SEL_SPARE_0a 0550h ;;< Spare selector number 0ah. +%define BS3_SEL_SPARE_0b 0558h ;;< Spare selector number 0bh. +%define BS3_SEL_SPARE_0c 0560h ;;< Spare selector number 0ch. +%define BS3_SEL_SPARE_0d 0568h ;;< Spare selector number 0dh. +%define BS3_SEL_SPARE_0e 0570h ;;< Spare selector number 0eh. +%define BS3_SEL_SPARE_0f 0578h ;;< Spare selector number 0fh. +%define BS3_SEL_SPARE_10 0580h ;;< Spare selector number 10h. +%define BS3_SEL_SPARE_11 0588h ;;< Spare selector number 11h. +%define BS3_SEL_SPARE_12 0590h ;;< Spare selector number 12h. +%define BS3_SEL_SPARE_13 0598h ;;< Spare selector number 13h. +%define BS3_SEL_SPARE_14 05a0h ;;< Spare selector number 14h. +%define BS3_SEL_SPARE_15 05a8h ;;< Spare selector number 15h. +%define BS3_SEL_SPARE_16 05b0h ;;< Spare selector number 16h. +%define BS3_SEL_SPARE_17 05b8h ;;< Spare selector number 17h. +%define BS3_SEL_SPARE_18 05c0h ;;< Spare selector number 18h. +%define BS3_SEL_SPARE_19 05c8h ;;< Spare selector number 19h. +%define BS3_SEL_SPARE_1a 05d0h ;;< Spare selector number 1ah. +%define BS3_SEL_SPARE_1b 05d8h ;;< Spare selector number 1bh. +%define BS3_SEL_SPARE_1c 05e0h ;;< Spare selector number 1ch. +%define BS3_SEL_SPARE_1d 05e8h ;;< Spare selector number 1dh. +%define BS3_SEL_SPARE_1e 05f0h ;;< Spare selector number 1eh. +%define BS3_SEL_SPARE_1f 05f8h ;;< Spare selector number 1fh. + +%define BS3_SEL_TILED 0600h ;;< 16-bit data tiling: First - base=0x00000000, limit=64KB, DPL=3. +%define BS3_SEL_TILED_LAST 0df8h ;;< 16-bit data tiling: Last - base=0x00ff0000, limit=64KB, DPL=3. +%define BS3_SEL_TILED_AREA_SIZE 001000000h ;;< 16-bit data tiling: Size of addressable area, in bytes. (16 MB) + +%define BS3_SEL_FREE_PART1 0e00h ;;< Free selector space - part \%1. +%define BS3_SEL_FREE_PART1_LAST 0ff8h ;;< Free selector space - part \%1, last entry. + +%define BS3_SEL_TEXT16 1000h ;;< The BS3TEXT16 selector. + +%define BS3_SEL_FREE_PART2 1008h ;;< Free selector space - part \#2. +%define BS3_SEL_FREE_PART2_LAST 17f8h ;;< Free selector space - part \#2, last entry. + +%define BS3_SEL_TILED_R0 1800h ;;< 16-bit data/stack tiling: First - base=0x00000000, limit=64KB, DPL=0. +%define BS3_SEL_TILED_R0_LAST 1ff8h ;;< 16-bit data/stack tiling: Last - base=0x00ff0000, limit=64KB, DPL=0. + +%define BS3_SEL_SYSTEM16 2000h ;;< The BS3SYSTEM16 selector. + +%define BS3_SEL_FREE_PART3 2008h ;;< Free selector space - part \%3. +%define BS3_SEL_FREE_PART3_LAST 28f8h ;;< Free selector space - part \%3, last entry. + +%define BS3_SEL_DATA16 2900h ;;< The BS3DATA16/BS3KIT_GRPNM_DATA16 selector. + +%define BS3_SEL_FREE_PART4 2908h ;;< Free selector space - part \#4. +%define BS3_SEL_FREE_PART4_LAST 2f98h ;;< Free selector space - part \#4, last entry. + +%define BS3_SEL_PRE_TEST_PAGE_08 2fa0h ;;< Selector located 8 selectors before the test page. +%define BS3_SEL_PRE_TEST_PAGE_07 2fa8h ;;< Selector located 7 selectors before the test page. +%define BS3_SEL_PRE_TEST_PAGE_06 2fb0h ;;< Selector located 6 selectors before the test page. +%define BS3_SEL_PRE_TEST_PAGE_05 2fb8h ;;< Selector located 5 selectors before the test page. +%define BS3_SEL_PRE_TEST_PAGE_04 2fc0h ;;< Selector located 4 selectors before the test page. +%define BS3_SEL_PRE_TEST_PAGE_03 2fc8h ;;< Selector located 3 selectors before the test page. +%define BS3_SEL_PRE_TEST_PAGE_02 2fd0h ;;< Selector located 2 selectors before the test page. +%define BS3_SEL_PRE_TEST_PAGE_01 2fd8h ;;< Selector located 1 selector before the test page. +%define BS3_SEL_TEST_PAGE 2fe0h ;;< Start of the test page intended for playing around with paging and GDT. +%define BS3_SEL_TEST_PAGE_00 2fe0h ;;< Test page selector number 00h (convenience). +%define BS3_SEL_TEST_PAGE_01 2fe8h ;;< Test page selector number 01h (convenience). +%define BS3_SEL_TEST_PAGE_02 2ff0h ;;< Test page selector number 02h (convenience). +%define BS3_SEL_TEST_PAGE_03 2ff8h ;;< Test page selector number 03h (convenience). +%define BS3_SEL_TEST_PAGE_04 3000h ;;< Test page selector number 04h (convenience). +%define BS3_SEL_TEST_PAGE_05 3008h ;;< Test page selector number 05h (convenience). +%define BS3_SEL_TEST_PAGE_06 3010h ;;< Test page selector number 06h (convenience). +%define BS3_SEL_TEST_PAGE_07 3018h ;;< Test page selector number 07h (convenience). +%define BS3_SEL_TEST_PAGE_LAST 3fd0h ;;< The last selector in the spare page. + +%define BS3_SEL_GDT_LIMIT 3fd8h ;;< The GDT limit. + +;; @} + + +; +; Sanity checks. +; +%if BS3_ADDR_BS3TEXT16 != BS3_ADDR_LOAD + %error "BS3_ADDR_BS3TEXT16 and BS3_ADDR_LOAD are out of sync" +%endif +%if (BS3_ADDR_BS3TEXT16 / 16) != BS3_SEL_TEXT16 + %error "BS3_ADDR_BS3TEXT16 and BS3_SEL_TEXT16 are out of sync" +%endif +%if (BS3_ADDR_BS3DATA16 / 16) != BS3_SEL_DATA16 + %error "BS3_ADDR_BS3DATA16 and BS3_SEL_DATA16 are out of sync" +%endif +%if (BS3_ADDR_BS3SYSTEM16 / 16) != BS3_SEL_SYSTEM16 + %error "BS3_ADDR_BS3SYSTEM16 and BS3_SEL_SYSTEM16 are out of sync" +%endif + + +;; @name BS3CPU_XXX - Bs3CpuDetect_mmm return value and g_bBs3CpuDetected. +;; @{ +%define BS3CPU_8086 0x0001 +%define BS3CPU_V20 0x0002 +%define BS3CPU_80186 0x0003 +%define BS3CPU_80286 0x0004 +%define BS3CPU_80386 0x0005 +%define BS3CPU_80486 0x0006 +%define BS3CPU_Pentium 0x0007 +%define BS3CPU_PPro 0x0008 +%define BS3CPU_PProOrNewer 0x0009 +%define BS3CPU_TYPE_MASK 0x00ff +%define BS3CPU_F_CPUID 0x0100 +%define BS3CPU_F_CPUID_EXT_LEAVES 0x0200 +%define BS3CPU_F_PAE 0x0400 +%define BS3CPU_F_PAE_BIT 10 +%define BS3CPU_F_PSE 0x0800 +%define BS3CPU_F_PSE_BIT 11 +%define BS3CPU_F_LONG_MODE 0x1000 +%define BS3CPU_F_LONG_MODE_BIT 12 +%define BS3CPU_F_NX 0x2000 +%define BS3CPU_F_NX_BIT 13 +;; @} + +%endif + |