summaryrefslogtreecommitdiffstats
path: root/src/VBox/ValidationKit/bootsectors/bs3kit
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
commitf215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch)
tree6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/ValidationKit/bootsectors/bs3kit
parentInitial commit. (diff)
downloadvirtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz
virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/ValidationKit/bootsectors/bs3kit')
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/Makefile.kmk760
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/VBoxBs3Linker.cpp362
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/VBoxBs3ObjConverter.cpp5530
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/asmdefs-first.mac62
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-bootsector.asm594
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-CreateHybridFarRet.asm63
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-SwitchFromV86To16BitAndCallC.asm109
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-Trap16Generic.asm720
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-TrapRmV86Data.c53
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-TrapRmV86Generic.asm401
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c32-Trap32Generic.asm546
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c64-Trap64Generic.asm337
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-A20Disable.asm115
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-A20Enable.asm122
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ConvertRMStackToP16UsingCxReturnToAx.asm88
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-CpuDetectData.c54
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxAlloc.c54
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxCopy.c53
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxFree.c56
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetAbridgedFtw.c71
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetFcw.c59
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetFsw.c59
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetMm.c60
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetMxCsr.c53
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetMxCsrMask.c53
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetSize.c69
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetXmm.c64
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxGetYmm.c70
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxInit.c84
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxRestore.asm155
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxRestoreEx.asm136
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSave.asm166
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSaveEx.asm136
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetAbridgedFtw.c61
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetFcw.c60
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetFsw.c60
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetMm.c66
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetMxCsr.c56
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetMxCsrMask.c56
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetXmm.c61
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-ExtCtxSetYmm.c79
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-GetCpuVendor.c63
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-GetModeName.c72
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-GetModeNameShortLower.c72
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-KbdRead.asm75
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-KbdWait.asm64
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-KbdWrite.asm82
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemAlloc.c111
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemAllocZ.c53
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemChr.asm88
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemCmp.asm99
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemCpy.c85
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemFree.c73
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemGuardedTestPage.c109
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemMove.c88
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemPCpy.c58
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemPrintInfo.c95
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemSet.asm102
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemZero.asm103
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingAlias.c193
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingData.c59
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingInitRootForLM.c115
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingInitRootForPAE.c102
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingInitRootForPP.c163
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingMapRamAbove4GForLM.c120
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingProtect.c392
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingQueryAddressInfo.c159
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingSetupCanonicalTraps.c123
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Panic.asm48
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PerCpuData.c74
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PicMaskAll.c51
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PicSetup.c90
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PicUpdateMask.c55
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PitIrqHandler.c76
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintChr.asm115
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintStr.c44
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintStrN.asm204
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintU32.asm93
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PrintX32.asm97
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Printf.c95
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxConvertToRingX.c182
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxConvertV86ToRm.c55
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxGetRspSsAsCurPtr.c71
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxPrint.c77
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxRestore.asm608
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSave.asm271
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSaveEx.asm460
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSaveForMode.c65
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetGpr.c64
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetGrpSegFromCurPtr.c60
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetGrpSegFromFlat.c75
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetRipCsFromCurPtr.c53
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetRipCsFromFlat.c75
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSetRipCsFromLnkPtr.c87
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetCr0.asm89
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetCr2.asm89
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetCr3.asm89
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetCr4.asm89
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr0.asm89
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr1.asm89
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr2.asm89
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr3.asm89
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr6.asm89
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDr7.asm89
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetDrX.asm135
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetLdtr.asm80
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetTr.asm80
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegGetXcr0.asm77
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetCr0.asm96
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetCr2.asm96
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetCr3.asm96
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetCr4.asm96
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr0.asm96
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr1.asm96
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr2.asm96
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr3.asm96
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr6.asm96
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDr7.asm96
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetDrX.asm142
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetLdtr.asm91
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetTr.asm108
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegSetXcr0.asm104
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFar32ToFlat32.c47
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFar32ToFlat32NoClobber.asm114
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFlatCodeToProtFar16.asm128
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFlatCodeToRealMode.asm163
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFlatDataToProtFar16.asm142
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelFlatDataToRealMode.asm104
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelLnkPtrToCurPtr.c51
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelLnkPtrToFlat.c49
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelProtFar16DataToFlat.asm100
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelProtFar16DataToRealMode.asm157
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelProtFar32ToFlat32.c55
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelProtModeCodeToRealMode.asm122
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelRealModeCodeToProtMode.asm94
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelRealModeDataToFlat.asm101
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelRealModeDataToProtFar16.asm151
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetup16BitCode.c61
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetup16BitData.c61
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetup32BitCode.c62
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetupGate.c61
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SelSetupGate64.c61
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Shutdown.asm63
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabAlloc.c64
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabAllocEx.c111
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabFree.c69
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabInit.c72
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListAdd.c53
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListAlloc.c67
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListAllocEx.c68
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListFree.c64
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SlabListInit.c50
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrCpy.c51
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrFormatV.c788
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrLen.c47
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrNLen.c47
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrPrintf.c105
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchHlpConvFlatRetToRetfProtMode.asm78
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchHlpConvProtModeRetfPopBpDecBpAndReturn.asm126
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchHlpConvRealModeRetfPopBpDecBpAndReturn.asm109
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchTo16Bit.asm130
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchTo16BitV86.asm133
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchTo32Bit.asm162
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchTo64Bit.asm120
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRing0.asm73
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRing1.asm73
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRing2.asm73
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRing3.asm73
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-SwitchToRingX.asm103
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Syscall.asm94
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestCheckExtCtx.c287
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestCheckRegCtxEx.c107
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestData.c135
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestDoModesByOneHlp.asm253
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestFailed.c151
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestHostPrintf.c114
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestInit.c77
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestIsVmmDevTestingPresent.asm78
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestNow.asm113
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestPrintf.c146
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestQueryCfgU32.asm94
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestQueryCfgU8.asm86
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSendCmdWithStr.asm90
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSendCmdWithU32.asm88
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSkipped.c100
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSub.c105
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSubDone.c54
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestSubErrorCount.c54
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestTerm.c117
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TestValue.c86
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap16Init.c129
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap16SetGate.c62
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap32Init.c101
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap32SetGate.c62
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap64Init.c109
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-Trap64SetGate.c65
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapDefaultHandler.c331
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapHandlersData.asm52
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapPrintFrame.c89
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapReInit.c65
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapRmV86Init.c122
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapRmV86SetGate.c51
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetDpl.c57
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetHandler.c57
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetHandlerEx.c71
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmp.asm143
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestore.c56
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestoreInRm.c133
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestoreWithExtCtx.c61
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestoreWithExtCtxAndRm.c66
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapSetJmpAndRestoreWithRm.c59
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-TrapUnsetJmp.c58
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-UInt32Div.c50
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-UInt64Div.c50
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-UtilSetFullGdtr.asm195
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-UtilSetFullIdtr.asm195
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-hexdigits.c42
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate-common.h214
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate-x0.c1639
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate-x1.c1639
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate.c1639
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate.c3239
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-instantiate.c6439
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-memory.h109
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-paging.h69
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-pic-data.c52
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-pic.h70
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-pit.c170
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-test.h179
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-common.mac281
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-dosexe.asm43
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-init-all-lm64.asm91
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-init-all-pe32.asm69
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-init-all-pp32.asm69
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-pe16.asm105
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-rm.asm59
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-BiosInt15hE820.asm245
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-CpuDetect.asm347
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-EnteredMode.asm279
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-Name.asm44
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-NameShortLower.asm46
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForLM64.asm141
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForPAE16.asm55
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForPAE32.asm127
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForPP16.asm55
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-PagingGetRootForPP32.asm142
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchTo32BitAndCallC.asm164
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToLM16.asm136
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToLM32.asm203
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToLM64.asm114
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE16.asm243
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE16_32.asm114
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE16_V86.asm124
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE32.asm202
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAE32_16.asm132
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPAEV86.asm118
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE16.asm198
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE16_32.asm114
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE16_V86.asm124
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE32.asm179
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPE32_16.asm132
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPEV86.asm118
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP16.asm258
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP16_32.asm114
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP16_V86.asm124
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP32.asm209
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPP32_16.asm132
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToPPV86.asm118
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-SwitchToRM.asm411
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModes.c380
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModes.h99
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesByMax.c380
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesByMaxStub.asm63
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesByOne.c424
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesByOneStub.asm63
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesHlp.asm1139
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TestDoModesStub.asm63
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TrapInit.c61
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TrapSetJmpAndRestoreInRmAsm.asm174
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TrapSystemCallHandler.asm891
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-rm-InitAll.c100
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-rm-InitGdt.c71
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-rm-InitMemory.c317
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-shutdown.c87
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-system-data.asm1056
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-I4D.asm80
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-I8DQ.asm121
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-I8DR.asm121
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-I8RS.asm78
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U4D.asm124
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U8DQ.asm124
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U8DR.asm124
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U8LS.asm80
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc16-U8RS.asm82
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-I8D.asm81
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-I8RS.asm70
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-U8D.asm81
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-U8LS.asm72
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-U8M.asm93
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-wc32-U8RS.asm70
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3cpudt.c71
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-autostubs.kmk194
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-docs.c170
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-mangling-code-define.h256
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-mangling-code-undef.h256
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-mangling-code.h52
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-mangling-data.h295
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-template-footer.h93
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-template-footer.mac142
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-template-header.h532
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit-template-header.mac532
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit.h4534
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit.mac1767
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
+