1. change *.msa to *.inf, and create platform configuration files .dec&.dsc&.fdf to comply with Edk2 build process 2. using PCD mechanism to replace macro. 3. change Sec code to cowork with PI1.0 Pei Core and produce temparory memory ppi. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@5380 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			537 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			537 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
 | 
						|
Copyright (c) 2006, Intel Corporation
 | 
						|
All rights reserved. This program and the accompanying materials
 | 
						|
are licensed and made available under the terms and conditions of the BSD License
 | 
						|
which accompanies this distribution.  The full text of the license may be found at
 | 
						|
http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
Module Name:
 | 
						|
 | 
						|
  Cpu.c
 | 
						|
 | 
						|
Abstract:
 | 
						|
 | 
						|
  Unix Emulation Architectural Protocol Driver as defined in Tiano.
 | 
						|
  This CPU module abstracts the interrupt subsystem of a platform and
 | 
						|
  the CPU-specific setjump/long pair.  Other services are not implemented
 | 
						|
  in this driver.
 | 
						|
 | 
						|
--*/
 | 
						|
#include "PiDxe.h"
 | 
						|
#include <Protocol/Cpu.h>
 | 
						|
#include <Protocol/DataHub.h>
 | 
						|
#include <Guid/DataHubRecords.h>
 | 
						|
#include <Protocol/CpuIo.h>
 | 
						|
#include <Protocol/FrameworkHii.h>
 | 
						|
#include <Guid/DataHubProducer.h>
 | 
						|
 | 
						|
#include <Library/BaseLib.h>
 | 
						|
#include <Library/DebugLib.h>
 | 
						|
#include <Library/HiiLib.h>
 | 
						|
#include <Library/UefiLib.h>
 | 
						|
#include <Library/UefiDriverEntryPoint.h>
 | 
						|
#include <Library/BaseMemoryLib.h>
 | 
						|
#include <Library/MemoryAllocationLib.h>
 | 
						|
#include <Library/UefiBootServicesTableLib.h>
 | 
						|
#include <Framework/DataHubRecords.h>
 | 
						|
#include "CpuDriver.h"
 | 
						|
#include "UnixDxe.h"
 | 
						|
#include <Protocol/UnixIo.h>
 | 
						|
 | 
						|
#define EFI_CPU_DATA_MAXIMUM_LENGTH 0x100
 | 
						|
 | 
						|
CPU_ARCH_PROTOCOL_PRIVATE mCpuTemplate = {
 | 
						|
  CPU_ARCH_PROT_PRIVATE_SIGNATURE,
 | 
						|
  NULL,
 | 
						|
  {
 | 
						|
    UnixFlushCpuDataCache,
 | 
						|
    UnixEnableInterrupt,
 | 
						|
    UnixDisableInterrupt,
 | 
						|
    UnixGetInterruptState,
 | 
						|
    UnixInit,
 | 
						|
    UnixRegisterInterruptHandler,
 | 
						|
    UnixGetTimerValue,
 | 
						|
    UnixSetMemoryAttributes,
 | 
						|
    0,
 | 
						|
    4
 | 
						|
  },
 | 
						|
  {
 | 
						|
    CpuMemoryServiceRead,
 | 
						|
    CpuMemoryServiceWrite,
 | 
						|
    CpuIoServiceRead,
 | 
						|
    CpuIoServiceWrite
 | 
						|
  },
 | 
						|
  0,
 | 
						|
  TRUE
 | 
						|
};
 | 
						|
 | 
						|
typedef union {
 | 
						|
  EFI_CPU_DATA_RECORD *DataRecord;
 | 
						|
  UINT8               *Raw;
 | 
						|
} EFI_CPU_DATA_RECORD_BUFFER;
 | 
						|
 | 
						|
