reactos/hal/halx86/generic/halinit.c
Hermès Bélusca-Maïto 3022d74beb
[NTOS:EX/KE][HALX86] Add support for NUMPROC, BOOTPROC, MAXPROC, ONECPU boot switches (#6024)
These SMP-specific switches allow to test and control configurations
with various number of CPUs on multiprocessor systems.

- NUMPROC: maximum number of logical processors that can be started
  (including dynamically, not currently supported by ReactOS) at run-time.

- BOOTPROC: maximum number of logical processors that can be started at
  boot-time.

- MAXPROC: forces the OS to report the maximum possible number of CPUs
  as existing on the system.

- ONECPU (MP HAL-only boot switch): causes the HAL to only use one
  (the boot) CPU on a multiprocessor system. Attempting to start other
  processors will fail.

For more information, see:
https://www.geoffchappell.com/notes/windows/boot/bcd/osloader/numproc.htm
https://www.geoffchappell.com/notes/windows/license/processors.htm
https://rmscrypt.wordpress.com/2011/02/
https://codeinsecurity.wordpress.com/2022/04/07/cpu-socket-and-core-count-limits-in-windows-10-and-how-to-remove-them/

Generic references about BOOT.INI switches:
https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/boot-options-in-a-boot-ini-file
https://www.itprotoday.com/cloud-computing/what-switches-can-be-used-bootini
http://franck.kiechel.free.fr/dbr_eng/BootIni.htm

References about BCD options:
https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/bcdedit--set
http://www.mistyprojects.co.uk/documents/BCDEdit/files/commands.6.1.7601.htm#TYPES%20OSLOADER
2025-04-04 12:51:49 +02:00

175 lines
4.9 KiB
C

/*
* PROJECT: ReactOS HAL
* LICENSE: GPL - See COPYING in the top level directory
* FILE: hal/halx86/generic/halinit.c
* PURPOSE: HAL Entrypoint and Initialization
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include <hal.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
//#ifdef CONFIG_SMP // FIXME: Reenable conditional once HAL is consistently compiled for SMP mode
BOOLEAN HalpOnlyBootProcessor;
//#endif
BOOLEAN HalpPciLockSettings;
/* PRIVATE FUNCTIONS *********************************************************/
static
CODE_SEG("INIT")
VOID
HalpGetParameters(
_In_ PLOADER_PARAMETER_BLOCK LoaderBlock)
{
/* Make sure we have a loader block and command line */
if (LoaderBlock && LoaderBlock->LoadOptions)
{
/* Read the command line */
PCSTR CommandLine = LoaderBlock->LoadOptions;
//#ifdef CONFIG_SMP // FIXME: Reenable conditional once HAL is consistently compiled for SMP mode
/* Check whether we should only start one CPU */
if (strstr(CommandLine, "ONECPU"))
HalpOnlyBootProcessor = TRUE;
//#endif
/* Check if PCI is locked */
if (strstr(CommandLine, "PCILOCK"))
HalpPciLockSettings = TRUE;
/* Check for initial breakpoint */
if (strstr(CommandLine, "BREAK"))
DbgBreakPoint();
}
}
/* FUNCTIONS *****************************************************************/
VOID
NTAPI
HalInitializeProcessor(
IN ULONG ProcessorNumber,
IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
/* Hal specific initialization for this cpu */
HalpInitProcessor(ProcessorNumber, LoaderBlock);
/* Set default stall count */
KeGetPcr()->StallScaleFactor = INITIAL_STALL_COUNT;
/* Update the interrupt affinity and processor mask */
InterlockedBitTestAndSetAffinity(&HalpActiveProcessors, ProcessorNumber);
InterlockedBitTestAndSetAffinity(&HalpDefaultInterruptAffinity, ProcessorNumber);
if (ProcessorNumber == 0)
{
/* Register routines for KDCOM */
HalpRegisterKdSupportFunctions();
}
}
/*
* @implemented
*/
CODE_SEG("INIT")
BOOLEAN
NTAPI
HalInitSystem(
_In_ ULONG BootPhase,
_In_ PLOADER_PARAMETER_BLOCK LoaderBlock)
{
PKPRCB Prcb = KeGetCurrentPrcb();
NTSTATUS Status;
/* Check the boot phase */
if (BootPhase == 0)
{
/* Save bus type */
HalpBusType = LoaderBlock->u.I386.MachineType & 0xFF;
/* Get command-line parameters */
HalpGetParameters(LoaderBlock);
/* Check for PRCB version mismatch */
if (Prcb->MajorVersion != PRCB_MAJOR_VERSION)
{
/* No match, bugcheck */
KeBugCheckEx(MISMATCHED_HAL, 1, Prcb->MajorVersion, PRCB_MAJOR_VERSION, 0);
}
/* Checked/free HAL requires checked/free kernel */
if (Prcb->BuildType != HalpBuildType)
{
/* No match, bugcheck */
KeBugCheckEx(MISMATCHED_HAL, 2, Prcb->BuildType, HalpBuildType, 0);
}
/* Initialize ACPI */
Status = HalpSetupAcpiPhase0(LoaderBlock);
if (!NT_SUCCESS(Status))
{
KeBugCheckEx(ACPI_BIOS_ERROR, Status, 0, 0, 0);
}
/* Initialize the PICs */
HalpInitializePICs(TRUE);
/* Initialize CMOS lock */
KeInitializeSpinLock(&HalpSystemHardwareLock);
/* Initialize CMOS */
HalpInitializeCmos();
/* Fill out the dispatch tables */
HalQuerySystemInformation = HaliQuerySystemInformation;
HalSetSystemInformation = HaliSetSystemInformation;
HalInitPnpDriver = HaliInitPnpDriver;
HalGetDmaAdapter = HalpGetDmaAdapter;
HalGetInterruptTranslator = NULL; // FIXME: TODO
HalResetDisplay = HalpBiosDisplayReset;
HalHaltSystem = HaliHaltSystem;
/* Setup I/O space */
HalpDefaultIoSpace.Next = HalpAddressUsageList;
HalpAddressUsageList = &HalpDefaultIoSpace;
/* Setup busy waiting */
HalpCalibrateStallExecution();
/* Initialize the clock */
HalpInitializeClock();
/*
* We could be rebooting with a pending profile interrupt,
* so clear it here before interrupts are enabled
*/
HalStopProfileInterrupt(ProfileTime);
/* Do some HAL-specific initialization */
HalpInitPhase0(LoaderBlock);
/* Initialize Phase 0 of the x86 emulator */
HalInitializeBios(0, LoaderBlock);
}
else if (BootPhase == 1)
{
/* Initialize bus handlers */
HalpInitBusHandlers();
/* Do some HAL-specific initialization */
HalpInitPhase1();
/* Initialize Phase 1 of the x86 emulator */
HalInitializeBios(1, LoaderBlock);
}
/* All done, return */
return TRUE;
}