126 lines
4.7 KiB
C
126 lines
4.7 KiB
C
// Kernel HAL binding and generic platform-operation wrappers.
|
|
|
|
#include <kernel/ke_hal.h>
|
|
|
|
static const HAL_API* gHal;
|
|
|
|
// Binds the bootstrap HAL table before kernel code begins using interrupt-state primitives.
|
|
KSTATUS KeBindBootstrapHal(void) {
|
|
const HAL_API* hal = HalGetApi();
|
|
if (!hal || hal->Size != sizeof(HAL_API) || hal->Version != HAL_API_VERSION ||
|
|
!hal->Processor.DisableInterrupts || !hal->Processor.RestoreInterrupts ||
|
|
!hal->Processor.EnableInterrupts || !hal->Processor.WaitForInterrupt ||
|
|
!hal->Processor.Halt || !hal->Processor.Stop) {
|
|
return NTLSTATUS_INVALID_PARAMETER;
|
|
}
|
|
gHal = hal;
|
|
return NTLSTATUS_SUCCESS;
|
|
}
|
|
|
|
// Returns whether the initialized table contains every mandatory kernel platform service.
|
|
static int KiHalRuntimeTableValid(const HAL_API* hal) {
|
|
return hal && hal->Size == sizeof(HAL_API) && hal->Version == HAL_API_VERSION &&
|
|
hal->Processor.DisableInterrupts && hal->Processor.RestoreInterrupts &&
|
|
hal->Processor.EnableInterrupts && hal->Processor.WaitForInterrupt &&
|
|
hal->Processor.Halt && hal->Processor.Stop && hal->Processor.QueryTopology &&
|
|
hal->Processor.Start &&
|
|
hal->Screen.GetFramebuffer &&
|
|
hal->Output.RegisterEndpoint && hal->Output.Write && hal->Output.QueryStats &&
|
|
hal->Timer.QueryTicks && hal->Timer.QueryTickFrequency && hal->Timer.Stall &&
|
|
hal->Timer.HandleInterrupt && hal->Timer.ConfigureCurrentProcessor &&
|
|
hal->Rtc.QueryTime && hal->Pci.Read32 && hal->Pci.Write32 &&
|
|
hal->InterruptController.RouteIrq && hal->InterruptController.MaskIrq &&
|
|
hal->InterruptController.UnmaskIrq && hal->InterruptController.SendEoi &&
|
|
hal->InterruptController.InitializeCurrentProcessor &&
|
|
hal->InterruptController.SendProcessorInterrupt &&
|
|
hal->InterruptController.SendProcessorNmi && hal->InterruptController.BroadcastNmi &&
|
|
hal->InterruptController.ComposeMsi && hal->Power.Shutdown;
|
|
}
|
|
|
|
// Initializes the HAL and validates every mandatory runtime service consumed by the kernel.
|
|
KSTATUS KeInitializeHal(const HAL_INIT_PARAMS* params) {
|
|
if (!gHal || !params)
|
|
return NTLSTATUS_INVALID_PARAMETER;
|
|
|
|
KSTATUS status = HalInitialize(params);
|
|
if (!KSUCCESS(status))
|
|
return status;
|
|
|
|
const HAL_API* hal = HalGetApi();
|
|
if (hal != gHal || !KiHalRuntimeTableValid(hal))
|
|
return NTLSTATUS_INVALID_PARAMETER;
|
|
return NTLSTATUS_SUCCESS;
|
|
}
|
|
|
|
// Returns the bound HAL table.
|
|
const HAL_API* KeGetHal(void) {
|
|
return gHal;
|
|
}
|
|
|
|
// Masks interrupts and returns the previous processor flags.
|
|
__declspec(dllexport) uintptr_t KeDisableInterrupts(void) {
|
|
return gHal->Processor.DisableInterrupts();
|
|
}
|
|
|
|
// Restores a previously saved processor interrupt state.
|
|
__declspec(dllexport) void KeRestoreInterrupts(uintptr_t flags) {
|
|
gHal->Processor.RestoreInterrupts(flags);
|
|
}
|
|
|
|
// Enables maskable interrupts on the current processor.
|
|
void KeEnableInterrupts(void) {
|
|
gHal->Processor.EnableInterrupts();
|
|
}
|
|
|
|
// Enables interrupts and waits for the next interrupt on the current processor.
|
|
void KeWaitForInterrupt(void) {
|
|
gHal->Processor.WaitForInterrupt();
|
|
}
|
|
|
|
// Halts the current processor once without changing interrupt state.
|
|
void KeHaltProcessor(void) {
|
|
gHal->Processor.Halt();
|
|
}
|
|
|
|
// Permanently stops the current processor.
|
|
_Noreturn void KeStopProcessor(void) {
|
|
gHal->Processor.Stop();
|
|
for (;;) {
|
|
}
|
|
}
|
|
|
|
// Queries platform processor topology without exposing interrupt-controller details.
|
|
KSTATUS KeQueryProcessorTopology(HAL_PROCESSOR_TOPOLOGY* topologyOut) {
|
|
return gHal->Processor.QueryTopology(topologyOut);
|
|
}
|
|
|
|
// Starts one processor at a physical bootstrap entry address.
|
|
KSTATUS KeStartProcessor(uint32_t hardwareId, uintptr_t startPhysical) {
|
|
return gHal->Processor.Start(hardwareId, startPhysical);
|
|
}
|
|
|
|
// Initializes the current processor's local interrupt-controller state.
|
|
void KeInitializeCurrentProcessorInterruptController(void) {
|
|
gHal->InterruptController.InitializeCurrentProcessor();
|
|
}
|
|
|
|
// Sends one fixed-vector interrupt to a processor hardware ID.
|
|
void KeSendProcessorInterrupt(uint32_t hardwareId, uint8_t vector) {
|
|
gHal->InterruptController.SendProcessorInterrupt(hardwareId, vector);
|
|
}
|
|
|
|
// Sends one non-maskable interrupt to a processor hardware ID.
|
|
void KeSendProcessorNmi(uint32_t hardwareId) {
|
|
gHal->InterruptController.SendProcessorNmi(hardwareId);
|
|
}
|
|
|
|
// Sends a non-maskable interrupt to every other processor.
|
|
void KeBroadcastProcessorNmi(void) {
|
|
gHal->InterruptController.BroadcastNmi();
|
|
}
|
|
|
|
// Arms the calibrated periodic timer on the current processor.
|
|
void KeConfigureCurrentProcessorTimer(void) {
|
|
gHal->Timer.ConfigureCurrentProcessor();
|
|
}
|