EFI_SUBCLASS_TYPE1_HEADER mCpuDataRecordHeader = {
 | 
						|
  EFI_PROCESSOR_SUBCLASS_VERSION,       // Version
 | 
						|
  sizeof (EFI_SUBCLASS_TYPE1_HEADER),   // Header Size
 | 
						|
  0,                                    // Instance, Initialize later
 | 
						|
  EFI_SUBCLASS_INSTANCE_NON_APPLICABLE, // SubInstance
 | 
						|
  0                                     // RecordType, Initialize later
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// Service routines for the driver
 | 
						|
//
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixFlushCpuDataCache (
 | 
						|
  IN EFI_CPU_ARCH_PROTOCOL  *This,
 | 
						|
  IN EFI_PHYSICAL_ADDRESS   Start,
 | 
						|
  IN UINT64                 Length,
 | 
						|
  IN EFI_CPU_FLUSH_TYPE     FlushType
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This routine would provide support for flushing the CPU data cache.
 | 
						|
  In the case of UNIX emulation environment, this flushing is not necessary and
 | 
						|
  is thus not implemented.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Pointer to CPU Architectural Protocol interface
 | 
						|
  Start adddress in memory to flush
 | 
						|
  Length of memory to flush
 | 
						|
  Flush type
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status
 | 
						|
    EFI_SUCCESS
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    This - add argument and description to function comment
 | 
						|
// TODO:    FlushType - add argument and description to function comment
 | 
						|
// TODO:    EFI_UNSUPPORTED - add return value to function comment
 | 
						|
{
 | 
						|
  if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
 | 
						|
    //
 | 
						|
    // Only WB flush is supported. We actually need do nothing on UNIX emulator
 | 
						|
    // environment. Classify this to follow EFI spec
 | 
						|
    //
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Other flush types are not supported by UNIX emulator
 | 
						|
  //
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixEnableInterrupt (
 | 
						|
  IN EFI_CPU_ARCH_PROTOCOL  *This
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This routine provides support for emulation of the interrupt enable of the
 | 
						|
  the system.  For our purposes, CPU enable is just a BOOLEAN that the Timer
 | 
						|
  Architectural Protocol observes in order to defer behaviour while in its
 | 
						|
  emulated interrupt, or timer tick.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Pointer to CPU Architectural Protocol interface
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status
 | 
						|
    EFI_SUCCESS
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    This - add argument and description to function comment
 | 
						|
{
 | 
						|
  CPU_ARCH_PROTOCOL_PRIVATE *Private;
 | 
						|
 | 
						|
  Private                 = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
  Private->InterruptState = TRUE;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixDisableInterrupt (
 | 
						|
  IN EFI_CPU_ARCH_PROTOCOL  *This
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This routine provides support for emulation of the interrupt disable of the
 | 
						|
  the system.  For our purposes, CPU enable is just a BOOLEAN that the Timer
 | 
						|
  Architectural Protocol observes in order to defer behaviour while in its
 | 
						|
  emulated interrupt, or timer tick.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Pointer to CPU Architectural Protocol interface
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status
 | 
						|
    EFI_SUCCESS
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    This - add argument and description to function comment
 | 
						|
{
 | 
						|
  CPU_ARCH_PROTOCOL_PRIVATE *Private;
 | 
						|
 | 
						|
  Private                 = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
  Private->InterruptState = FALSE;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixGetInterruptState (
 | 
						|
  IN EFI_CPU_ARCH_PROTOCOL  *This,
 | 
						|
  OUT BOOLEAN               *State
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This routine provides support for emulation of the interrupt disable of the
 | 
						|
  the system.  For our purposes, CPU enable is just a BOOLEAN that the Timer
 | 
						|
  Architectural Protocol observes in order to defer behaviour while in its
 | 
						|
  emulated interrupt, or timer tick.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Pointer to CPU Architectural Protocol interface
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status
 | 
						|
    EFI_SUCCESS
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    This - add argument and description to function comment
 | 
						|
// TODO:    State - add argument and description to function comment
 | 
						|
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
 | 
						|
{
 | 
						|
  CPU_ARCH_PROTOCOL_PRIVATE *Private;
 | 
						|
 | 
						|
  if (State == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
  *State  = Private->InterruptState;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixInit (
 | 
						|
  IN EFI_CPU_ARCH_PROTOCOL  *This,
 | 
						|
  IN EFI_CPU_INIT_TYPE      InitType
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This routine would support generation of a CPU INIT.  At
 | 
						|
  present, this code does not provide emulation.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Pointer to CPU Architectural Protocol interface
 | 
						|
  INIT Type
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status
 | 
						|
    EFI_UNSUPPORTED - not yet implemented
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    This - add argument and description to function comment
 | 
						|
// TODO:    InitType - add argument and description to function comment
 | 
						|
{
 | 
						|
  CPU_ARCH_PROTOCOL_PRIVATE *Private;
 | 
						|
 | 
						|
  Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixRegisterInterruptHandler (
 | 
						|
  IN EFI_CPU_ARCH_PROTOCOL      *This,
 | 
						|
  IN EFI_EXCEPTION_TYPE         InterruptType,
 | 
						|
  IN EFI_CPU_INTERRUPT_HANDLER  InterruptHandler
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This routine would support registration of an interrupt handler.  At
 | 
						|
  present, this code does not provide emulation.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Pointer to CPU Architectural Protocol interface
 | 
						|
  Pointer to interrupt handlers
 | 
						|
  Interrupt type
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status
 | 
						|
    EFI_UNSUPPORTED - not yet implemented
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    This - add argument and description to function comment
 | 
						|
// TODO:    InterruptType - add argument and description to function comment
 | 
						|
// TODO:    InterruptHandler - add argument and description to function comment
 | 
						|
{
 | 
						|
  CPU_ARCH_PROTOCOL_PRIVATE *Private;
 | 
						|
 | 
						|
  //
 | 
						|
  // Do parameter checking for EFI spec conformance
 | 
						|
  //
 | 
						|
  if (InterruptType < 0 || InterruptType > 0xff) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Do nothing for Nt32 emulation
 | 
						|
  //
 | 
						|
  Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixGetTimerValue (
 | 
						|
  IN  EFI_CPU_ARCH_PROTOCOL *This,
 | 
						|
  IN  UINT32                TimerIndex,
 | 
						|
  OUT UINT64                *TimerValue,
 | 
						|
  OUT UINT64                *TimerPeriod OPTIONAL
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This routine would support querying of an on-CPU timer.  At present,
 | 
						|
  this code does not provide timer emulation.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  This        - Pointer to CPU Architectural Protocol interface
 | 
						|
  TimerIndex  - Index of given CPU timer
 | 
						|
  TimerValue  - Output of the timer
 | 
						|
  TimerPeriod - Output of the timer period
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_UNSUPPORTED       - not yet implemented
 | 
						|
  EFI_INVALID_PARAMETER - TimeValue is NULL
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  if (TimerValue == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // No timer supported
 | 
						|
  //
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixSetMemoryAttributes (
 | 
						|
  IN EFI_CPU_ARCH_PROTOCOL  *This,
 | 
						|
  IN EFI_PHYSICAL_ADDRESS   BaseAddress,
 | 
						|
  IN UINT64                 Length,
 | 
						|
  IN UINT64                 Attributes
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This routine would support querying of an on-CPU timer.  At present,
 | 
						|
  this code does not provide timer emulation.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Pointer to CPU Architectural Protocol interface
 | 
						|
  Start address of memory region
 | 
						|
  The size in bytes of the memory region
 | 
						|
  The bit mask of attributes to set for the memory region
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status
 | 
						|
    EFI_UNSUPPORTED - not yet implemented
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    This - add argument and description to function comment
 | 
						|
// TODO:    BaseAddress - add argument and description to function comment
 | 
						|
// TODO:    Length - add argument and description to function comment
 | 
						|
// TODO:    Attributes - add argument and description to function comment
 | 
						|
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
 | 
						|
{
 | 
						|
  CPU_ARCH_PROTOCOL_PRIVATE *Private;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check for invalid parameter for Spec conformance
 | 
						|
  //
 | 
						|
  if (Length == 0) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Do nothing for Nt32 emulation
 | 
						|
  //
 | 
						|
  Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
CpuUpdateDataHub (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  This function will log processor version and frequency data to data hub.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Event        - Event whose notification function is being invoked.
 | 
						|
  Context      - Pointer to the notification function's context.
 | 
						|
 | 
						|
Returns:
 | 
						|
  None.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  EFI_CPU_DATA_RECORD_BUFFER  RecordBuffer;
 | 
						|
  UINT32                      HeaderSize;
 | 
						|
  UINT32                      TotalSize;
 | 
						|
  EFI_DATA_HUB_PROTOCOL       *DataHub;
 | 
						|
  EFI_HII_HANDLE              HiiHandle;
 | 
						|
 | 
						|
  //
 | 
						|
  // Locate DataHub protocol.
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, &DataHub);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize data record header
 | 
						|
  //
 | 
						|
  mCpuDataRecordHeader.Instance = 1;
 | 
						|
  HeaderSize                    = sizeof (EFI_SUBCLASS_TYPE1_HEADER);
 | 
						|
 | 
						|
  RecordBuffer.Raw              = AllocatePool (HeaderSize + EFI_CPU_DATA_MAXIMUM_LENGTH);
 | 
						|
  if (RecordBuffer.Raw == NULL) {
 | 
						|
    return ;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize strings to HII database
 | 
						|
  //
 | 
						|
  HiiLibAddPackages (1, &gEfiProcessorProducerGuid, NULL, &HiiHandle, CpuStrings);
 | 
						|
  
 | 
						|
 | 
						|
  CopyMem (RecordBuffer.Raw, &mCpuDataRecordHeader, HeaderSize);
 | 
						|
 | 
						|
 | 
						|
  RecordBuffer.DataRecord->DataRecordHeader.RecordType      = ProcessorVersionRecordType;
 | 
						|
  RecordBuffer.DataRecord->VariableRecord.ProcessorVersion  = STRING_TOKEN (STR_INTEL_GENUINE_PROCESSOR);
 | 
						|
  TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_VERSION_DATA);
 | 
						|
 | 
						|
  Status = DataHub->LogData (
 | 
						|
                      DataHub,
 | 
						|
                      &gEfiProcessorSubClassGuid,
 | 
						|
                      &gEfiProcessorProducerGuid,
 | 
						|
                      EFI_DATA_RECORD_CLASS_DATA,
 | 
						|
                      RecordBuffer.Raw,
 | 
						|
                      TotalSize
 | 
						|
                      );
 | 
						|
 | 
						|
  //
 | 
						|
  // Store CPU frequency data record to data hub - It's an emulator so make up a value
 | 
						|
  //
 | 
						|
  RecordBuffer.DataRecord->DataRecordHeader.RecordType                    = ProcessorCoreFrequencyRecordType;
 | 
						|
  RecordBuffer.DataRecord->VariableRecord.ProcessorCoreFrequency.Value    = 1234;
 | 
						|
  RecordBuffer.DataRecord->VariableRecord.ProcessorCoreFrequency.Exponent = 6;
 | 
						|
  TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_CORE_FREQUENCY_DATA);
 | 
						|
 | 
						|
  Status = DataHub->LogData (
 | 
						|
                      DataHub,
 | 
						|
                      &gEfiProcessorSubClassGuid,
 | 
						|
                      &gEfiProcessorProducerGuid,
 | 
						|
                      EFI_DATA_RECORD_CLASS_DATA,
 | 
						|
                      RecordBuffer.Raw,
 | 
						|
                      TotalSize
 | 
						|
                      );
 | 
						|
 | 
						|
  FreePool (RecordBuffer.Raw);
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
InitializeCpu (
 | 
						|
  IN EFI_HANDLE        ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE  *SystemTable
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Initialize the state information for the CPU Architectural Protocol
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  ImageHandle of the loaded driver
 | 
						|
  Pointer to the System Table
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status
 | 
						|
 | 
						|
  EFI_SUCCESS           - protocol instance can be published
 | 
						|
  EFI_OUT_OF_RESOURCES  - cannot allocate protocol data structure
 | 
						|
  EFI_DEVICE_ERROR      - cannot create the thread
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    SystemTable - add argument and description to function comment
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
 | 
						|
  CpuUpdateDataHub ();
 | 
						|
 | 
						|
  Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                  &mCpuTemplate.Handle,
 | 
						|
                  &gEfiCpuArchProtocolGuid,   &mCpuTemplate.Cpu,
 | 
						|
                  &gEfiCpuIoProtocolGuid,     &mCpuTemplate.CpuIo,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  DEBUG ((EFI_D_ERROR, "CPU Architectural Protocol Loaded\n"));
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 |