/** * Function probe all legal Target and Lun, find valid Target and Lun * which point to the present device on SCSI channel * @param a pointer of EFI_SCSI_PASS_THRU_PROTOCOL. * @param a pointer of Target. * @param a pointer of Lun. * @return EFI_SUCCESS if get the valid Target and Lun successfully. */ EFI_STATUS GetPresentTargetLun( IN EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru, IN OUT UINT32 *Target, IN OUT UINT64 *Lun ) { EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET Packet; UINT8 Cdb[6]; UINT8 *Data; EFI_STATUS Status = EFI_SUCCESS; Data = (UINT8 *)AllocateZeroPool (ScsiPassThru->Mode->IoAlign + 96); while (EFI_NOT_FOUND != ScsiPassThru->GetNextDevice (ScsiPassThru, Target, Lun)) { // // Initialize the Request Packet. // EfiCommonLibZeroMem (&Packet, sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET)); EfiCommonLibZeroMem (Cdb, 6); EfiCommonLibZeroMem (Data, ScsiPassThru->Mode->IoAlign + 96); // Set to OP_INQUIRY. Cdb[0] = 0x12; Cdb[1] = (UINT8)(((UINT8)(*Lun) << 5) & 0xE0); Cdb[4] = 96; Packet.Timeout = EfiScsiStallSeconds (2); Packet.Cdb = Cdb; Packet.CdbLength = 6; if((ScsiPassThru->Mode->IoAlign == 0)|| (ScsiPassThru->Mode->IoAlign == 1)){ Packet.DataBuffer = (VOID *)Data; } else { Packet.DataBuffer = (VOID *)(((UINTN)Data + ScsiPassThru->Mode->IoAlign - 1) & ~(ScsiPassThru->Mode->IoAlign - 1)); } Packet.TransferLength = 96; Packet.DataDirection = 0; Status = ScsiPassThru->PassThru (ScsiPassThru, *Target, *Lun, &Packet, NULL); if (Status == EFI_SUCCESS) break; } FreePool(Data); return Status; }
VOID ZeroMem ( IN VOID *Buffer, IN UINTN Size ) /*++ Routine Description: Set Buffer to zero for Size bytes. Arguments: Buffer - Memory to set. Size - Number of bytes to set Returns: None --*/ { EfiCommonLibZeroMem (Buffer, Size); }
VOID * PreparePageTable ( VOID *PageNumberTop, UINT8 SizeOfMemorySpace ) /*++ Description: Generate pagetable below PageNumberTop, and return the bottom address of pagetable for putting other things later. --*/ { VOID *PageNumberBase; PageNumberBase = (VOID *)((UINTN)PageNumberTop - EFI_PAGE_NUMBER * EFI_PAGE_SIZE_4K); EfiCommonLibZeroMem (PageNumberBase, EFI_PAGE_NUMBER * EFI_PAGE_SIZE_4K); Ia32Create4MPageTables (PageNumberBase); Ia32Create4KPageTables (PageNumberBase); // // Not enable NULL Pointer Protection if using INTX call // // EnableNullPointerProtection (PageNumberBase); return PageNumberBase; }
VOID EfiCommonLibSetMem ( IN VOID *Buffer, IN UINTN Size, IN UINT8 Value ) /*++ Routine Description: Set Buffer to Value for Size bytes. Arguments: Buffer - Memory to set. Size - Number of bytes to set Value - Value of the set operation. Returns: None --*/ { INT8 *Ptr; if (Value == 0) { EfiCommonLibZeroMem (Buffer, Size); } else { Ptr = Buffer; while (Size--) { *(Ptr++) = Value; } } }
// // TDS 4.5 // EFI_STATUS BBTestPassThruConformanceAutoTest ( IN EFI_BB_TEST_PROTOCOL *This, IN VOID *ClientInterface, IN EFI_TEST_LEVEL TestLevel, IN EFI_HANDLE SupportHandle ) { EFI_STANDARD_TEST_LIBRARY_PROTOCOL *StandardLib; EFI_STATUS Status; EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru; EFI_TEST_ASSERTION AssertionType; UINT32 Target; UINT64 Lun; EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET Packet; UINT8 Cdb[6]; UINT8 Data[100]; //UINT8 Count; // // Get the Standard Library Interface // Status = gtBS->HandleProtocol ( SupportHandle, &gEfiStandardTestLibraryGuid, &StandardLib ); if (EFI_ERROR(Status)) { StandardLib->RecordAssertion ( StandardLib, EFI_TEST_ASSERTION_FAILED, gTestGenericFailureGuid, L"BS.HandleProtocol - Handle standard test library", L"%a:%d:Status - %r", __FILE__, __LINE__, Status ); return Status; } ScsiPassThru = (EFI_SCSI_PASS_THRU_PROTOCOL *)ClientInterface; // // Assertion Point 4.5.2.1 // Call PassThru() with too long TransferLength. // Status = GetScsiDevice (ScsiPassThru, &Target, &Lun); if (EFI_ERROR(Status)) { StandardLib->RecordAssertion ( StandardLib, EFI_TEST_ASSERTION_FAILED, gTestGenericFailureGuid, L"Can't Get any Scsi Device", L"%a:%d:Status - %r", __FILE__, __LINE__, Status ); return EFI_UNSUPPORTED; } // // Initialize the Request Packet. // EfiCommonLibZeroMem (&Packet, sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET)); EfiCommonLibZeroMem (Cdb, 6); EfiCommonLibZeroMem (Data, 100); // Set to OP_INQUIRY. Cdb[0] = 0x12; Cdb[1] = (UINT8)(((UINT8)Lun << 5) & 0xE0); Cdb[4] = 100; Packet.Timeout = 0; Packet.Cdb = Cdb; Packet.CdbLength = 6; Packet.DataBuffer = Data; Packet.TransferLength = 0xFFFFFFFF; Packet.DataDirection = 0; Status = ScsiPassThru->PassThru (ScsiPassThru, Target, Lun, &Packet, NULL); if (Status == EFI_BAD_BUFFER_SIZE) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gScsiPassThruBBTestConformanceAssertionGuid013, L"EFI_SCSI_PASS_THRU_PROTOCOL.PassThru - Call PassThru() with with too long TransferLength", L"%a:%d:Status - %r, Target - %d, Lun - %ld, The max length is %d", __FILE__, __LINE__, Status, Target, Lun, Packet.TransferLength ); // // Assertion Point 4.5.2.3 // Call PassThru() with invalid parameter. // EfiCommonLibZeroMem (&Packet, sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET)); EfiCommonLibZeroMem (Cdb, 6); EfiCommonLibZeroMem (Data, 100); // Set to OP_INQUIRY. Cdb[0] = 0x12; Cdb[1] = (UINT8)(((UINT8)Lun << 5) & 0xE0); Cdb[4] = 100; Packet.Timeout = 0; Packet.Cdb = Cdb; Packet.CdbLength = 6; Packet.DataBuffer = Data; Packet.TransferLength = 100; Packet.DataDirection = 0; // // Check Point 1. Invalid Target // Status = ScsiPassThru->PassThru (ScsiPassThru, 0xEEEEEEEE, Lun, &Packet, NULL); if (Status == EFI_INVALID_PARAMETER) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gScsiPassThruBBTestConformanceAssertionGuid016, L"EFI_SCSI_PASS_THRU_PROTOCOL.PassThru - Call PassThru() with invalid Target", L"%a:%d:Status - %r", __FILE__, __LINE__, Status ); // // Check Point 2. Invalid Lun // EfiCommonLibZeroMem (&Packet, sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET)); EfiCommonLibZeroMem (Cdb, 6); EfiCommonLibZeroMem (Data, 100); // Set to OP_INQUIRY. Cdb[0] = 0x12; Cdb[1] = (UINT8)(((UINT8)Lun << 5) & 0xE0); Cdb[4] = 100; Packet.Timeout = 0; Packet.Cdb = Cdb; Packet.CdbLength = 6; Packet.DataBuffer = Data; Packet.TransferLength = 100; Packet.DataDirection = 0; Status = ScsiPassThru->PassThru (ScsiPassThru, Target, 0xEEEEEEEE, &Packet, NULL); if (Status == EFI_INVALID_PARAMETER) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gScsiPassThruBBTestConformanceAssertionGuid017, L"EFI_SCSI_PASS_THRU_PROTOCOL.PassThru - Call PassThru() with invalid Lun", L"%a:%d:Status - %r", __FILE__, __LINE__, Status ); // // Check Point 3. Invalid ScsiRequestPacket. // EfiCommonLibZeroMem (&Packet, sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET)); Status = ScsiPassThru->PassThru (ScsiPassThru, Target, Lun, &Packet, NULL); if (Status == EFI_INVALID_PARAMETER) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gScsiPassThruBBTestConformanceAssertionGuid018, L"EFI_SCSI_PASS_THRU_PROTOCOL.PassThru - Call PassThru() with invalid ScsiRequestPacket", L"%a:%d:Status - %r", __FILE__, __LINE__, Status ); return EFI_SUCCESS; }
// // TDS 3.3 // EFI_STATUS BBTestReadFunctionManualTest ( IN EFI_BB_TEST_PROTOCOL *This, IN VOID *ClientInterface, IN EFI_TEST_LEVEL TestLevel, IN EFI_HANDLE SupportHandle ) { EFI_STANDARD_TEST_LIBRARY_PROTOCOL *StandardLib; EFI_STATUS Status; EFI_DEBUGPORT_PROTOCOL *DebugPort; EFI_TEST_ASSERTION AssertionType; UINTN BufferSize; CHAR8 Buffer[20]; UINTN WaitIndex; EFI_INPUT_KEY Key; // // Get the Standard Library Interface // Status = gtBS->HandleProtocol ( SupportHandle, &gEfiStandardTestLibraryGuid, &StandardLib ); if (EFI_ERROR(Status)) { StandardLib->RecordAssertion ( StandardLib, EFI_TEST_ASSERTION_FAILED, gTestGenericFailureGuid, L"BS.HandleProtocol - Handle standard test library", L"%a:%d:Status - %r", __FILE__, (UINTN)__LINE__, Status ); return Status; } DebugPort = (EFI_DEBUGPORT_PROTOCOL *)ClientInterface; // // Assertion Point 3.3.2.1 // Call Read() to send data to debug port with enough time. // BufferSize = 1; EfiCommonLibZeroMem ((VOID*)Buffer, sizeof(Buffer)); // // Wait for the input data. // Print (L"Please any key after input data."); gtBS->WaitForEvent (1, &(gtST->ConIn->WaitForKey), &WaitIndex); gtST->ConIn->ReadKeyStroke (gtST->ConIn, &Key); Status = DebugPort->Read (DebugPort, 1000, &BufferSize, (VOID*)Buffer); if (EFI_ERROR(Status)) { AssertionType = EFI_TEST_ASSERTION_FAILED; } else { AssertionType = EFI_TEST_ASSERTION_PASSED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gDebugPortBBTestFunctionAssertionGuid006, L"EFI_DEBUGPORT_PROTOCOL.Read - Invoke Read and verify interface correctness with enough time", L"%a:%d:Status - %r", __FILE__, (UINTN)__LINE__, Status ); // // Verify the functionality manually. // Print (L"Please verify the input string is %s, right press \"Y\", wrong press \"N\"", Buffer); // // Get the input key. // while(1) { gtBS->WaitForEvent (1, &(gtST->ConIn->WaitForKey), &WaitIndex); gtST->ConIn->ReadKeyStroke (gtST->ConIn, &Key); if((Key.UnicodeChar == L'Y') || (Key.UnicodeChar == L'y') || (Key.UnicodeChar == L'N') || (Key.UnicodeChar == L'n')) { break; } else { Print (L"Please press \"Y\" or \"N\""); } } if ((Key.UnicodeChar == L'N') || (Key.UnicodeChar == L'n')) { AssertionType = EFI_TEST_ASSERTION_FAILED; } else { AssertionType = EFI_TEST_ASSERTION_PASSED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gDebugPortBBTestFunctionAssertionGuid007, L"EFI_DEBUGPORT_PROTOCOL.Read - Invoke Read and verify its functionality correctness with enough time", L"%a:%d:Status - %r", __FILE__, (UINTN)__LINE__, Status ); return EFI_SUCCESS; }
EFI_STATUS EFIAPI AmdRasSmmDxeDriverEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; BOOLEAN InSmm; EFI_HANDLE hNrthBrdgError = NULL; EFI_SMM_BASE_PROTOCOL *SmmBase = NULL; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage = NULL; EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath = NULL; EFI_DEVICE_PATH_PROTOCOL *NewFilePath = NULL; AMD_RAS_DXE_INTERFACE_PROTOCOL *RasIntProtocol = NULL; SMM_SETUP_CONFIG SmmSetupCfg; // Initialize Global Variables Status = InitializeRasRuntime ( ImageHandle, // IN EFI_HANDLE SystemTable // IN EFI_SYSTEM_TABLE ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; // Error detected while trying to locate SMM Base Protocol } // Locate SMM Base Protocol Status = gBS->LocateProtocol ( &gEfiSmmBaseProtocolGuid, // IN EFI_GUID Published unique identifier of requested protocol GUID to locate NULL, // IN VOID* Published unique identifier of requested protocol GUID &SmmBase // OUT VOID** Returns address of pointer for SMM Base protocol interface ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; // Error detected while trying to locate SMM Base Protocol } // Save the SMM Base system table pointer SmmBase->GetSmstLocation (SmmBase, &gSmst); // Determine if we are in SMM or not SmmBase->InSmm (SmmBase, &InSmm); if (!InSmm) { // // Not in SMM so load this driver's SMM image to memory // // Configure Northbridge Interrupt Event to make an I/O Write to SMI Command Port in the // Southbridge and cause a Software SMI for which we will handle in the NbSmiHandler // SMI service routine. Status = ConfigNbSmiProcessing (); // Query image handle to see if it supports a requested protocol and then get an address of the protocol image to be loaded Status = gBS->HandleProtocol ( ImageHandle, // Handle of requested protocol &gEfiLoadedImageProtocolGuid, // Published unique identifier of requested protocol GUID (VOID*)&LoadedImage // Returns address of pointer for requested protocol interface of the image ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; // Error detected while trying to query LoadImage protocol } // Query device handle of loaded image to see if it supports a requested protocol and then get an address of the prototocl device path Status = gBS->HandleProtocol ( LoadedImage->DeviceHandle, // Handle of requested protocol &gEfiDevicePathProtocolGuid, // Published unique identifier of requested protocol GUID (VOID*)&ImageDevicePath // Returns address of pointer for requested protocol interface ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; } // Add this image's device path to the loaded image device path image and return // a pointer to the new file path. NewFilePath = AddDevicePath ( ImageDevicePath, // IN EFI_DEVICE_PATH_PROTOCOL LoadedImage->FilePath // IN EFI_DEVICE_PATH_PROTOCOL Device Path Image to add ); //Load the image in System Management RAM; it will automatically generate SMI. Status = SmmBase->Register ( SmmBase, // IN *This Addreess of pointer for SMM Base protocol interface) NewFilePath, // IN EFI_DEVICE_PATH_PROTOCOL NULL, // IN SourceBuffer OPTIONAL 0, // IN SourceSize OPTIONAL &hNrthBrdgError, // OUT *ImageHandle FALSE // IN LegacyIA32Binary OPTIONAL ); // Free up residual heap memory if not equal to NULL if (NewFilePath) { gBS->FreePool (NewFilePath); } } else { // We are in SMM // // Callout to use platform-specific Setup // Status = AmdRasSmmCallout (ECC_HNDLR_CALLOUT_ID, &SmmSetupCfg); if (EFI_ERROR (Status)) { SmmSetupCfg.EccHandlerEnable = FALSE; //Load default value = ECC Disabled } // Enable / Disable RAS MCA ECC Support if (SmmSetupCfg.EccHandlerEnable == TRUE) { // Callback to execute from within SMM, error occurs if called from Boot Services mode Status = SmmBase->RegisterCallback ( SmmBase, // IN *This ImageHandle, // IN SmmImageHandle MC4SmmHandler, // IN EFI SMM Dispatcher Callback Entry Point Address FALSE, // IN Makelast (SMM Dispatcher should call this handler last) OPTIONAL FALSE // IN FloatingPointSave OPTIONAL ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; } // Update Global Varibles for this driver Status = UpdateGlobalVars (); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; } } //End-- Enable / Disable ECC Handler Support } // End-- if(!InSmm) if (!InSmm) { // Allocate memory for a new protocol structure Status = gBS->AllocatePool ( EfiBootServicesData, sizeof (AMD_RAS_DXE_INTERFACE_PROTOCOL), &RasIntProtocol ); if (RasIntProtocol == NULL) { return EFI_OUT_OF_RESOURCES; } // Zero out memory buffer EfiCommonLibZeroMem ( RasIntProtocol, sizeof (AMD_RAS_DXE_INTERFACE_PROTOCOL) ); // Locate AMD RAS Interface Protocol Status = gBS->LocateProtocol ( &gAmdRasDxeInterfaceProtocolGuid, // IN EFI_GUID Published unique identifier of requested protocol GUID to locate NULL, // IN VOID* Published unique identifier of requested protocol GUID (VOID **)&RasIntProtocol // OUT VOID** Returns address of pointer for SMM Base protocol interface ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; // Error detected while trying to locate RAS Interface Protocol } // Callout to get ECC Threshold BIOS Setup option config. Status = AmdRasSmmCallout (ECC_THRESH_COUNTER_CALLOUT_ID, &SmmSetupCfg); if (EFI_ERROR (Status)) { gRasNbCorrMemConfig.ThreshLimit = 0xFFE; // Load default value = threshold value of 1 (1's complement) } else { gRasNbCorrMemConfig.ThreshLimit = SmmSetupCfg.DramErrorThreshold; } // Callout to get RAS Handle Type BIOS Setup option config. Status = AmdRasSmmCallout (RAS_HANDLE_CALLOUT_ID, &SmmSetupCfg); if (EFI_ERROR (Status)) { gRasNbCorrMemConfig.DevCommon.ErrorMonitorType = APIC; // Default to APIC interrupt = 1 on error } else { if (SmmSetupCfg.RasHandleType == 1) { gRasNbCorrMemConfig.DevCommon.ErrorMonitorType = APIC; // APIC interrupt = 1 } } // Configure Correctable Memory Error Operation Status = RasIntProtocol->AmdSetErrorConfigDevice ( RasIntProtocol, // IN *This gRasNbCorrMemConfig.DevCommon.DeviceID, // IN UINTN (enum AMD_RAS_DEVICE_ID) (VOID*) &gRasNbCorrMemConfig // IN OUT VOID* RAS Device Struct ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; // Error detected while trying to locate SMM Base Protocol } // Configure UnCorrectable Memory Error Operation Status = RasIntProtocol->AmdSetErrorConfigDevice ( RasIntProtocol, // IN *This gRasNbUnCorrMemConfig.DevCommon.DeviceID, // IN UINTN (enum AMD_RAS_DEVICE_ID) (VOID*) &gRasNbUnCorrMemConfig // IN OUT VOID* RAS Device Struct ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; // Error detected while trying to locate SMM Base Protocol } } // End-- if (!InSmm) return Status; }
EFI_STATUS EFIAPI AmdRasApeiDxeDriverEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status = EFI_SUCCESS; EFI_HANDLE Handle = NULL; EFI_HANDLE hEinj = NULL; AMD_RAS_APEI_PROTOCOL *AmdRasApeiProtocol; BOOLEAN InSmm; EFI_SMM_BASE_PROTOCOL *SmmBase = NULL; EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath = NULL; EFI_DEVICE_PATH_PROTOCOL *NewFilePath = NULL; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage = NULL; EFI_SMM_SW_DISPATCH_PROTOCOL *SwDispatch = NULL; EFI_SMM_SW_DISPATCH_CONTEXT SwContext; EFI_ACPI_SUPPORT_PROTOCOL *AcpiSupportProtocol = NULL; EFI_HANDLE SwHandle = NULL; EFI_HANDLE hNewHandle = NULL; UINTN BufferSize; UINTN HestTblHandle; UINT64 Address64; UINT32 Value32; // // Initialize Local Variables // InSmm = FALSE; BufferSize = 0; HestTblHandle = 0; // // Initialize Global Variables // EfiInitializeApei (ImageHandle, SystemTable); // Locate SMM Base Protocol Status = gBS->LocateProtocol ( &gEfiSmmBaseProtocolGuid, // IN EFI_GUID Published unique identifier of requested protocol GUID to locate NULL, // IN VOID* Published unique identifier of requested protocol GUID &SmmBase // OUT VOID** Returns address of pointer for SMM Base protocol interface ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; // Error detected while trying to locate SMM Base Protocol } // Save the SMM Base system table pointer SmmBase->GetSmstLocation (SmmBase, &gSmst); // Determine if we are in SMM or not SmmBase->InSmm (SmmBase, &InSmm); if (!InSmm) { // Query image handle to see if it supports a requested protocol and then get an address of the protocol image to be loaded Status = gBS->HandleProtocol ( ImageHandle, // Handle of requested protocol &gEfiLoadedImageProtocolGuid, // Published unique identifier of requested protocol GUID (VOID*)&LoadedImage // Returns address of pointer for requested protocol interface of the image ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; // Error detected while trying to query LoadImage protocol } // Query device handle of loaded image to see if it supports a requested protocol and then get an address of the prototocl device path Status = gBS->HandleProtocol ( LoadedImage->DeviceHandle, // Handle of requested protocol &gEfiDevicePathProtocolGuid, // Published unique identifier of requested protocol GUID (VOID*) &ImageDevicePath // Returns address of pointer for requested protocol interface ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; } // Add this image's device path to the loaded image device path image and return // a pointer to the new file path. NewFilePath = AddDevicePath ( ImageDevicePath, // IN EFI_DEVICE_PATH_PROTOCOL* LoadedImage->FilePath // IN EFI_DEVICE_PATH_PROTOCOL* Device Path Image to add ); //Load the image in System Management RAM; it will automatically generate an SMI. Status = SmmBase->Register ( SmmBase, // IN *This Addreess of pointer for SMM Base protocol interface) NewFilePath, // IN EFI_DEVICE_PATH_PROTOCOL NULL, // IN SourceBuffer OPTIONAL 0, // IN SourceSize OPTIONAL &hEinj, // OUT *ImageHandle FALSE // IN LegacyIA32Binary OPTIONAL ); // Free up residual heap memory if not equal to NULL if (NewFilePath) { gBS->FreePool (NewFilePath); } if (EFI_ERROR (Status)) { switch (EFIERR (Status)) { case EFI_LOAD_ERROR: break; case EFI_INVALID_PARAMETER: break; case EFI_UNSUPPORTED: break; default: ; } return Status; } } else { // We are in SMM... // Allocate Memory for type Runtime Services Data - APEI Module Private Data Status = gBS->AllocatePool (EfiRuntimeServicesData, sizeof (APEI_DRIVER_PRIVATE_DATA), &mApeiPrivData); if (EFI_ERROR (Status)) { return Status; } // Allocate Memory for type Runtime Services Data - APEI Interface Status = gBS->AllocatePool (EfiRuntimeServicesData, sizeof (AMD_APEI_INTERFACE), &mApeiInterface); if (EFI_ERROR (Status)) { return Status; } // Locate SW SMM Dispatch Protocol Status = gBS->LocateProtocol ( &gEfiSmmSwDispatchProtocolGuid, // IN EFI_GUID Published unique identifier of requested protocol GUID to locate NULL, // IN VOID* Published unique identifier of requested protocol GUID &SwDispatch // OUT VOID** Returns address of pointer for SMM Base protocol interface ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; } SwContext.SwSmiInputValue = EINJ_BEGIN_INJ_CMD; // Register EINJ SMM callback handler. Status = SwDispatch->Register ( SwDispatch, // IN *This ApeiEinjSwSmiHandler, // IN EFI SW SMM Dispatcher Callback Entry Point Address &SwContext, // IN SwContext &SwHandle // IN OUT SwHandle ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; } SwContext.SwSmiInputValue = ERST_EXECUTE_OPERATION_CMD; // Register ERST SMM callback handler. Status = SwDispatch->Register ( SwDispatch, ApeiErstSwSmiHandler, &SwContext, &SwHandle ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; } // Allocate Memory for the the AMD_RAS_APEI_PROTOCOL protocol. Status = gBS->AllocatePool ( EfiBootServicesData, // IN EFI_MEMORY_TYPE PoolType sizeof (AMD_RAS_APEI_PROTOCOL), // IN UINTN Size &AmdRasApeiProtocol // OUT VOID **Buffer ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return EFI_OUT_OF_RESOURCES; // Error detected while trying to locate SMM Base Protocol } EfiCommonLibZeroMem (AmdRasApeiProtocol, sizeof (AMD_RAS_APEI_PROTOCOL)); // Initialize BERT ApeiBertInit (); // Initialize HEST ApeiHestInit (); // Determine if we have ECC error enable bits set Address64 = mCfgMmioBase | ((0x18 << 15) | (3 << 12) | 0x44); //F3:44 MC4_NB_CFG Value32 = RasSmmReadMem32 (Address64); if (Value32 & (1 << 22)) { //Initialize EINJ if ECC is Enabled ApeiEinjInit (); } // Initialize ERST ApeiErstInit (); AmdRasApeiProtocol->AmdApeiInterface = mApeiInterface; mApeiInterface->ApeiPrivData = mApeiPrivData; AmdRasApeiProtocol->AddBootErrorRecordEntry = 0; AmdRasApeiProtocol->AddHestErrorSourceEntry = 0; Status = gBS->InstallProtocolInterface ( &Handle, // IN OUT EFI_HANDLE &gAmdRasApeiProtocolGuid, // IN EFI_GUID EFI_NATIVE_INTERFACE, // IN EFI_INITERFACE_TYPE AmdRasApeiProtocol // IN VOID* Interface ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return EFI_PROTOCOL_ERROR; // Error detected while trying to locate SMM Base Protocol } } // End-- if(!InSmm) // // Do more non-SMM configuration // if (!InSmm) { Status = gBS->LocateProtocol ( &gAmdRasApeiProtocolGuid, NULL, &AmdRasApeiProtocol ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return EFI_PROTOCOL_ERROR; // Error detected while trying to locate SMM Base Protocol } mApeiInterface = AmdRasApeiProtocol->AmdApeiInterface; mApeiPrivData = mApeiInterface->ApeiPrivData; // Initialize function pointers to protocol interfaces AmdRasApeiProtocol->AddBootErrorRecordEntry = &AddBertErrorRecord; AmdRasApeiProtocol->AddHestErrorSourceEntry = &AddHestErrorRecord; // // Find the protocol that was installed during SMM phase and reinstall it during // Non-SMM phase as well. // // Get the buffer size for the EFI_HANDLE BufferSize = sizeof (EFI_HANDLE); // Returns an array of handles that support a specified protocol. Status = gBS->LocateHandle ( ByProtocol, // IN EFI_LOCATE_SEARCH_TYPE SearchType &gAmdRasApeiProtocolGuid, // IN EFI_GUID *Protocol OPTIONAL NULL, // IN VOID *SearchKey OPTIONAL &BufferSize, // IN OUT UINTN BufferSize &hNewHandle // OUT EFI_HANDLE *Buffer ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return EFI_PROTOCOL_ERROR; // Error detected while trying to locate SMM Base Protocol } // Queries a handle to determine if it supports a specified protocol. Status = gBS->HandleProtocol ( hNewHandle, // IN EFI_HANDLE Handle &gAmdRasApeiProtocolGuid, // IN EFI_GUID *Protocol (VOID **) &AmdRasApeiProtocol // OUT VOID *NewInterface ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return EFI_PROTOCOL_ERROR; // Error detected while trying to locate SMM Base Protocol } // Local ACPI Protocol Status = gBS->LocateProtocol ( &gAcpiSupportGuid, NULL, (VOID **) &AcpiSupportProtocol ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return EFI_PROTOCOL_ERROR; // Error detected while trying to locate ACPI Support Protocol } //Add HEST table to the ACPI aware OS Status = AcpiSupportProtocol->SetAcpiTable ( AcpiSupportProtocol, // IN EFI_ACPI_SUPPORT_PROTOCOL *This mApeiInterface->ApeiPrivData->ApeiHestTbl, // IN VOID *Table OPTIONAL TRUE, // IN BOOLEAN Checksum EFI_ACPI_TABLE_VERSION_ALL, // IN EFI_ACPI_TABLE_VERSION Version &HestTblHandle // IN OUT UINTN *TableHandle ); ASSERT_EFI_ERROR (Status); // Reinstalls a protocol interface on a device handle. Status = gBS->ReinstallProtocolInterface ( hNewHandle, // IN EFI_HANDLE Handle &gAmdRasApeiProtocolGuid, // IN EFI_GUID *Protocol AmdRasApeiProtocol, // IN VOID *OldInterface AmdRasApeiProtocol // IN VOID *NewInterface ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return EFI_PROTOCOL_ERROR; // Error detected while trying to locate SMM Base Protocol } // Create a callback event to be executed at ReadyToBoot to publish APEI tables to OS. Status = gBS->CreateEventEx ( EFI_EVENT_NOTIFY_SIGNAL, EFI_TPL_NOTIFY, AddApeiTables, NULL, &gEfiEventReadyToBootGuid, &mEvtApeiReadyToBoot ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return EFI_OUT_OF_RESOURCES; // Error detected while trying to locate SMM Base Protocol } } return Status; }
VOID EfiLoader ( UINT32 BiosMemoryMapBaseAddress ) { BIOS_MEMORY_MAP *BiosMemoryMap; EFILDR_HEADER *EFILDRHeader; EFILDR_IMAGE *EFILDRImage; EFI_MEMORY_DESCRIPTOR EfiMemoryDescriptor[EFI_MAX_MEMORY_DESCRIPTORS]; EFI_STATUS Status; UINTN NumberOfMemoryMapEntries; UINT32 DestinationSize; UINT32 ScratchSize; UINTN BfvPageNumber; UINTN BfvBase; EFI_MAIN_ENTRYPOINT EfiMainEntrypoint; static EFILDRHANDOFF Handoff; PrintHeader ('A'); ClearScreen(); PrintString("EFI Loader\n"); // PrintString("&BiosMemoryMapBaseAddress = "); // PrintValue64 ((UINT64)(&BiosMemoryMapBaseAddress)); // PrintString(" BiosMemoryMapBaseAddress = "); // PrintValue(BiosMemoryMapBaseAddress); // PrintString("\n"); // // Add all EfiConventionalMemory descriptors to the table. If there are partial pages, then // round the start address up to the next page, and round the length down to a page boundry. // BiosMemoryMap = (BIOS_MEMORY_MAP *)(UINTN)(BiosMemoryMapBaseAddress); NumberOfMemoryMapEntries = 0; GenMemoryMap (&NumberOfMemoryMapEntries, EfiMemoryDescriptor, BiosMemoryMap); // // Get information on where the image is in memory // EFILDRHeader = (EFILDR_HEADER *)(UINTN)(EFILDR_HEADER_ADDRESS); EFILDRImage = (EFILDR_IMAGE *)(UINTN)(EFILDR_HEADER_ADDRESS + sizeof(EFILDR_HEADER)); PrintHeader ('D'); // // Point to the 4th image (Bfv) // EFILDRImage += 3; // // Decompress the image // Status = TianoGetInfo ( NULL, (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), EFILDRImage->Length, &DestinationSize, &ScratchSize ); if (EFI_ERROR (Status)) { EFI_DEADLOOP(); } Status = TianoDecompress ( NULL, (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), EFILDRImage->Length, (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS, DestinationSize, (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000), ScratchSize ); if (EFI_ERROR (Status)) { EFI_DEADLOOP(); } BfvPageNumber = EFI_SIZE_TO_PAGES (DestinationSize); BfvBase = (UINTN) FindSpace (BfvPageNumber, &NumberOfMemoryMapEntries, EfiMemoryDescriptor, EfiRuntimeServicesData, EFI_MEMORY_WB); if (BfvBase == 0) { EFI_DEADLOOP(); } EfiCommonLibZeroMem ((VOID *)(UINTN)BfvBase, BfvPageNumber * EFI_PAGE_SIZE); EfiCommonLibCopyMem ((VOID *)(UINTN)BfvBase, (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS, DestinationSize); PrintHeader ('B'); // // Point to the 2nd image (DxeIpl) // EFILDRImage -= 2; // // Decompress the image // Status = TianoGetInfo ( NULL, (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), EFILDRImage->Length, &DestinationSize, &ScratchSize ); if (EFI_ERROR (Status)) { EFI_DEADLOOP(); } Status = TianoDecompress ( NULL, (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), EFILDRImage->Length, (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS, DestinationSize, (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000), ScratchSize ); if (EFI_ERROR (Status)) { EFI_DEADLOOP(); } // // Load and relocate the EFI PE/COFF Firmware Image // Status = EfiLdrPeCoffLoadPeImage ( (VOID *)(UINTN)(EFI_DECOMPRESSED_BUFFER_ADDRESS), &DxeIplImage, &NumberOfMemoryMapEntries, EfiMemoryDescriptor ); if (EFI_ERROR (Status)) { EFI_DEADLOOP(); } // PrintString("Image.NoPages = "); // PrintValue(Image.NoPages); // PrintString("\n"); PrintHeader ('C'); // // Point to the 3rd image (DxeMain) // EFILDRImage++; // // Decompress the image // Status = TianoGetInfo ( NULL, (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), EFILDRImage->Length, &DestinationSize, &ScratchSize ); if (EFI_ERROR (Status)) { EFI_DEADLOOP(); } Status = TianoDecompress ( NULL, (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), EFILDRImage->Length, (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS, DestinationSize, (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000), ScratchSize ); if (EFI_ERROR (Status)) { EFI_DEADLOOP(); } // // Load and relocate the EFI PE/COFF Firmware Image // Status = EfiLdrPeCoffLoadPeImage ( (VOID *)(UINTN)(EFI_DECOMPRESSED_BUFFER_ADDRESS), &DxeCoreImage, &NumberOfMemoryMapEntries, EfiMemoryDescriptor ); if (EFI_ERROR (Status)) { EFI_DEADLOOP(); } PrintHeader ('E'); // // Display the table of memory descriptors. // // PrintString("\nEFI Memory Descriptors\n"); /* { UINTN Index; for (Index = 0; Index < NumberOfMemoryMapEntries; Index++) { PrintString("Type = "); PrintValue(EfiMemoryDescriptor[Index].Type); PrintString(" Start = "); PrintValue((UINT32)(EfiMemoryDescriptor[Index].PhysicalStart)); PrintString(" NumberOfPages = "); PrintValue((UINT32)(EfiMemoryDescriptor[Index].NumberOfPages)); PrintString("\n"); } } */ // // Jump to EFI Firmware // if (DxeIplImage.EntryPoint != NULL) { Handoff.MemDescCount = NumberOfMemoryMapEntries; Handoff.MemDesc = EfiMemoryDescriptor; Handoff.BfvBase = (VOID *)(UINTN)BfvBase; Handoff.BfvSize = BfvPageNumber * EFI_PAGE_SIZE; Handoff.DxeIplImageBase = (VOID *)(UINTN)DxeIplImage.ImageBasePage; Handoff.DxeIplImageSize = DxeIplImage.NoPages * EFI_PAGE_SIZE; Handoff.DxeCoreImageBase = (VOID *)(UINTN)DxeCoreImage.ImageBasePage; Handoff.DxeCoreImageSize = DxeCoreImage.NoPages * EFI_PAGE_SIZE; Handoff.DxeCoreEntryPoint = (VOID *)(UINTN)DxeCoreImage.EntryPoint; EfiMainEntrypoint = (EFI_MAIN_ENTRYPOINT)(UINTN)DxeIplImage.EntryPoint; EfiMainEntrypoint (&Handoff); } PrintHeader ('F'); // // There was a problem loading the image, so HALT the system. // EFI_DEADLOOP(); }
// // TDS 3.6 // EFI_STATUS BBTestPassThruFunctionAutoTest ( IN EFI_BB_TEST_PROTOCOL *This, IN VOID *ClientInterface, IN EFI_TEST_LEVEL TestLevel, IN EFI_HANDLE SupportHandle ) { EFI_STANDARD_TEST_LIBRARY_PROTOCOL *StandardLib; EFI_STATUS Status; EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru; EFI_TEST_ASSERTION AssertionType; UINT32 Target; UINT64 Lun; EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET Packet; UINT8 Cdb[6]; UINT8 *Data; EFI_EVENT Event; // // Get the Standard Library Interface // Status = gtBS->HandleProtocol ( SupportHandle, &gEfiStandardTestLibraryGuid, &StandardLib ); if ( EFI_ERROR(Status) ) { StandardLib->RecordAssertion ( StandardLib, EFI_TEST_ASSERTION_FAILED, gTestGenericFailureGuid, L"BS.HandleProtocol - Handle standard test library", L"%a:%d:Status - %r\n", __FILE__, (UINTN)__LINE__, Status ); return Status; } ScsiPassThru = (EFI_SCSI_PASS_THRU_PROTOCOL *)ClientInterface; // // Assertion Point 3.6.2.1 // Call PassThru() with NULL Event. // Target = 0xFFFFFFFF; Status = GetPresentTargetLun(ScsiPassThru, &Target, &Lun); if (EFI_ERROR(Status)) { StandardLib->RecordAssertion ( StandardLib, EFI_TEST_ASSERTION_FAILED, gTestGenericFailureGuid, L"Can't Get any Scsi Device", L"%a:%d:Status - %r\n", __FILE__, (UINTN)__LINE__, Status ); return EFI_UNSUPPORTED; } // // Initialize the Request Packet. // Data = (UINT8 *)AllocatePool (ScsiPassThru->Mode->IoAlign + 96); EfiCommonLibZeroMem (&Packet,sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET)); EfiCommonLibZeroMem (Cdb,6); EfiCommonLibZeroMem (Data, ScsiPassThru->Mode->IoAlign + 96); // Set to OP_INQUIRY. Cdb[0] = 0x12; Cdb[1] = (UINT8)(((UINT8)Lun << 5) & 0xE0); Cdb[4] = 96; Packet.Timeout = EfiScsiStallSeconds (2); Packet.Cdb = Cdb; Packet.CdbLength = 6; if ((ScsiPassThru->Mode->IoAlign == 0) || (ScsiPassThru->Mode->IoAlign == 1)){ Packet.DataBuffer = (VOID *)Data; } else { Packet.DataBuffer = (VOID *)(((UINTN)Data + ScsiPassThru->Mode->IoAlign - 1) & ~(ScsiPassThru->Mode->IoAlign - 1)); } Packet.TransferLength = 96; Packet.DataDirection = 0; Status = ScsiPassThru->PassThru (ScsiPassThru, Target, Lun, &Packet, NULL); if (EFI_ERROR(Status)) { AssertionType = EFI_TEST_ASSERTION_FAILED; } else { AssertionType = EFI_TEST_ASSERTION_PASSED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gScsiPassThruBBTestFunctionAssertionGuid006, L"EFI_SCSI_PASS_THRU_PROTOCOL.PassThru - Call PassThru() with NULL Event", L"%a:%d:Status - %r, Target - %d, Lun - %ld, TransferLen - %d\n", __FILE__, (UINTN)__LINE__, Status, Target, Lun, Packet.TransferLength ); // // Assertion Point 3.6.2.2 // Call PassThru() with Event. // // // Create Event // Status = gtBS->CreateEvent ( EFI_EVENT_NOTIFY_SIGNAL, EFI_TPL_CALLBACK, NotifyFunction, NULL, &Event ); if (EFI_ERROR(Status)) { StandardLib->RecordAssertion ( StandardLib, EFI_TEST_ASSERTION_FAILED, gTestGenericFailureGuid, L"BS.CreateEvent", L"%a:%d:Status - %r\n", __FILE__, (UINTN)__LINE__, Status ); return Status; } EnterEvent = 0; // // Initialize the Request Packet. // EfiCommonLibZeroMem (&Packet,sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET)); EfiCommonLibZeroMem (Cdb,6); EfiCommonLibZeroMem (Data, ScsiPassThru->Mode->IoAlign + 96); // Set to OP_INQUIRY. Cdb[0] = 0x12; Cdb[1] = (UINT8)(((UINT8)Lun << 5) & 0xE0); Cdb[4] = 96; Packet.Timeout = EfiScsiStallSeconds (2); Packet.Cdb = Cdb; Packet.CdbLength = 6; if ((ScsiPassThru->Mode->IoAlign == 0) || (ScsiPassThru->Mode->IoAlign == 1)){ Packet.DataBuffer = (VOID *)Data; } else { Packet.DataBuffer = (VOID *)(((UINTN)Data + ScsiPassThru->Mode->IoAlign - 1) & ~(ScsiPassThru->Mode->IoAlign - 1)); } Packet.TransferLength = 96; Packet.DataDirection = 0; Status = ScsiPassThru->PassThru (ScsiPassThru, Target, Lun, &Packet, Event); if (!(ScsiPassThru->Mode->Attributes & EFI_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO)) { if (!EFI_ERROR(Status) && (EnterEvent == 0)) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } } else { // // wait for event being signaled. // gtBS->Stall(EfiScsiStallSeconds (3)); if (!EFI_ERROR(Status) && (EnterEvent == 1)) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } } StandardLib->RecordAssertion ( StandardLib, AssertionType, gScsiPassThruBBTestFunctionAssertionGuid007, L"EFI_SCSI_PASS_THRU_PROTOCOL.PassThru - Call PassThru() with Event", L"%a:%d:Status - %r, Target - %d, Lun - %ld\n", __FILE__, (UINTN)__LINE__, Status, Target, Lun ); // Close the event Status = gtBS->CloseEvent (Event); if (EFI_ERROR(Status)) { return EFI_UNSUPPORTED; } FreePool (Data); return EFI_SUCCESS; }