// HAL output router. This file fans typed text streams out to registered physical and runtime endpoints. #include #include #include #include #include #define HAL_OUTPUT_ENDPOINT_CAPACITY 8u typedef struct HAL_OUTPUT_SLOT { HAL_OUTPUT_ENDPOINT Endpoint; volatile long Published; } HAL_OUTPUT_SLOT; static HAL_OUTPUT_SLOT gOutputSlots[HAL_OUTPUT_ENDPOINT_CAPACITY]; static volatile long gOutputRegistrationLock; static volatile long long gOutputRecordCount; static volatile long long gOutputByteCount; static volatile long long gOutputEndpointWriteCount; static volatile long long gOutputEmergencyRecordCount; static volatile long gOutputEndpointCount; // Acquires the endpoint registration lock. static void HalOutputAcquireRegistrationLock(void) { while (_InterlockedCompareExchange(&gOutputRegistrationLock, 1, 0) != 0) _mm_pause(); } // Releases the endpoint registration lock. static void HalOutputReleaseRegistrationLock(void) { _InterlockedExchange(&gOutputRegistrationLock, 0); } // Registers one output endpoint in the fixed endpoint table. static KSTATUS HalOutputRegisterEndpoint(const HAL_OUTPUT_ENDPOINT* endpoint, uint32_t* endpointIdOut) { if (!endpoint || !endpointIdOut || !endpoint->Name || !endpoint->Write || endpoint->StreamMask == 0 || (endpoint->StreamMask & ~HAL_OUTPUT_STREAM_ALL) != 0) return STATUS_INVALID_PARAMETER; KSTATUS status = STATUS_NO_MEMORY; HalOutputAcquireRegistrationLock(); for (uint32_t i = 0; i < HAL_OUTPUT_ENDPOINT_CAPACITY; i++) { HAL_OUTPUT_SLOT* slot = &gOutputSlots[i]; if (_InterlockedCompareExchange(&slot->Published, 0, 0) != 0) continue; slot->Endpoint = *endpoint; _ReadWriteBarrier(); _InterlockedExchange(&slot->Published, 1); _InterlockedIncrement(&gOutputEndpointCount); *endpointIdOut = i; status = STATUS_SUCCESS; break; } HalOutputReleaseRegistrationLock(); return status; } // Replaces the stream subscription mask for a registered endpoint. static KSTATUS HalOutputSetEndpointStreams(uint32_t endpointId, uint32_t streamMask) { if (endpointId >= HAL_OUTPUT_ENDPOINT_CAPACITY || (streamMask & ~HAL_OUTPUT_STREAM_ALL) != 0) return STATUS_INVALID_PARAMETER; HAL_OUTPUT_SLOT* slot = &gOutputSlots[endpointId]; if (_InterlockedCompareExchange(&slot->Published, 0, 0) == 0) return STATUS_NOT_FOUND; _InterlockedExchange((volatile long*)&slot->Endpoint.StreamMask, (long)streamMask); return STATUS_SUCCESS; } // Fans one text record out to every subscribed endpoint. static void HalOutputWrite(const HAL_OUTPUT_RECORD* record) { if (!record || !record->Buffer || record->Length == 0 || (record->Stream & HAL_OUTPUT_STREAM_ALL) == 0 || (record->Stream & (record->Stream - 1u)) != 0) return; _InterlockedIncrement64(&gOutputRecordCount); _InterlockedExchangeAdd64(&gOutputByteCount, (long long)record->Length); if (record->Flags & HAL_OUTPUT_WRITE_EMERGENCY) _InterlockedIncrement64(&gOutputEmergencyRecordCount); for (uint32_t i = 0; i < HAL_OUTPUT_ENDPOINT_CAPACITY; i++) { HAL_OUTPUT_SLOT* slot = &gOutputSlots[i]; if (_InterlockedCompareExchange(&slot->Published, 0, 0) == 0) continue; uint32_t streams = (uint32_t)_InterlockedCompareExchange( (volatile long*)&slot->Endpoint.StreamMask, 0, 0); if ((streams & record->Stream) == 0) continue; if ((record->Flags & HAL_OUTPUT_WRITE_EMERGENCY) && !(slot->Endpoint.Capabilities & HAL_OUTPUT_ENDPOINT_PANIC_SAFE)) continue; HAL_OUTPUT_ENDPOINT_WRITE write = slot->Endpoint.Write; void* context = slot->Endpoint.Context; if (!write) continue; write(context, record); _InterlockedIncrement64(&gOutputEndpointWriteCount); } } // Returns a snapshot of output router counters. static void HalOutputQueryStats(HAL_OUTPUT_STATS* statsOut) { if (!statsOut) return; memset(statsOut, 0, sizeof(*statsOut)); statsOut->RecordCount = (uint64_t)_InterlockedCompareExchange64(&gOutputRecordCount, 0, 0); statsOut->ByteCount = (uint64_t)_InterlockedCompareExchange64(&gOutputByteCount, 0, 0); statsOut->EndpointWriteCount = (uint64_t)_InterlockedCompareExchange64(&gOutputEndpointWriteCount, 0, 0); statsOut->EmergencyRecordCount = (uint64_t)_InterlockedCompareExchange64(&gOutputEmergencyRecordCount, 0, 0); statsOut->EndpointCount = (uint32_t)_InterlockedCompareExchange(&gOutputEndpointCount, 0, 0); } // Initializes the fixed HAL output endpoint table. void HalOutputInitialize(HAL_OUTPUT_ROUTER* output) { if (!output) return; memset(gOutputSlots, 0, sizeof(gOutputSlots)); gOutputRegistrationLock = 0; gOutputRecordCount = 0; gOutputByteCount = 0; gOutputEndpointWriteCount = 0; gOutputEmergencyRecordCount = 0; gOutputEndpointCount = 0; memset(output, 0, sizeof(*output)); output->RegisterEndpoint = HalOutputRegisterEndpoint; output->SetEndpointStreams = HalOutputSetEndpointStreams; output->Write = HalOutputWrite; output->QueryStats = HalOutputQueryStats; output->SerialEndpointId = HAL_OUTPUT_ENDPOINT_INVALID; output->BootFramebufferEndpointId = HAL_OUTPUT_ENDPOINT_INVALID; }