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
|
|||
|
|
|||
|
}
|