404 lines
7.5 KiB
C
404 lines
7.5 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
jxreboot.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the Firmware Termination Functions.
|
||
|
||
Author:
|
||
|
||
Lluis Abello (lluis) 4-Sep-1991
|
||
|
||
|
||
Revision History:
|
||
|
||
Lluis Abello (lluis) 29-Apr-1993
|
||
Added FwpRestart function
|
||
|
||
--*/
|
||
#include "fwp.h"
|
||
#include "selftest.h"
|
||
#include "fwstring.h"
|
||
#include "oli2msft.h"
|
||
#include "arceisa.h"
|
||
|
||
VOID FwBootRestartProcessorEnd(
|
||
IN VOID
|
||
);
|
||
|
||
VOID FwBootRestartProcessor(
|
||
IN PVOID RestartBlock
|
||
);
|
||
|
||
BOOLEAN
|
||
SendKbdCommand(
|
||
IN UCHAR Command
|
||
);
|
||
|
||
BOOLEAN
|
||
SendKbdData(
|
||
IN UCHAR Data
|
||
);
|
||
|
||
VOID
|
||
ResetSystem (
|
||
IN VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine resets the system by asserting the reset line
|
||
from the keyboard controller.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
SendKbdCommand(0xD1);
|
||
SendKbdData(0);
|
||
}
|
||
|
||
VOID
|
||
FwHalt(
|
||
IN VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is the Firmware Halt termination function.
|
||
It displays a message and halts.
|
||
This routine is also the firmware PowerDown function.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
FwClearScreen();
|
||
FwPrint(FW_SYSTEM_HALT_MSG);
|
||
DisableInterrupts();
|
||
for (;;) {
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
FwpRestart(
|
||
IN VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine implements the Firmware Restart termination function.
|
||
If a valid restart block is detected, It is loaded and execution
|
||
continues at the restart address.
|
||
If no valid restart block is found, a soft reset is generated and the
|
||
normal boot sequence takes place.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
Does not return to the caller.
|
||
|
||
--*/
|
||
{
|
||
|
||
PRESTART_BLOCK RestartBlock;
|
||
PULONG BlockPointer;
|
||
ULONG Checksum;
|
||
ULONG WhoAmI;
|
||
|
||
#ifdef DUO
|
||
WhoAmI = READ_REGISTER_ULONG(&DMA_CONTROL->WhoAmI.Long);
|
||
#else
|
||
WhoAmI = 0;
|
||
#endif
|
||
|
||
RestartBlock = SYSTEM_BLOCK->RestartBlock;
|
||
|
||
while ((RestartBlock != NULL) && (RestartBlock->ProcessorId != WhoAmI)) {
|
||
RestartBlock = RestartBlock->NextRestartBlock;
|
||
}
|
||
|
||
if (RestartBlock != NULL) {
|
||
|
||
//
|
||
// Check signature;
|
||
//
|
||
if (RestartBlock->Signature == 0x42545352) {
|
||
|
||
//
|
||
// Check checksum.
|
||
//
|
||
//Checksum = 0;
|
||
//BlockPointer = (PULONG) RestartBlock;
|
||
//
|
||
//BlockPointer += sizeof(RESTART_BLOCK)/sizeof(ULONG);
|
||
|
||
//do {
|
||
// BlockPointer--;
|
||
// Checksum+= *BlockPointer;
|
||
//} while (BlockPointer != (PULONG)RestartBlock);
|
||
|
||
//if (Checksum == 0) {
|
||
|
||
//
|
||
// A valid restart block has been detected
|
||
// Flush the data cache and restart the processor.
|
||
//
|
||
HalSweepDcache();
|
||
VenRestartBlock(RestartBlock);
|
||
return;
|
||
//}
|
||
}
|
||
}
|
||
|
||
//
|
||
// No valid restart block found. Reset.
|
||
//
|
||
return;
|
||
//ResetSystem();
|
||
}
|
||
#ifdef DUO
|
||
|
||
VOID
|
||
ProcessorBSystemBoot(
|
||
IN VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is the second processor boot routine. It polls the boot
|
||
status field of the restart block and when the StartProcessor bit
|
||
is set it restarts from the Restart block.
|
||
|
||
The master processor sets the address of this routine in the Task vector
|
||
and issues an IP interrupt to processor B who starts executing this code.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
Does not return to the caller.
|
||
|
||
--*/
|
||
{
|
||
BOOT_STATUS BootStatus;
|
||
for (;;) {
|
||
BootStatus = SYSTEM_BLOCK->RestartBlock->NextRestartBlock->BootStatus;
|
||
if (BootStatus.ProcessorStart == 1) {
|
||
FwpRestart();
|
||
FwPrint("Processor B failed to start from Restart Block\r\n");
|
||
} else {
|
||
FwStallExecution(10000); // wait 10ms
|
||
|
||
//
|
||
// Check if another Ip interrupt was issued to us
|
||
// if it was give up boot.
|
||
//
|
||
if (IsIpInterruptSet()) {
|
||
return;
|
||
}
|
||
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|
||
|
||
VOID
|
||
FwReboot(
|
||
IN VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine implements the Firmware Reboot termination function.
|
||
It generates a soft reset to the system.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
Does not return to the caller.
|
||
|
||
--*/
|
||
{
|
||
ResetSystem();
|
||
}
|
||
|
||
VOID
|
||
FwEnterInteractiveMode(
|
||
IN VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine implements the Firmware EnterInteractiveMode function.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
FwMonitor(3);
|
||
}
|
||
|
||
|
||
#ifdef DUO
|
||
|
||
VOID
|
||
InitializeRestartBlock(
|
||
IN VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine intializes the restart blocks for all processors.
|
||
The boot status field has already been initialized and indicates
|
||
weather the processor passed selftest or not.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PULONG BlockPointer;
|
||
PRESTART_BLOCK RestartBlock;
|
||
ULONG Checksum;
|
||
ULONG ProcessorId;
|
||
|
||
RestartBlock = SYSTEM_BLOCK->RestartBlock;
|
||
|
||
for (ProcessorId = 0; RestartBlock != NULL; ProcessorId++) {
|
||
|
||
RestartBlock->Signature = 0x42545352;
|
||
RestartBlock->Length = sizeof(RESTART_BLOCK);
|
||
RestartBlock->Version = ARC_VERSION;
|
||
RestartBlock->Revision = ARC_REVISION;
|
||
RestartBlock->RestartAddress = NULL;
|
||
RestartBlock->SaveAreaLength = (ULONG)SYSTEM_BLOCK->RestartBlock + sizeof(RESTART_BLOCK)- (ULONG)&SYSTEM_BLOCK->RestartBlock->u.SaveArea[0];
|
||
RestartBlock->BootMasterId = 0;
|
||
RestartBlock->ProcessorId = ProcessorId;
|
||
|
||
//
|
||
// Zero Save area.
|
||
//
|
||
RtlZeroMemory(RestartBlock->u.SaveArea,RestartBlock->SaveAreaLength);
|
||
|
||
//
|
||
// Compute checksum.
|
||
//
|
||
Checksum = 0;
|
||
RestartBlock->CheckSum = 0;
|
||
BlockPointer = (PULONG) RestartBlock;
|
||
BlockPointer += sizeof(RESTART_BLOCK)/sizeof(ULONG);
|
||
|
||
do {
|
||
BlockPointer--;
|
||
Checksum+= *BlockPointer;
|
||
} while (BlockPointer != (PULONG)RestartBlock);
|
||
|
||
RestartBlock->CheckSum = -Checksum;
|
||
|
||
//
|
||
// Get next restart block
|
||
//
|
||
RestartBlock = RestartBlock->NextRestartBlock;
|
||
}
|
||
}
|
||
|
||
#endif // DUO
|
||
|
||
|
||
VOID
|
||
FwTerminationInitialize(
|
||
IN VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
//
|
||
// Initialize the termination function entry points in the transfer vector
|
||
//
|
||
This routine initializes the termination function entry points
|
||
in the transfer vector.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
|
||
PULONG Destination;
|
||
|
||
(PARC_HALT_ROUTINE)SYSTEM_BLOCK->FirmwareVector[HaltRoutine] = FwHalt;
|
||
(PARC_POWERDOWN_ROUTINE)SYSTEM_BLOCK->FirmwareVector[PowerDownRoutine] = FwHalt;
|
||
(PARC_RESTART_ROUTINE)SYSTEM_BLOCK->FirmwareVector[RestartRoutine] = FwReboot;
|
||
(PARC_REBOOT_ROUTINE)SYSTEM_BLOCK->FirmwareVector[RebootRoutine] = FwReboot;
|
||
(PARC_INTERACTIVE_MODE_ROUTINE)SYSTEM_BLOCK->FirmwareVector[InteractiveModeRoutine] = FwEnterInteractiveMode;
|
||
// (PARC_RETURN_FROM_MAIN_ROUTINE)SYSTEM_BLOCK->FirmwareVector[ReturnFromMainRoutine] = FwReturnFromMain;
|
||
|
||
#ifdef DUO
|
||
|
||
InitializeRestartBlock();
|
||
Destination = (PULONG)(((ULONG)&SYSTEM_BLOCK->Adapter0Vector[MaximumEisaRoutine] & ~KSEG1_BASE) | KSEG0_BASE);
|
||
(PVEN_BOOT_RESTART_ROUTINE)SYSTEM_BLOCK->VendorVector[BootRestartRoutine] = Destination;
|
||
Destination = (PULONG)((ULONG)Destination | KSEG1_BASE);
|
||
RtlMoveMemory(Destination,FwBootRestartProcessor,(PCHAR)FwBootRestartProcessorEnd - (PCHAR)FwBootRestartProcessor);
|
||
|
||
#endif // DUO
|
||
|
||
}
|