/** Get ESRT FwType according to ImageTypeId @param[in] ImageTypeId ImageTypeId of an FMP capsule. @return ESRT FwType **/ UINT32 GetEsrtFwType ( IN EFI_GUID *ImageTypeId ) { EFI_STATUS Status; EFI_SYSTEM_RESOURCE_TABLE *Esrt; EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry; UINTN Index; // // Check ESRT // Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID **)&Esrt); if (!EFI_ERROR(Status)) { ASSERT(Esrt != NULL); EsrtEntry = (VOID *)(Esrt + 1); for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) { if (CompareGuid(&EsrtEntry->FwClass, ImageTypeId)) { return EsrtEntry->FwType; } } } return ESRT_FW_TYPE_UNKNOWN; }
EFI_STATUS EblDumpFdt ( IN UINTN Argc, IN CHAR8 **Argv ) { EFI_STATUS Status; VOID *FdtBlob; UINTN Ret; // If no FDT file is passed to the argument then get the one from the platform if (Argc < 2) { Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &FdtBlob); if (EFI_ERROR (Status)) { Print (L"ERROR: Did not find the Fdt Blob.\n"); return Status; } } else { return EFI_NOT_FOUND; } Ret = fdt_check_header (FdtBlob); if (Ret != 0) { Print (L"ERROR: Device Tree header not valid (err:%d)\n", Ret); return EFI_INVALID_PARAMETER; } DumpFdt (FdtBlob); return EFI_SUCCESS; }
/** Called to initialize the memory service. @param SmramRangeCount Number of SMRAM Regions @param SmramRanges Pointer to SMRAM Descriptors **/ VOID SmmInitializeMemoryServices ( IN UINTN SmramRangeCount, IN EFI_SMRAM_DESCRIPTOR *SmramRanges ) { UINTN Index; EFI_STATUS Status; UINTN SmmPoolTypeIndex; EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE *LMFAConfigurationTable; // // Initialize Pool list // for (SmmPoolTypeIndex = 0; SmmPoolTypeIndex < SmmPoolTypeMax; SmmPoolTypeIndex++) { for (Index = 0; Index < ARRAY_SIZE (mSmmPoolLists[SmmPoolTypeIndex]); Index++) { InitializeListHead (&mSmmPoolLists[SmmPoolTypeIndex][Index]); } } Status = EfiGetSystemConfigurationTable ( &gLoadFixedAddressConfigurationTableGuid, (VOID **) &LMFAConfigurationTable ); if (!EFI_ERROR (Status) && LMFAConfigurationTable != NULL) { gLoadModuleAtFixAddressSmramBase = LMFAConfigurationTable->SmramBase; } // // Add Free SMRAM regions // Need add Free memory at first, to let gSmmMemoryMap record data // for (Index = 0; Index < SmramRangeCount; Index++) { if ((SmramRanges[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) != 0) { continue; } SmmAddMemoryRegion ( SmramRanges[Index].CpuStart, SmramRanges[Index].PhysicalSize, EfiConventionalMemory, SmramRanges[Index].RegionState ); } // // Add the allocated SMRAM regions // for (Index = 0; Index < SmramRangeCount; Index++) { if ((SmramRanges[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) == 0) { continue; } SmmAddMemoryRegion ( SmramRanges[Index].CpuStart, SmramRanges[Index].PhysicalSize, EfiConventionalMemory, SmramRanges[Index].RegionState ); } }
/** This is the shell command "dumpfdt" handler function. This function handles the command when it is invoked in the shell. @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. @param[in] SystemTable The pointer to the UEFI system table. @param[in] ShellParameters The parameters associated with the command. @param[in] Shell The instance of the shell protocol used in the context of processing this command. @return SHELL_SUCCESS The operation was successful. @return SHELL_ABORTED Operation aborted due to internal error. @return SHELL_NOT_FOUND Failed to locate the Device Tree into the EFI Configuration Table @return SHELL_OUT_OF_RESOURCES A memory allocation failed. **/ SHELL_STATUS EFIAPI ShellDynCmdDumpFdtHandler ( IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, IN EFI_SYSTEM_TABLE *SystemTable, IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, IN EFI_SHELL_PROTOCOL *Shell ) { SHELL_STATUS ShellStatus; EFI_STATUS Status; VOID *FdtBlob; ShellStatus = SHELL_SUCCESS; // // Install the Shell and Shell Parameters Protocols on the driver // image. This is necessary for the initialisation of the Shell // Library to succeed in the next step. // Status = gBS->InstallMultipleProtocolInterfaces ( &gImageHandle, &gEfiShellProtocolGuid, Shell, &gEfiShellParametersProtocolGuid, ShellParameters, NULL ); if (EFI_ERROR (Status)) { return SHELL_ABORTED; } // // Initialise the Shell Library as we are going to use it. // Assert that the return code is EFI_SUCCESS as it should. // To anticipate any change is the codes returned by // ShellInitialize(), leave in case of error. // Status = ShellInitialize (); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return SHELL_ABORTED; } Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &FdtBlob); if (EFI_ERROR (Status)) { Print (L"ERROR: Did not find the Fdt Blob.\n"); return EfiCodeToShellCode (Status); } DumpFdt (FdtBlob); gBS->UninstallMultipleProtocolInterfaces ( gImageHandle, &gEfiShellProtocolGuid, Shell, &gEfiShellParametersProtocolGuid, ShellParameters, NULL ); return ShellStatus; }
VOID EblInitializeDeviceCmd ( VOID ) { EfiGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, (VOID **) &gDS); EblAddCommands (mCmdDeviceTemplate, sizeof (mCmdDeviceTemplate)/sizeof (EBL_COMMAND_TABLE)); }
/** Simple arm disassembler via a library Argv[0] - symboltable Argv[1] - Optional qoted format string Argv[2] - Optional flag @param Argc Number of command arguments in Argv @param Argv Array of strings that represent the parsed command line. Argv[0] is the command name @return EFI_SUCCESS **/ EFI_STATUS EblSymbolTable ( IN UINTN Argc, IN CHAR8 **Argv ) { EFI_STATUS Status; EFI_DEBUG_IMAGE_INFO_TABLE_HEADER *DebugImageTableHeader = NULL; EFI_DEBUG_IMAGE_INFO *DebugTable; UINTN Entry; CHAR8 *Format; CHAR8 *Pdb; UINT32 PeCoffSizeOfHeaders; UINT32 ImageBase; BOOLEAN Elf; // Need to add lots of error checking on the passed in string // Default string is for RealView debugger #if (__ARMCC_VERSION < 500000) Format = (Argc > 1) ? Argv[1] : "load /a /ni /np %a &0x%x"; #else Format = (Argc > 1) ? Argv[1] : "add-symbol-file %a 0x%x"; #endif Elf = (Argc > 2) ? FALSE : TRUE; Status = EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid, (VOID **)&DebugImageTableHeader); if (EFI_ERROR (Status)) { return Status; } DebugTable = DebugImageTableHeader->EfiDebugImageInfoTable; if (DebugTable == NULL) { return EFI_SUCCESS; } for (Entry = 0; Entry < DebugImageTableHeader->TableSize; Entry++, DebugTable++) { if (DebugTable->NormalImage != NULL) { if ((DebugTable->NormalImage->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) && (DebugTable->NormalImage->LoadedImageProtocolInstance != NULL)) { ImageBase = (UINTN)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase; PeCoffSizeOfHeaders = PeCoffGetSizeOfHeaders ((VOID *)(UINTN)ImageBase); Pdb = PeCoffLoaderGetPdbPointer (DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase); if (Pdb != NULL) { if (Elf) { // ELF and Mach-O images don't include the header so the linked address does not include header ImageBase += PeCoffSizeOfHeaders; } AsciiPrint (Format, Pdb, ImageBase); AsciiPrint ("\n"); } else { } } } } return EFI_SUCCESS; }
/** This function gets system guid and serial number from the smbios table. @param SystemGuid The pointer of returned system guid. @param SystemSerialNumber The pointer of returned system serial number. @retval EFI_SUCCESS Successfully get the system guid and system serial number. @retval EFI_NOT_FOUND Not find the SMBIOS table. **/ EFI_STATUS GetSmbiosSystemGuidAndSerialNumber ( IN EFI_GUID *SystemGuid, OUT CHAR8 **SystemSerialNumber ) { EFI_STATUS Status; SMBIOS_TABLE_ENTRY_POINT *SmbiosTable; SMBIOS_STRUCTURE_POINTER Smbios; SMBIOS_STRUCTURE_POINTER SmbiosEnd; UINT16 Index; Status = EfiGetSystemConfigurationTable (&gEfiSmbiosTableGuid, (VOID **) &SmbiosTable); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; } ASSERT (SmbiosTable != NULL); Smbios.Hdr = (SMBIOS_STRUCTURE *) (UINTN) SmbiosTable->TableAddress; SmbiosEnd.Raw = (UINT8 *) (UINTN) (SmbiosTable->TableAddress + SmbiosTable->TableLength); for (Index = 0; Index < SmbiosTable->TableLength; Index++) { if (Smbios.Hdr->Type == 1) { if (Smbios.Hdr->Length < 0x19) { // // Older version did not support Guid and Serial number // continue; } // // SMBIOS tables are byte packed so we need to do a byte copy to // prevend alignment faults on Itanium-based platform. // CopyMem (SystemGuid, &Smbios.Type1->Uuid, sizeof (EFI_GUID)); *SystemSerialNumber = GetSmbiosString (&Smbios, Smbios.Type1->SerialNumber); return EFI_SUCCESS; } // // Make Smbios point to the next record // GetSmbiosString (&Smbios, 0); if (Smbios.Raw >= SmbiosEnd.Raw) { // // SMBIOS 2.1 incorrectly stated the length of SmbiosTable as 0x1e. // given this we must double check against the length of the structure. // return EFI_SUCCESS; } } return EFI_SUCCESS; }
EFI_STATUS PciRomLoadEfiDriversFromOptionRomTable ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo ) /*++ Routine Description: Arguments: Returns: --*/ { EFI_STATUS Status; EFI_PCI_OPTION_ROM_TABLE *PciOptionRomTable; EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor; UINTN Index; EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; UINT16 MinBus; UINT16 MaxBus; Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; } Status = EFI_NOT_FOUND; for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) { PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index]; if (!PciOptionRomDescriptor->DontLoadEfiRom) { if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber) { Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors); if (EFI_ERROR (Status)) { return Status; } PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL); if ((MinBus <= PciOptionRomDescriptor->Bus) && (PciOptionRomDescriptor->Bus <= MaxBus)) { Status = PciRomLoadEfiDriversFromRomImage (This, PciOptionRomDescriptor); PciOptionRomDescriptor->DontLoadEfiRom |= 2; } } } } return Status; }
EFIAPI GetHobList ( VOID ) { EFI_STATUS Status; if (mHobList == NULL) { Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &mHobList); ASSERT_EFI_ERROR (Status); ASSERT (mHobList != NULL); } return mHobList; }
EFI_STATUS PciRomGetRomResourceFromPciOptionRomTable ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, PCI_IO_DEVICE *PciIoDevice ) /*++ Routine Description: Arguments: Returns: --*/ { EFI_STATUS Status; EFI_PCI_OPTION_ROM_TABLE *PciOptionRomTable; EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor; UINTN Index; Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; } for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) { PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index]; if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber && PciOptionRomDescriptor->Bus == PciIoDevice->BusNumber && PciOptionRomDescriptor->Dev == PciIoDevice->DeviceNumber && PciOptionRomDescriptor->Func == PciIoDevice->FunctionNumber ) { PciIoDevice->PciIo.RomImage = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress; PciIoDevice->PciIo.RomSize = (UINTN) PciOptionRomDescriptor->RomLength; } } for (Index = 0; Index < mNumberOfPciRomImages; Index++) { if (mRomImageTable[Index].Seg == PciRootBridgeIo->SegmentNumber && mRomImageTable[Index].Bus == PciIoDevice->BusNumber && mRomImageTable[Index].Dev == PciIoDevice->DeviceNumber && mRomImageTable[Index].Func == PciIoDevice->FunctionNumber ) { AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle); } } return EFI_SUCCESS; }
/** The constructor function caches the pointer to HOB list. The constructor function gets the start address of HOB list from system configuration table. It will ASSERT() if that operation fails and it will always return EFI_SUCCESS. @param ImageHandle The firmware allocated handle for the EFI image. @param SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The constructor successfully gets HobList. @retval Other value The constructor can't get HobList. **/ EFI_STATUS EFIAPI HobLibConstructor ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &mHobList); ASSERT_EFI_ERROR (Status); ASSERT (mHobList != NULL); return Status; }
/** Get the pointer to Mailbox from the configuration table. @return Pointer to Mailbox. **/ DEBUG_AGENT_MAILBOX * GetMailboxFromConfigurationTable ( VOID ) { EFI_STATUS Status; DEBUG_AGENT_MAILBOX *Mailbox; Status = EfiGetSystemConfigurationTable (&gEfiDebugAgentGuid, (VOID **) &Mailbox); if (Status == EFI_SUCCESS && Mailbox != NULL) { VerifyMailboxChecksum (Mailbox); return Mailbox; } else { return NULL; } }
/** Return if there is a FMP header below capsule header. @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER @retval TRUE There is a FMP header below capsule header. @retval FALSE There is not a FMP header below capsule header **/ BOOLEAN IsNestedFmpCapsule ( IN EFI_CAPSULE_HEADER *CapsuleHeader ) { EFI_STATUS Status; EFI_SYSTEM_RESOURCE_TABLE *Esrt; EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry; UINTN Index; BOOLEAN EsrtGuidFound; EFI_CAPSULE_HEADER *NestedCapsuleHeader; UINTN NestedCapsuleSize; // // Check ESRT // EsrtGuidFound = FALSE; Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID **)&Esrt); if (!EFI_ERROR(Status)) { ASSERT (Esrt != NULL); EsrtEntry = (VOID *)(Esrt + 1); for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) { if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) { EsrtGuidFound = TRUE; break; } } } if (!EsrtGuidFound) { return FALSE; } // // Check nested capsule header // FMP GUID after ESRT one // NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize); NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->HeaderSize - (UINTN)NestedCapsuleHeader; if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) { return FALSE; } if (!CompareGuid(&NestedCapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)) { return FALSE; } return TRUE; }
/** The constructor function caches the pointer of DXE Services Table. The constructor function caches the pointer of DXE Services Table. It will ASSERT() if that operation fails. It will ASSERT() if the pointer of DXE Services Table is NULL. It will always return EFI_SUCCESS. @param ImageHandle The firmware allocated handle for the EFI image. @param SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. **/ EFI_STATUS EFIAPI DxeServicesTableLibConstructor ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; // // Cache copy of the DXE Services Table // Status = EfiGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, (VOID **) &gDS); ASSERT_EFI_ERROR (Status); ASSERT (gDS != NULL); return Status; }
/** Dump ESRT info. **/ VOID DumpEsrtData ( VOID ) { EFI_STATUS Status; EFI_SYSTEM_RESOURCE_TABLE *Esrt; Print(L"##############\n"); Print(L"# ESRT TABLE #\n"); Print(L"##############\n"); Status = EfiGetSystemConfigurationTable (&gEfiSystemResourceTableGuid, (VOID **)&Esrt); if (EFI_ERROR(Status)) { Print(L"ESRT - %r\n", Status); return; } DumpEsrt(Esrt); Print(L"\n"); }
/** Measure and log EFI handoff tables, and extend the measurement result into PCR[1]. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The operation was unsuccessful. **/ EFI_STATUS EFIAPI MeasureHandoffTables ( VOID ) { EFI_STATUS Status; SMBIOS_TABLE_ENTRY_POINT *SmbiosTable; TCG_PCR_EVENT_HDR TcgEvent; EFI_HANDOFF_TABLE_POINTERS HandoffTables; Status = EfiGetSystemConfigurationTable ( &gEfiSmbiosTableGuid, (VOID **) &SmbiosTable ); if (!EFI_ERROR (Status)) { ASSERT (SmbiosTable != NULL); TcgEvent.PCRIndex = 1; TcgEvent.EventType = EV_EFI_HANDOFF_TABLES; TcgEvent.EventSize = sizeof (HandoffTables); HandoffTables.NumberOfTables = 1; HandoffTables.TableEntry[0].VendorGuid = gEfiSmbiosTableGuid; HandoffTables.TableEntry[0].VendorTable = SmbiosTable; DEBUG ((DEBUG_INFO, "The Smbios Table starts at: 0x%x\n", SmbiosTable->TableAddress)); DEBUG ((DEBUG_INFO, "The Smbios Table size: 0x%x\n", SmbiosTable->TableLength)); Status = TcgDxeHashLogExtendEventI ( &mTcgDxeData, (UINT8*)(UINTN)SmbiosTable->TableAddress, SmbiosTable->TableLength, &TcgEvent, (UINT8*)&HandoffTables ); } return Status; }
/** The constructor function of UEFI SAL Lib. The constructor function looks up the SAL System Table in the EFI System Configuration Table. Once the SAL System Table is found, the SAL Entry Point in the SAL System Table will be derived and stored into a global variable for library usage. It will ASSERT() if the SAL System Table cannot be found or the data in the SAL System Table is not the valid data. @param ImageHandle The firmware allocated handle for the EFI image. @param SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. **/ EFI_STATUS EFIAPI UefiSalLibConstructor ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; SAL_ST_ENTRY_POINT_DESCRIPTOR *SalStEntryDes; SAL_SYSTEM_TABLE_HEADER *SalSystemTable; Status = EfiGetSystemConfigurationTable ( &gEfiSalSystemTableGuid, (VOID **) &SalSystemTable ); ASSERT_EFI_ERROR (Status); ASSERT (SalSystemTable != NULL); // // Check the first entry of SAL System Table, // because the SAL entry is in ascending order with the entry type, // the type 0 entry should be the first if exist. // SalStEntryDes = (SAL_ST_ENTRY_POINT_DESCRIPTOR *)(SalSystemTable + 1); // // Assure the SAL ENTRY Type is 0 // ASSERT (SalStEntryDes->Type == EFI_SAL_ST_ENTRY_POINT); mPlabel.EntryPoint = SalStEntryDes->SalProcEntry; mPlabel.GP = SalStEntryDes->SalGlobalDataPointer; // // Make sure the EntryPoint has the valid value // ASSERT ((mPlabel.EntryPoint != 0) && (mPlabel.GP != 0)); mSalProcEntry = (SAL_PROC)((UINT64)&(mPlabel.EntryPoint)); return EFI_SUCCESS; }
STATIC VOID EFIAPI ApplyDeviceTreeOverlay ( EFI_EVENT Event, VOID *Context ) { VOID *Dtb; MEZZANINE_PROTOCOL *Mezzanine; EFI_STATUS Status; // // Find the DTB in the configuration table array. If it isn't there, just // bail without an error: we may be running on an ACPI platform even if // this driver does not support it [yet]. // Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &Dtb); if (Status == EFI_NOT_FOUND) { return; } ASSERT_EFI_ERROR (Status); Status = gBS->LocateProtocol (&g96BoardsMezzanineProtocolGuid, NULL, (VOID **)&Mezzanine); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "%a: no mezzanine driver active\n", __FUNCTION__)); return; } Status = Mezzanine->ApplyDeviceTreeOverlay (Mezzanine, Dtb); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_WARN, "%a: failed to apply DT overlay - %r\n", __FUNCTION__, Status)); } }
/** The user Entry Point for Application. The user code starts with this function as the real entry point for the image goes into a library that calls this function. @param[in] ImageHandle The firmware allocated handle for the EFI image. @param[in] SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The entry point is executed successfully. @retval other Some error occurs when executing this entry point. **/ EFI_STATUS EFIAPI GdbStubEntry ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_DEBUG_SUPPORT_PROTOCOL *DebugSupport; UINTN HandleCount; EFI_HANDLE *Handles; UINTN Index; UINTN Processor; BOOLEAN IsaSupported; Status = EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid, (VOID **)&gDebugImageTableHeader); if (EFI_ERROR (Status)) { gDebugImageTableHeader = NULL; } Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiDebugSupportProtocolGuid, NULL, &HandleCount, &Handles ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Debug Support Protocol not found\n")); return Status; } DebugSupport = NULL; IsaSupported = FALSE; do { HandleCount--; Status = gBS->HandleProtocol ( Handles[HandleCount], &gEfiDebugSupportProtocolGuid, (VOID **) &DebugSupport ); if (!EFI_ERROR (Status)) { if (CheckIsa (DebugSupport->Isa)) { // We found what we are looking for so break out of the loop IsaSupported = TRUE; break; } } } while (HandleCount > 0); FreePool (Handles); if (!IsaSupported) { DEBUG ((EFI_D_ERROR, "Debug Support Protocol does not support our ISA\n")); return EFI_NOT_FOUND; } Status = DebugSupport->GetMaximumProcessorIndex (DebugSupport, &gMaxProcessorIndex); ASSERT_EFI_ERROR (Status); DEBUG ((EFI_D_INFO, "Debug Support Protocol ISA %x\n", DebugSupport->Isa)); DEBUG ((EFI_D_INFO, "Debug Support Protocol Processor Index %d\n", gMaxProcessorIndex)); // Call processor-specific init routine InitializeProcessor (); for (Processor = 0; Processor <= gMaxProcessorIndex; Processor++) { for (Index = 0; Index < MaxEfiException (); Index++) { Status = DebugSupport->RegisterExceptionCallback (DebugSupport, Processor, GdbExceptionHandler, gExceptionType[Index].Exception); ASSERT_EFI_ERROR (Status); } // // Current edk2 DebugPort is not interrupt context safe so we can not use it // Status = DebugSupport->RegisterPeriodicCallback (DebugSupport, Processor, GdbPeriodicCallBack); ASSERT_EFI_ERROR (Status); } // // This even fires every time an image is added. This allows the stub to know when gdb needs // to update the symbol table. // Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_CALLBACK, GdbSymbolEventHandler, NULL, &gEvent ); ASSERT_EFI_ERROR (Status); // // Register for protocol notifications on this event // Status = gBS->RegisterProtocolNotify ( &gEfiLoadedImageProtocolGuid, gEvent, &gGdbSymbolEventHandlerRegistration ); ASSERT_EFI_ERROR (Status); if (PcdGetBool (PcdGdbSerial)) { GdbInitializeSerialConsole (); } return EFI_SUCCESS; }
/** Get SMI handler profile database. **/ VOID GetSmiHandlerProfileDatabase( VOID ) { EFI_STATUS Status; UINTN CommSize; UINT8 *CommBuffer; EFI_SMM_COMMUNICATE_HEADER *CommHeader; SMI_HANDLER_PROFILE_PARAMETER_GET_INFO *CommGetInfo; SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET *CommGetData; EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication; UINTN MinimalSizeNeeded; EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable; UINT32 Index; EFI_MEMORY_DESCRIPTOR *Entry; VOID *Buffer; UINTN Size; UINTN Offset; Status = gBS->LocateProtocol(&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **)&SmmCommunication); if (EFI_ERROR(Status)) { Print(L"SmiHandlerProfile: Locate SmmCommunication protocol - %r\n", Status); return ; } MinimalSizeNeeded = EFI_PAGE_SIZE; Status = EfiGetSystemConfigurationTable( &gEdkiiPiSmmCommunicationRegionTableGuid, (VOID **)&PiSmmCommunicationRegionTable ); if (EFI_ERROR(Status)) { Print(L"SmiHandlerProfile: Get PiSmmCommunicationRegionTable - %r\n", Status); return ; } ASSERT(PiSmmCommunicationRegionTable != NULL); Entry = (EFI_MEMORY_DESCRIPTOR *)(PiSmmCommunicationRegionTable + 1); Size = 0; for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) { if (Entry->Type == EfiConventionalMemory) { Size = EFI_PAGES_TO_SIZE((UINTN)Entry->NumberOfPages); if (Size >= MinimalSizeNeeded) { break; } } Entry = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Entry + PiSmmCommunicationRegionTable->DescriptorSize); } ASSERT(Index < PiSmmCommunicationRegionTable->NumberOfEntries); CommBuffer = (UINT8 *)(UINTN)Entry->PhysicalStart; // // Get Size // CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0]; CopyMem(&CommHeader->HeaderGuid, &gSmiHandlerProfileGuid, sizeof(gSmiHandlerProfileGuid)); CommHeader->MessageLength = sizeof(SMI_HANDLER_PROFILE_PARAMETER_GET_INFO); CommGetInfo = (SMI_HANDLER_PROFILE_PARAMETER_GET_INFO *)&CommBuffer[OFFSET_OF(EFI_SMM_COMMUNICATE_HEADER, Data)]; CommGetInfo->Header.Command = SMI_HANDLER_PROFILE_COMMAND_GET_INFO; CommGetInfo->Header.DataLength = sizeof(*CommGetInfo); CommGetInfo->Header.ReturnStatus = (UINT64)-1; CommGetInfo->DataSize = 0; CommSize = sizeof(EFI_GUID) + sizeof(UINTN) + CommHeader->MessageLength; Status = SmmCommunication->Communicate(SmmCommunication, CommBuffer, &CommSize); if (EFI_ERROR(Status)) { Print(L"SmiHandlerProfile: SmmCommunication - %r\n", Status); return ; } if (CommGetInfo->Header.ReturnStatus != 0) { Print(L"SmiHandlerProfile: GetInfo - 0x%0x\n", CommGetInfo->Header.ReturnStatus); return ; } mSmiHandlerProfileDatabaseSize = (UINTN)CommGetInfo->DataSize; // // Get Data // mSmiHandlerProfileDatabase = AllocateZeroPool(mSmiHandlerProfileDatabaseSize); if (mSmiHandlerProfileDatabase == NULL) { Status = EFI_OUT_OF_RESOURCES; Print(L"SmiHandlerProfile: AllocateZeroPool (0x%x) for dump buffer - %r\n", mSmiHandlerProfileDatabaseSize, Status); return ; } CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0]; CopyMem(&CommHeader->HeaderGuid, &gSmiHandlerProfileGuid, sizeof(gSmiHandlerProfileGuid)); CommHeader->MessageLength = sizeof(SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET); CommGetData = (SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET *)&CommBuffer[OFFSET_OF(EFI_SMM_COMMUNICATE_HEADER, Data)]; CommGetData->Header.Command = SMI_HANDLER_PROFILE_COMMAND_GET_DATA_BY_OFFSET; CommGetData->Header.DataLength = sizeof(*CommGetData); CommGetData->Header.ReturnStatus = (UINT64)-1; CommSize = sizeof(EFI_GUID) + sizeof(UINTN) + CommHeader->MessageLength; Buffer = (UINT8 *)CommHeader + CommSize; Size -= CommSize; CommGetData->DataBuffer = (PHYSICAL_ADDRESS)(UINTN)Buffer; CommGetData->DataOffset = 0; while (CommGetData->DataOffset < mSmiHandlerProfileDatabaseSize) { Offset = (UINTN)CommGetData->DataOffset; if (Size <= (mSmiHandlerProfileDatabaseSize - CommGetData->DataOffset)) { CommGetData->DataSize = (UINT64)Size; } else { CommGetData->DataSize = (UINT64)(mSmiHandlerProfileDatabaseSize - CommGetData->DataOffset); } Status = SmmCommunication->Communicate(SmmCommunication, CommBuffer, &CommSize); ASSERT_EFI_ERROR(Status); if (CommGetData->Header.ReturnStatus != 0) { FreePool(mSmiHandlerProfileDatabase); mSmiHandlerProfileDatabase = NULL; Print(L"SmiHandlerProfile: GetData - 0x%x\n", CommGetData->Header.ReturnStatus); return ; } CopyMem((UINT8 *)mSmiHandlerProfileDatabase + Offset, (VOID *)(UINTN)CommGetData->DataBuffer, (UINTN)CommGetData->DataSize); } DEBUG ((DEBUG_INFO, "SmiHandlerProfileSize - 0x%x\n", mSmiHandlerProfileDatabaseSize)); return ; }
/** The hook in InitializeEbcDriver. It will init the EbcDebuggerPrivate data structure. @param Handle - The EbcDebugProtocol handle. @param EbcDebugProtocol - The EbcDebugProtocol interface. **/ VOID EbcDebuggerHookInit ( IN EFI_HANDLE Handle, IN EFI_DEBUG_SUPPORT_PROTOCOL *EbcDebugProtocol ) { EFI_STATUS Status; UINTN Index; EFI_DEBUGGER_SYMBOL_OBJECT *Object; EFI_DEBUGGER_SYMBOL_ENTRY *Entry; // // Register all exception handler // for (Index = EXCEPT_EBC_UNDEFINED; Index <= EXCEPT_EBC_STEP; Index++) { EbcDebugProtocol->RegisterExceptionCallback ( EbcDebugProtocol, 0, NULL, Index ); EbcDebugProtocol->RegisterExceptionCallback ( EbcDebugProtocol, 0, EdbExceptionHandler, Index ); } // // Init Symbol // Object = AllocateZeroPool (sizeof(EFI_DEBUGGER_SYMBOL_OBJECT) * EFI_DEBUGGER_SYMBOL_OBJECT_MAX); ASSERT (Object != NULL); mDebuggerPrivate.DebuggerSymbolContext.Object = Object; mDebuggerPrivate.DebuggerSymbolContext.ObjectCount = 0; mDebuggerPrivate.DebuggerSymbolContext.MaxObjectCount = EFI_DEBUGGER_SYMBOL_OBJECT_MAX; for (Index = 0; Index < EFI_DEBUGGER_SYMBOL_OBJECT_MAX; Index++) { Entry = AllocateZeroPool (sizeof(EFI_DEBUGGER_SYMBOL_ENTRY) * EFI_DEBUGGER_SYMBOL_ENTRY_MAX); ASSERT (Entry != NULL); Object[Index].Entry = Entry; Object[Index].MaxEntryCount = EFI_DEBUGGER_SYMBOL_ENTRY_MAX; Object[Index].SourceBuffer = AllocateZeroPool (sizeof(VOID *) * (EFI_DEBUGGER_SYMBOL_ENTRY_MAX + 1)); ASSERT (Object[Index].SourceBuffer != NULL); } // // locate PciRootBridgeIo // Status = gBS->LocateProtocol ( &gEfiPciRootBridgeIoProtocolGuid, NULL, (VOID**) &mDebuggerPrivate.PciRootBridgeIo ); // // locate DebugImageInfoTable // Status = EfiGetSystemConfigurationTable ( &gEfiDebugImageInfoTableGuid, (VOID**) &mDebuggerPrivate.DebugImageInfoTableHeader ); // // Register Debugger Configuration Protocol, for config in shell // Status = gBS->InstallProtocolInterface ( &Handle, &gEfiDebuggerConfigurationProtocolGuid, EFI_NATIVE_INTERFACE, &mDebuggerPrivate.DebuggerConfiguration ); // // // Create break event // Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, EbcDebuggerBreakEventFunc, NULL, &mDebuggerPrivate.BreakEvent ); if (!EFI_ERROR (Status)) { Status = gBS->SetTimer ( mDebuggerPrivate.BreakEvent, TimerPeriodic, EFI_DEBUG_BREAK_TIMER_INTERVAL ); } return ; }
/** Get and dump SMRAM profile data. @return EFI_SUCCESS Get the SMRAM profile data successfully. @return other Fail to get the SMRAM profile data. **/ EFI_STATUS GetSmramProfileData ( VOID ) { EFI_STATUS Status; UINTN CommSize; UINT8 *CommBuffer; EFI_SMM_COMMUNICATE_HEADER *CommHeader; SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *CommGetProfileInfo; SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *CommGetProfileData; UINTN ProfileSize; VOID *ProfileBuffer; EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication; UINTN MinimalSizeNeeded; EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable; UINT32 Index; EFI_MEMORY_DESCRIPTOR *Entry; VOID *Buffer; UINTN Size; UINTN Offset; Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &SmmCommunication); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "SmramProfile: Locate SmmCommunication protocol - %r\n", Status)); return Status; } MinimalSizeNeeded = sizeof (EFI_GUID) + sizeof (UINTN) + MAX (sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO), sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET)); MinimalSizeNeeded += MAX (sizeof (MEMORY_PROFILE_CONTEXT), MAX (sizeof (MEMORY_PROFILE_DRIVER_INFO), MAX (sizeof (MEMORY_PROFILE_ALLOC_INFO), MAX (sizeof (MEMORY_PROFILE_DESCRIPTOR), MAX (sizeof (MEMORY_PROFILE_FREE_MEMORY), sizeof (MEMORY_PROFILE_MEMORY_RANGE)))))); Status = EfiGetSystemConfigurationTable ( &gEdkiiPiSmmCommunicationRegionTableGuid, (VOID **) &PiSmmCommunicationRegionTable ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "SmramProfile: Get PiSmmCommunicationRegionTable - %r\n", Status)); return Status; } ASSERT (PiSmmCommunicationRegionTable != NULL); Entry = (EFI_MEMORY_DESCRIPTOR *) (PiSmmCommunicationRegionTable + 1); Size = 0; for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) { if (Entry->Type == EfiConventionalMemory) { Size = EFI_PAGES_TO_SIZE ((UINTN) Entry->NumberOfPages); if (Size >= MinimalSizeNeeded) { break; } } Entry = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) Entry + PiSmmCommunicationRegionTable->DescriptorSize); } ASSERT (Index < PiSmmCommunicationRegionTable->NumberOfEntries); CommBuffer = (UINT8 *) (UINTN) Entry->PhysicalStart; // // Get Size // CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0]; CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid)); CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO); CommGetProfileInfo = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; CommGetProfileInfo->Header.Command = SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO; CommGetProfileInfo->Header.DataLength = sizeof (*CommGetProfileInfo); CommGetProfileInfo->Header.ReturnStatus = (UINT64)-1; CommGetProfileInfo->ProfileSize = 0; CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength; Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "SmramProfile: SmmCommunication - %r\n", Status)); return Status; } if (CommGetProfileInfo->Header.ReturnStatus != 0) { Print (L"SmramProfile: GetProfileInfo - 0x%0x\n", CommGetProfileInfo->Header.ReturnStatus); return EFI_SUCCESS; } ProfileSize = (UINTN) CommGetProfileInfo->ProfileSize; // // Get Data // ProfileBuffer = AllocateZeroPool (ProfileSize); if (ProfileBuffer == 0) { Status = EFI_OUT_OF_RESOURCES; Print (L"SmramProfile: AllocateZeroPool (0x%x) for profile buffer - %r\n", ProfileSize, Status); return Status; } CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0]; CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof(gEdkiiMemoryProfileGuid)); CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET); CommGetProfileData = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; CommGetProfileData->Header.Command = SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET; CommGetProfileData->Header.DataLength = sizeof (*CommGetProfileData); CommGetProfileData->Header.ReturnStatus = (UINT64)-1; CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength; Buffer = (UINT8 *) CommHeader + CommSize; Size -= CommSize; CommGetProfileData->ProfileBuffer = (PHYSICAL_ADDRESS) (UINTN) Buffer; CommGetProfileData->ProfileOffset = 0; while (CommGetProfileData->ProfileOffset < ProfileSize) { Offset = (UINTN) CommGetProfileData->ProfileOffset; if (Size <= (ProfileSize - CommGetProfileData->ProfileOffset)) { CommGetProfileData->ProfileSize = (UINT64) Size; } else { CommGetProfileData->ProfileSize = (UINT64) (ProfileSize - CommGetProfileData->ProfileOffset); } Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize); ASSERT_EFI_ERROR (Status); if (CommGetProfileData->Header.ReturnStatus != 0) { FreePool (ProfileBuffer); Print (L"GetProfileData - 0x%x\n", CommGetProfileData->Header.ReturnStatus); return EFI_SUCCESS; } CopyMem ((UINT8 *) ProfileBuffer + Offset, (VOID *) (UINTN) CommGetProfileData->ProfileBuffer, (UINTN) CommGetProfileData->ProfileSize); } Print (L"SmramProfileSize - 0x%x\n", ProfileSize); Print (L"======= SmramProfile begin =======\n"); DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) ProfileBuffer, ProfileSize); Print (L"======= SmramProfile end =======\n\n\n"); FreePool (ProfileBuffer); return EFI_SUCCESS; }
/** The Entry Point for SMM IPL Load SMM Core into SMRAM, register SMM Core entry point for SMIs, install SMM Base 2 Protocol and SMM Communication Protocol, and register for the critical events required to coordinate between DXE and SMM environments. @param ImageHandle The firmware allocated handle for the EFI image. @param SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The entry point is executed successfully. @retval Other Some error occurred when executing this entry point. **/ EFI_STATUS EFIAPI SmmIplEntry ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_SMM_CONFIGURATION_PROTOCOL *SmmConfiguration; UINTN Size; UINTN Index; EFI_SMM_RESERVED_SMRAM_REGION *SmramResRegion; UINT64 MaxSize; VOID *Registration; UINT64 SmmCodeSize; EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE *LMFAConfigurationTable; EFI_CPU_ARCH_PROTOCOL *CpuArch; // // Fill in the image handle of the SMM IPL so the SMM Core can use this as the // ParentImageHandle field of the Load Image Protocol for all SMM Drivers loaded // by the SMM Core // mSmmCorePrivateData.SmmIplImageHandle = ImageHandle; // // Get SMM Access Protocol // Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&mSmmAccess); ASSERT_EFI_ERROR (Status); // // Get SMM Control2 Protocol // Status = gBS->LocateProtocol (&gEfiSmmControl2ProtocolGuid, NULL, (VOID **)&mSmmControl2); ASSERT_EFI_ERROR (Status); // // Get SMM Configuration Protocol if it is present // SmmConfiguration = NULL; Status = gBS->LocateProtocol (&gEfiSmmConfigurationProtocolGuid, NULL, (VOID **) &SmmConfiguration); // // Get SMRAM information // Size = 0; Status = mSmmAccess->GetCapabilities (mSmmAccess, &Size, NULL); ASSERT (Status == EFI_BUFFER_TOO_SMALL); gSmmCorePrivate->SmramRanges = (EFI_SMRAM_DESCRIPTOR *)AllocatePool (Size); ASSERT (gSmmCorePrivate->SmramRanges != NULL); Status = mSmmAccess->GetCapabilities (mSmmAccess, &Size, gSmmCorePrivate->SmramRanges); ASSERT_EFI_ERROR (Status); gSmmCorePrivate->SmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR); // // Open all SMRAM ranges // Status = mSmmAccess->Open (mSmmAccess); ASSERT_EFI_ERROR (Status); // // Print debug message that the SMRAM window is now open. // DEBUG ((DEBUG_INFO, "SMM IPL opened SMRAM window\n")); // // Subtract SMRAM any reserved SMRAM regions. // if (SmmConfiguration != NULL) { SmramResRegion = SmmConfiguration->SmramReservedRegions; while (SmramResRegion->SmramReservedSize != 0) { for (Index = 0; Index < gSmmCorePrivate->SmramRangeCount; Index ++) { if ((SmramResRegion->SmramReservedStart >= gSmmCorePrivate->SmramRanges[Index].CpuStart) && \ ((SmramResRegion->SmramReservedStart + SmramResRegion->SmramReservedSize) <= \ (gSmmCorePrivate->SmramRanges[Index].CpuStart + gSmmCorePrivate->SmramRanges[Index].PhysicalSize))) { // // This range has reserved area, calculate the left free size // gSmmCorePrivate->SmramRanges[Index].PhysicalSize = SmramResRegion->SmramReservedStart - gSmmCorePrivate->SmramRanges[Index].CpuStart; } } SmramResRegion++; } } // // Find the largest SMRAM range between 1MB and 4GB that is at least 256KB - 4K in size // mCurrentSmramRange = NULL; for (Index = 0, MaxSize = SIZE_256KB - EFI_PAGE_SIZE; Index < gSmmCorePrivate->SmramRangeCount; Index++) { // // Skip any SMRAM region that is already allocated, needs testing, or needs ECC initialization // if ((gSmmCorePrivate->SmramRanges[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) != 0) { continue; } if (gSmmCorePrivate->SmramRanges[Index].CpuStart >= BASE_1MB) { if ((gSmmCorePrivate->SmramRanges[Index].CpuStart + gSmmCorePrivate->SmramRanges[Index].PhysicalSize) <= BASE_4GB) { if (gSmmCorePrivate->SmramRanges[Index].PhysicalSize >= MaxSize) { MaxSize = gSmmCorePrivate->SmramRanges[Index].PhysicalSize; mCurrentSmramRange = &gSmmCorePrivate->SmramRanges[Index]; } } } } if (mCurrentSmramRange != NULL) { // // Print debug message showing SMRAM window that will be used by SMM IPL and SMM Core // DEBUG ((DEBUG_INFO, "SMM IPL found SMRAM window %p - %p\n", (VOID *)(UINTN)mCurrentSmramRange->CpuStart, (VOID *)(UINTN)(mCurrentSmramRange->CpuStart + mCurrentSmramRange->PhysicalSize - 1) )); GetSmramCacheRange (mCurrentSmramRange, &mSmramCacheBase, &mSmramCacheSize); // // If CPU AP is present, attempt to set SMRAM cacheability to WB // Note that it is expected that cacheability of SMRAM has been set to WB if CPU AP // is not available here. // CpuArch = NULL; Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&CpuArch); if (!EFI_ERROR (Status)) { Status = gDS->SetMemorySpaceAttributes( mSmramCacheBase, mSmramCacheSize, EFI_MEMORY_WB ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_WARN, "SMM IPL failed to set SMRAM window to EFI_MEMORY_WB\n")); } } // // if Loading module at Fixed Address feature is enabled, save the SMRAM base to Load // Modules At Fixed Address Configuration Table. // if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) { // // Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber // SmmCodeSize = LShiftU64 (PcdGet32(PcdLoadFixAddressSmmCodePageNumber), EFI_PAGE_SHIFT); // // The SMRAM available memory is assumed to be larger than SmmCodeSize // ASSERT (mCurrentSmramRange->PhysicalSize > SmmCodeSize); // // Retrieve Load modules At fixed address configuration table and save the SMRAM base. // Status = EfiGetSystemConfigurationTable ( &gLoadFixedAddressConfigurationTableGuid, (VOID **) &LMFAConfigurationTable ); if (!EFI_ERROR (Status) && LMFAConfigurationTable != NULL) { LMFAConfigurationTable->SmramBase = mCurrentSmramRange->CpuStart; // // Print the SMRAM base // DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: TSEG BASE is %x. \n", LMFAConfigurationTable->SmramBase)); } } // // Load SMM Core into SMRAM and execute it from SMRAM // Status = ExecuteSmmCoreFromSmram (mCurrentSmramRange, gSmmCorePrivate); if (EFI_ERROR (Status)) { // // Print error message that the SMM Core failed to be loaded and executed. // DEBUG ((DEBUG_ERROR, "SMM IPL could not load and execute SMM Core from SMRAM\n")); // // Attempt to reset SMRAM cacheability to UC // if (CpuArch != NULL) { Status = gDS->SetMemorySpaceAttributes( mSmramCacheBase, mSmramCacheSize, EFI_MEMORY_UC ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_WARN, "SMM IPL failed to reset SMRAM window to EFI_MEMORY_UC\n")); } } } } else { // // Print error message that there are not enough SMRAM resources to load the SMM Core. // DEBUG ((DEBUG_ERROR, "SMM IPL could not find a large enough SMRAM region to load SMM Core\n")); } // // If the SMM Core could not be loaded then close SMRAM window, free allocated // resources, and return an error so SMM IPL will be unloaded. // if (mCurrentSmramRange == NULL || EFI_ERROR (Status)) { // // Close all SMRAM ranges // Status = mSmmAccess->Close (mSmmAccess); ASSERT_EFI_ERROR (Status); // // Print debug message that the SMRAM window is now closed. // DEBUG ((DEBUG_INFO, "SMM IPL closed SMRAM window\n")); // // Free all allocated resources // FreePool (gSmmCorePrivate->SmramRanges); return EFI_UNSUPPORTED; } // // Install SMM Base2 Protocol and SMM Communication Protocol // Status = gBS->InstallMultipleProtocolInterfaces ( &mSmmIplHandle, &gEfiSmmBase2ProtocolGuid, &mSmmBase2, &gEfiSmmCommunicationProtocolGuid, &mSmmCommunication, NULL ); ASSERT_EFI_ERROR (Status); // // Create the set of protocol and event notififcations that the SMM IPL requires // for (Index = 0; mSmmIplEvents[Index].NotifyFunction != NULL; Index++) { if (mSmmIplEvents[Index].Protocol) { mSmmIplEvents[Index].Event = EfiCreateProtocolNotifyEvent ( mSmmIplEvents[Index].Guid, mSmmIplEvents[Index].NotifyTpl, mSmmIplEvents[Index].NotifyFunction, mSmmIplEvents[Index].NotifyContext, &Registration ); } else { Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, mSmmIplEvents[Index].NotifyTpl, mSmmIplEvents[Index].NotifyFunction, mSmmIplEvents[Index].NotifyContext, mSmmIplEvents[Index].Guid, &mSmmIplEvents[Index].Event ); ASSERT_EFI_ERROR (Status); } } return EFI_SUCCESS; }
/** This routine adjust the memory information for different memory type and save them into the variables for next boot. **/ VOID BdsSetMemoryTypeInformationVariable ( VOID ) { EFI_STATUS Status; EFI_MEMORY_TYPE_INFORMATION *PreviousMemoryTypeInformation; EFI_MEMORY_TYPE_INFORMATION *CurrentMemoryTypeInformation; UINTN VariableSize; UINTN Index; UINTN Index1; UINT32 Previous; UINT32 Current; UINT32 Next; EFI_HOB_GUID_TYPE *GuidHob; BOOLEAN MemoryTypeInformationModified; BOOLEAN MemoryTypeInformationVariableExists; EFI_BOOT_MODE BootMode; MemoryTypeInformationModified = FALSE; MemoryTypeInformationVariableExists = FALSE; BootMode = GetBootModeHob (); // // In BOOT_IN_RECOVERY_MODE, Variable region is not reliable. // if (BootMode == BOOT_IN_RECOVERY_MODE) { return; } // // Only check the the Memory Type Information variable in the boot mode // other than BOOT_WITH_DEFAULT_SETTINGS because the Memory Type // Information is not valid in this boot mode. // if (BootMode != BOOT_WITH_DEFAULT_SETTINGS) { VariableSize = 0; Status = gRT->GetVariable ( EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME, &gEfiMemoryTypeInformationGuid, NULL, &VariableSize, NULL ); if (Status == EFI_BUFFER_TOO_SMALL) { MemoryTypeInformationVariableExists = TRUE; } } // // Retrieve the current memory usage statistics. If they are not found, then // no adjustments can be made to the Memory Type Information variable. // Status = EfiGetSystemConfigurationTable ( &gEfiMemoryTypeInformationGuid, (VOID **) &CurrentMemoryTypeInformation ); if (EFI_ERROR (Status) || CurrentMemoryTypeInformation == NULL) { return; } // // Get the Memory Type Information settings from Hob if they exist, // PEI is responsible for getting them from variable and build a Hob to save them. // If the previous Memory Type Information is not available, then set defaults // GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid); if (GuidHob == NULL) { // // If Platform has not built Memory Type Info into the Hob, just return. // return; } PreviousMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob); VariableSize = GET_GUID_HOB_DATA_SIZE (GuidHob); // // Use a heuristic to adjust the Memory Type Information for the next boot // // DEBUG ((EFI_D_INFO, "Memory Previous Current Next \n")); // DEBUG ((EFI_D_INFO, " Type Pages Pages Pages \n")); // DEBUG ((EFI_D_INFO, "====== ======== ======== ========\n")); for (Index = 0; PreviousMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) { for (Index1 = 0; CurrentMemoryTypeInformation[Index1].Type != EfiMaxMemoryType; Index1++) { if (PreviousMemoryTypeInformation[Index].Type == CurrentMemoryTypeInformation[Index1].Type) { break; } } if (CurrentMemoryTypeInformation[Index1].Type == EfiMaxMemoryType) { continue; } // // Previous is the number of pages pre-allocated // Current is the number of pages actually needed // Previous = PreviousMemoryTypeInformation[Index].NumberOfPages; Current = CurrentMemoryTypeInformation[Index1].NumberOfPages; Next = Previous; // // Inconsistent Memory Reserved across bootings may lead to S4 fail // Write next varible to 125% * current when the pre-allocated memory is: // 1. More than 150% of needed memory and boot mode is BOOT_WITH_DEFAULT_SETTING // 2. Less than the needed memory // if (Current < Previous) { if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) { Next = Current + (Current >> 2); } else if (!MemoryTypeInformationVariableExists) { Next = MAX (Current + (Current >> 2), Previous); }
/** Start a Linux kernel from a Device Path @param LinuxKernelDevicePath Device Path to the Linux Kernel @param InitrdDevicePath Device Path to the Initrd @param CommandLineArguments Linux command line @retval EFI_SUCCESS All drivers have been connected @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results. **/ EFI_STATUS BdsBootLinuxFdt ( IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath, IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath, IN CONST CHAR8* CommandLineArguments ) { EFI_STATUS Status; UINT32 LinuxImageSize; UINT32 InitrdImageBaseSize = 0; UINT32 InitrdImageSize = 0; VOID *InstalledFdtBase; UINT32 FdtBlobSize; EFI_PHYSICAL_ADDRESS FdtBlobBase; EFI_PHYSICAL_ADDRESS LinuxImage; EFI_PHYSICAL_ADDRESS InitrdImageBase = 0; EFI_PHYSICAL_ADDRESS InitrdImage = 0; PERF_START (NULL, "BDS", NULL, 0); // Load the Linux kernel from a device path LinuxImage = LINUX_KERNEL_MAX_OFFSET; Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize); if (EFI_ERROR(Status)) { Print (L"ERROR: Did not find Linux kernel.\n"); return Status; } if (InitrdDevicePath) { InitrdImageBase = LINUX_KERNEL_MAX_OFFSET; Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImageBase, &InitrdImageBaseSize); if (Status == EFI_OUT_OF_RESOURCES) { Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImageBase, &InitrdImageBaseSize); } if (EFI_ERROR(Status)) { Print (L"ERROR: Did not find initrd image.\n"); goto EXIT_FREE_LINUX; } // Check if the initrd is a uInitrd if (*(UINT32*)((UINTN)InitrdImageBase) == LINUX_UIMAGE_SIGNATURE) { // Skip the 64-byte image header InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImageBase + 64); InitrdImageSize = InitrdImageBaseSize - 64; } else { InitrdImage = InitrdImageBase; InitrdImageSize = InitrdImageBaseSize; } } // // Get the FDT from the Configuration Table. // The FDT will be reloaded in PrepareFdt() to a more appropriate // location for the Linux Kernel. // Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &InstalledFdtBase); if (EFI_ERROR (Status)) { Print (L"ERROR: Did not get the Device Tree blob (%r).\n", Status); goto EXIT_FREE_INITRD; } FdtBlobBase = (EFI_PHYSICAL_ADDRESS)(UINTN)InstalledFdtBase; FdtBlobSize = fdt_totalsize (InstalledFdtBase); // Update the Fdt with the Initrd information. The FDT will increase in size. // By setting address=0 we leave the memory allocation to the function Status = PrepareFdt (CommandLineArguments, InitrdImage, InitrdImageSize, &FdtBlobBase, &FdtBlobSize); if (EFI_ERROR(Status)) { Print(L"ERROR: Can not load kernel with FDT. Status=%r\n", Status); goto EXIT_FREE_FDT; } return StartLinux (LinuxImage, LinuxImageSize, FdtBlobBase, FdtBlobSize, ARM_FDT_MACHINE_TYPE); EXIT_FREE_FDT: gBS->FreePages (FdtBlobBase, EFI_SIZE_TO_PAGES (FdtBlobSize)); EXIT_FREE_INITRD: if (InitrdDevicePath) { gBS->FreePages (InitrdImageBase, EFI_SIZE_TO_PAGES (InitrdImageBaseSize)); } EXIT_FREE_LINUX: gBS->FreePages (LinuxImage, EFI_SIZE_TO_PAGES (LinuxImageSize)); return Status; }
/** Publish and remove the iSCSI Boot Firmware Table according to the iSCSI session status. **/ VOID IScsiPublishIbft ( VOID ) { EFI_STATUS Status; EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol; EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table; UINTN HandleCount; EFI_HANDLE *HandleBuffer; UINT8 *Heap; UINT8 Checksum; EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; EFI_ACPI_DESCRIPTION_HEADER *Rsdt; EFI_ACPI_DESCRIPTION_HEADER *Xsdt; Rsdt = NULL; Xsdt = NULL; Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTableProtocol); if (EFI_ERROR (Status)) { return ; } // // Find ACPI table RSD_PTR from system table // Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID **) &Rsdp); if (EFI_ERROR (Status)) { Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **) &Rsdp); } if (EFI_ERROR (Status) || (Rsdp == NULL)) { return ; } else if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION && Rsdp->XsdtAddress != 0) { Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->XsdtAddress; } else if (Rsdp->RsdtAddress != 0) { Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress; } if ((Xsdt == NULL) && (Rsdt == NULL)) { return ; } if (mIbftInstalled) { Status = AcpiTableProtocol->UninstallAcpiTable ( AcpiTableProtocol, mTableKey ); if (EFI_ERROR (Status)) { return ; } mIbftInstalled = FALSE; } // // Get all iSCSI private protocols. // Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiCallerIdGuid, NULL, &HandleCount, &HandleBuffer ); if (EFI_ERROR (Status)) { return ; } // // Allocate 4k bytes to hold the ACPI table. // Table = AllocateZeroPool (IBFT_MAX_SIZE); if (Table == NULL) { return ; } Heap = (UINT8 *) Table + IBFT_HEAP_OFFSET; // // Fill in the various section of the iSCSI Boot Firmware Table. // if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) { IScsiInitIbfTableHeader (Table, Xsdt->OemId, &Xsdt->OemTableId); } else { IScsiInitIbfTableHeader (Table, Rsdt->OemId, &Rsdt->OemTableId); } IScsiInitControlSection (Table, HandleCount); IScsiFillInitiatorSection (Table, &Heap, HandleBuffer[0]); IScsiFillNICAndTargetSections (Table, &Heap, HandleCount, HandleBuffer); Checksum = CalculateCheckSum8((UINT8 *)Table, Table->Length); Table->Checksum = Checksum; FreePool (HandleBuffer); // // Install or update the iBFT table. // Status = AcpiTableProtocol->InstallAcpiTable ( AcpiTableProtocol, Table, Table->Length, &mTableKey ); if (EFI_ERROR(Status)) { return; } mIbftInstalled = TRUE; FreePool (Table); }
EFI_STATUS RebuildHeap ( IN OUT HEAP_MANAGER **HeapManagerPtr ) { EFI_STATUS Status; AGESA_STATUS AgesaStatus; UINTN AlignTo16ByteInDxeMem; UINTN TotalAlignTo16ByteInHob; EFI_PEI_HOB_POINTERS Hob; VOID *HobList; VOID *HeapBufferInHob; HEAP_MANAGER *HeapManagerInHob; BUFFER_NODE *HeapHeaderNodeInHob; BUFFER_NODE *HeapCurrentNodeInHob; BUFFER_NODE *HeapPreNodeInHob; HEAP_MANAGER *HeapManagerInDxeMem; BUFFER_NODE *HeapHeaderNodeInDxeMem; BUFFER_NODE *HeapCurrentNodeInDxeMem; BUFFER_NODE *HeapPreNodeInDxeMem; UINT32 OffsetOfHeapCurrentNodeInDxeMem; EFI_HOB_GUID_TYPE *GuidHob; AGESA_BUFFER_PARAMS AllocParams; Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList); ASSERT_EFI_ERROR (Status); Hob.Raw = HobList; HeapBufferInHob = NULL; while (!END_OF_HOB_LIST (Hob)) { GuidHob = GetNextGuidHob (&gAmdHeapHobGuid, HobList); HeapBufferInHob = GET_GUID_HOB_DATA (GuidHob); if (HeapBufferInHob != NULL) { HeapManagerInHob = (HEAP_MANAGER *) HeapBufferInHob; HeapHeaderNodeInHob = (BUFFER_NODE *) ((UINT8 *) HeapManagerInHob + HeapManagerInHob->FirstActiveBufferOffset); HeapCurrentNodeInHob = HeapHeaderNodeInHob; // // 1. Analyse heap buffer from HOB data to calculate the final size for recreating the heap buffers // Reserve maximum pad size for each heap node. // 2. Allocate memory for heap buffers // 3. Copying heap manager data from HOB include extracing 1-byte alignment to 16-byte alignment // // // 1. Analyse heap buffer from HOB data to calculate the final size for recreating the heap buffers. // Reserve maximum pad size for each heap node. // TotalAlignTo16ByteInHob = 0; do { HeapPreNodeInHob = HeapCurrentNodeInHob; TotalAlignTo16ByteInHob += 0xF; HeapCurrentNodeInHob = (BUFFER_NODE *) ((UINT8 *) HeapBufferInHob + HeapCurrentNodeInHob->OffsetOfNextNode); } while (HeapPreNodeInHob->OffsetOfNextNode != AMD_HEAP_INVALID_HEAP_OFFSET); // // 2. Allocate memory for heap buffers // AllocParams.BufferLength = (UINT32) (HeapManagerInHob->UsedSize + TotalAlignTo16ByteInHob + 0x0F); AllocParams.BufferHandle = AMD_HEAP_IN_MAIN_MEMORY_HANDLE; if ((AgesaStatus = AgesaAllocateBuffer (0, &AllocParams)) != AGESA_SUCCESS) { if (AGESA_ERROR > AgesaStatus) { return EFI_OUT_OF_RESOURCES; } } ZeroMem (AllocParams.BufferPointer, AllocParams.BufferLength); *HeapManagerPtr = AllocParams.BufferPointer; // // 3. Copying heap manager data from HOB include extracing 1-byte alignment to 16-byte alignment // HeapManagerInDxeMem = *HeapManagerPtr; HeapManagerInDxeMem->FirstActiveBufferOffset = sizeof (HEAP_MANAGER); HeapManagerInDxeMem->UsedSize = sizeof (HEAP_MANAGER); HeapHeaderNodeInDxeMem = (BUFFER_NODE *) ((UINT8 *) HeapManagerInDxeMem + HeapManagerInDxeMem->FirstActiveBufferOffset); OffsetOfHeapCurrentNodeInDxeMem = HeapManagerInDxeMem->FirstActiveBufferOffset; HeapCurrentNodeInDxeMem = HeapHeaderNodeInDxeMem; HeapCurrentNodeInHob = HeapHeaderNodeInHob; HeapPreNodeInHob = NULL; do { // Create BUFFER_NODE with 16-byte alignment padding considered. // The beginning of data buffer is on 16-byte boundary address. // The structure of a heap buffer would be looked like below. // // +---------------------------------------------------------------------------------+ // | BUFFER_NODE | Pad | IDS SENTINEL ("Head") | Data buffer | IDS SENTINEL ("Tail") | // +---------------------------------------------------------------------------------+ // AlignTo16ByteInDxeMem = ((0x10 - (((UINTN) (VOID *) HeapCurrentNodeInDxeMem + sizeof (BUFFER_NODE) + SIZE_OF_SENTINEL) & 0xF)) & 0xF); HeapCurrentNodeInDxeMem->BufferHandle = HeapCurrentNodeInHob->BufferHandle; HeapCurrentNodeInDxeMem->BufferSize = (UINT32) (HeapCurrentNodeInHob->BufferSize + AlignTo16ByteInDxeMem); HeapCurrentNodeInDxeMem->Persist = HeapCurrentNodeInHob->Persist; HeapCurrentNodeInDxeMem->PadSize = (UINT8) AlignTo16ByteInDxeMem; HeapCurrentNodeInDxeMem->OffsetOfNextNode = OffsetOfHeapCurrentNodeInDxeMem + sizeof (BUFFER_NODE) + HeapCurrentNodeInDxeMem->BufferSize; // Copy buffer data gBS->CopyMem ( (UINT8 *) ((UINT8 *) HeapCurrentNodeInDxeMem + sizeof (BUFFER_NODE) + AlignTo16ByteInDxeMem), (UINT8 *) ((UINT8 *) HeapCurrentNodeInHob + sizeof (BUFFER_NODE)), HeapCurrentNodeInHob->BufferSize ); // Point to the next heap node HeapPreNodeInHob = HeapCurrentNodeInHob; HeapPreNodeInDxeMem = HeapCurrentNodeInDxeMem; HeapCurrentNodeInHob = (BUFFER_NODE *) ((UINT8 *) HeapBufferInHob + HeapCurrentNodeInHob->OffsetOfNextNode); HeapCurrentNodeInDxeMem = (BUFFER_NODE *) ((UINT8 *) HeapManagerInDxeMem + HeapCurrentNodeInDxeMem->OffsetOfNextNode); OffsetOfHeapCurrentNodeInDxeMem = (UINT32) ((UINTN) HeapCurrentNodeInDxeMem - (UINTN) HeapManagerInDxeMem); } while (HeapPreNodeInHob->OffsetOfNextNode != AMD_HEAP_INVALID_HEAP_OFFSET); // // Finalize the last heap node // HeapManagerInDxeMem->UsedSize = (UINT32) HeapPreNodeInDxeMem->OffsetOfNextNode; HeapPreNodeInDxeMem->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET; // // Finalize Heap Manager pointer // No free buffer node is provide after heap recreation. // *HeapManagerPtr = HeapManagerInDxeMem; HeapManagerInDxeMem->FirstActiveBufferOffset = (UINT32) ((UINT8 *) HeapHeaderNodeInDxeMem - (UINT8 *) HeapManagerInDxeMem); HeapManagerInDxeMem->FirstFreeSpaceOffset = AMD_HEAP_INVALID_HEAP_OFFSET; HeapManagerInDxeMem->Signature = HeapManagerInHob->Signature; return EFI_SUCCESS; } } return EFI_NOT_FOUND; }
/** Initialize debug agent. This function is used to set up debug enviroment for source level debug in SMM code. If InitFlag is DEBUG_AGENT_INIT_SMM, it will overirde IDT table entries and initialize debug port. It will get debug agent Mailbox from GUIDed HOB, it it exists, debug agent wiil copied it into the local Mailbox in SMM space. it will overirde IDT table entries and initialize debug port. Context will be NULL. If InitFlag is DEBUG_AGENT_INIT_ENTER_SMI, debug agent will save Debug Registers and get local Mailbox in SMM space. Context will be NULL. If InitFlag is DEBUG_AGENT_INIT_EXIT_SMI, debug agent will restore Debug Registers. Context will be NULL. @param[in] InitFlag Init flag is used to decide initialize process. @param[in] Context Context needed according to InitFlag. @param[in] Function Continue function called by debug agent library; it was optional. **/ VOID EFIAPI InitializeDebugAgent ( IN UINT32 InitFlag, IN VOID *Context, OPTIONAL IN DEBUG_AGENT_CONTINUE Function OPTIONAL ) { EFI_STATUS Status; UINT64 DebugPortHandle; IA32_IDT_GATE_DESCRIPTOR IdtEntry[33]; IA32_DESCRIPTOR IdtDescriptor; IA32_DESCRIPTOR *Ia32Idtr; IA32_IDT_ENTRY *Ia32IdtEntry; IA32_DESCRIPTOR Idtr; UINT16 IdtEntryCount; DEBUG_AGENT_MAILBOX *Mailbox; UINT64 *MailboxLocation; UINT32 DebugTimerFrequency; BOOLEAN PeriodicMode; UINTN TimerCycle; switch (InitFlag) { case DEBUG_AGENT_INIT_SMM: // // Install configuration table for persisted vector handoff info // Status = gSmst->SmmInstallConfigurationTable ( gSmst, &gEfiVectorHandoffTableGuid, (VOID *) &mVectorHandoffInfoDebugAgent[0], sizeof (EFI_VECTOR_HANDOFF_INFO) * mVectorHandoffInfoCount ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "DebugAgent: Cannot install configuration table for persisted vector handoff info!\n")); CpuDeadLoop (); } // // Check if Debug Agent initialized in DXE phase // Status = EfiGetSystemConfigurationTable (&gEfiDebugAgentGuid, (VOID **) &Mailbox); if (Status == EFI_SUCCESS && Mailbox != NULL) { VerifyMailboxChecksum (Mailbox); mMailboxPointer = Mailbox; break; } // // Check if Debug Agent initialized in SEC/PEI phase // Mailbox = GetMailboxFromHob (); if (Mailbox != NULL) { mMailboxPointer = Mailbox; break; } // // Debug Agent was not initialized before, use the local mailbox. // ZeroMem (&mLocalMailbox, sizeof (DEBUG_AGENT_MAILBOX)); Mailbox = &mLocalMailbox; // // Save original IDT entries // AsmReadIdtr (&IdtDescriptor); CopyMem (&IdtEntry, (VOID *)IdtDescriptor.Base, 33 * sizeof(IA32_IDT_GATE_DESCRIPTOR)); // // Initialized Debug Agent // InitializeDebugIdt (); // // Initialize Debug Timer hardware and save its frequency // InitializeDebugTimer (&DebugTimerFrequency, TRUE); UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency); DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((DEBUG_PORT_HANDLE) (UINTN)Mailbox->DebugPortHandle, NULL); UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle); mMailboxPointer = Mailbox; // // Trigger one software interrupt to inform HOST // TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE); SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1); // // Memory has been ready // if (IsHostAttached ()) { // // Trigger one software interrupt to inform HOST // TriggerSoftInterrupt (MEMORY_READY_SIGNATURE); } // // Find and report PE/COFF image info to HOST // FindAndReportModuleImageInfo (SIZE_4KB); // // Restore saved IDT entries // CopyMem ((VOID *)IdtDescriptor.Base, &IdtEntry, 33 * sizeof(IA32_IDT_GATE_DESCRIPTOR)); break; case DEBUG_AGENT_INIT_ENTER_SMI: SaveDebugRegister (); if (!mSmmDebugIdtInitFlag) { // // We only need to initialize Debug IDT table at first SMI entry // after SMM relocation. // InitializeDebugIdt (); mSmmDebugIdtInitFlag = TRUE; } // // Check if CPU APIC Timer is working, otherwise initialize it. // InitializeLocalApicSoftwareEnable (TRUE); GetApicTimerState (NULL, &PeriodicMode, NULL); TimerCycle = GetApicTimerInitCount (); if (!PeriodicMode || TimerCycle == 0) { InitializeDebugTimer (NULL, FALSE); } Mailbox = GetMailboxPointer (); if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) { // // If Debug Agent has been communicaton state with HOST, we need skip // any break points set in SMM, set Skip Breakpoint flag // mSkipBreakpoint = TRUE; } if (GetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI) == 1) { if (mSkipBreakpoint) { // // Print warning message if ignore smm entry break // DebugPortWriteBuffer ((DEBUG_PORT_HANDLE) (UINTN)Mailbox->DebugPortHandle, (UINT8 *)mWarningMsgIgnoreSmmEntryBreak, AsciiStrLen (mWarningMsgIgnoreSmmEntryBreak) ); } else { // // If SMM entry break is set, SMM code will be break at here. // CpuBreakpoint (); } } break; case DEBUG_AGENT_INIT_EXIT_SMI: Mailbox = GetMailboxPointer (); // // Clear Skip Breakpoint flag // mSkipBreakpoint = FALSE; RestoreDebugRegister (); break; case DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64: if (Context == NULL) { DEBUG ((EFI_D_ERROR, "DebugAgent: Input parameter Context cannot be NULL!\n")); CpuDeadLoop (); } else { Ia32Idtr = (IA32_DESCRIPTOR *) Context; Ia32IdtEntry = (IA32_IDT_ENTRY *)(Ia32Idtr->Base); MailboxLocation = (UINT64 *) (UINTN) (Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow + (UINT32) (Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16)); mMailboxPointer = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation); VerifyMailboxChecksum (mMailboxPointer); // // Get original IDT address and size. // AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr); IdtEntryCount = (UINT16) ((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR)); if (IdtEntryCount < 33) { Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1); Idtr.Base = (UINTN) &mIdtEntryTable; ZeroMem (&mIdtEntryTable, Idtr.Limit + 1); AsmWriteIdtr ((IA32_DESCRIPTOR *) &Idtr); } InitializeDebugIdt (); // // Initialize Debug Timer hardware and save its frequency // InitializeDebugTimer (&DebugTimerFrequency, TRUE); UpdateMailboxContent (mMailboxPointer, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency); // // Enable Debug Timer interrupt and CPU interrupt // SaveAndSetDebugTimerInterrupt (TRUE); EnableInterrupts (); FindAndReportModuleImageInfo (SIZE_4KB); } break; default: // // Only DEBUG_AGENT_INIT_PREMEM_SEC and DEBUG_AGENT_INIT_POSTMEM_SEC are allowed for this // Debug Agent library instance. // DEBUG ((EFI_D_ERROR, "Debug Agent: The InitFlag value is not allowed!\n")); CpuDeadLoop (); break; } }
/** Measure and log EFI handoff tables, and extend the measurement result into PCR[1]. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The operation was unsuccessful. **/ EFI_STATUS EFIAPI MeasureHandoffTables ( VOID ) { EFI_STATUS Status; SMBIOS_TABLE_ENTRY_POINT *SmbiosTable; TCG_PCR_EVENT_HDR TcgEvent; EFI_HANDOFF_TABLE_POINTERS HandoffTables; UINTN ProcessorNum; EFI_CPU_PHYSICAL_LOCATION *ProcessorLocBuf; // // Measure SMBIOS with EV_EFI_HANDOFF_TABLES to PCR[1] // Status = EfiGetSystemConfigurationTable ( &gEfiSmbiosTableGuid, (VOID **) &SmbiosTable ); if (!EFI_ERROR (Status)) { ASSERT (SmbiosTable != NULL); TcgEvent.PCRIndex = 1; TcgEvent.EventType = EV_EFI_HANDOFF_TABLES; TcgEvent.EventSize = sizeof (HandoffTables); HandoffTables.NumberOfTables = 1; HandoffTables.TableEntry[0].VendorGuid = gEfiSmbiosTableGuid; HandoffTables.TableEntry[0].VendorTable = SmbiosTable; DEBUG ((DEBUG_INFO, "The Smbios Table starts at: 0x%x\n", SmbiosTable->TableAddress)); DEBUG ((DEBUG_INFO, "The Smbios Table size: 0x%x\n", SmbiosTable->TableLength)); Status = TcgDxeHashLogExtendEventI ( &mTcgDxeData, (UINT8*)(UINTN)SmbiosTable->TableAddress, SmbiosTable->TableLength, &TcgEvent, (UINT8*)&HandoffTables ); } if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_SERVER) { // // Tcg Server spec. // Measure each processor EFI_CPU_PHYSICAL_LOCATION with EV_TABLE_OF_DEVICES to PCR[1] // Status = GetProcessorsCpuLocation(&ProcessorLocBuf, &ProcessorNum); if (!EFI_ERROR(Status)) { TcgEvent.PCRIndex = 1; TcgEvent.EventType = EV_TABLE_OF_DEVICES; TcgEvent.EventSize = sizeof (HandoffTables); HandoffTables.NumberOfTables = 1; HandoffTables.TableEntry[0].VendorGuid = gEfiMpServiceProtocolGuid; HandoffTables.TableEntry[0].VendorTable = ProcessorLocBuf; Status = TcgDxeHashLogExtendEventI ( &mTcgDxeData, (UINT8*)(UINTN)ProcessorLocBuf, sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum, &TcgEvent, (UINT8*)&HandoffTables ); FreePool(ProcessorLocBuf); } } return Status; }
/** Internal constructor worker function. It will register one callback function on EFI PCD Protocol. It will allocate the NVS memory to store Mailbox and install configuration table in system table to store its pointer. **/ VOID InternalConstructorWorker ( VOID ) { EFI_STATUS Status; EFI_PHYSICAL_ADDRESS Address; BOOLEAN DebugTimerInterruptState; DEBUG_AGENT_MAILBOX *Mailbox; DEBUG_AGENT_MAILBOX *NewMailbox; EFI_HOB_GUID_TYPE *GuidHob; EFI_VECTOR_HANDOFF_INFO *VectorHandoffInfo; // // Check persisted vector handoff info // Status = EFI_SUCCESS; GuidHob = GetFirstGuidHob (&gEfiVectorHandoffInfoPpiGuid); if (GuidHob != NULL && !mDxeCoreFlag) { // // Check if configuration table is installed or not if GUIDed HOB existed, // only when Debug Agent is not linked by DXE Core // Status = EfiGetSystemConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID **) &VectorHandoffInfo); } if (GuidHob == NULL || Status != EFI_SUCCESS) { // // Install configuration table for persisted vector handoff info if GUIDed HOB cannot be found or // configuration table does not exist // Status = gBS->InstallConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID *) &mVectorHandoffInfoDebugAgent[0]); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "DebugAgent: Cannot install configuration table for persisted vector handoff info!\n")); CpuDeadLoop (); } } // // Install EFI Serial IO protocol on debug port // InstallSerialIo (); Address = 0; Status = gBS->AllocatePages ( AllocateAnyPages, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES (sizeof(DEBUG_AGENT_MAILBOX) + PcdGet16(PcdDebugPortHandleBufferSize)), &Address ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "DebugAgent: Cannot install configuration table for mailbox!\n")); CpuDeadLoop (); } DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE); NewMailbox = (DEBUG_AGENT_MAILBOX *) (UINTN) Address; // // Copy Mailbox and Debug Port Handle buffer to new location in ACPI NVS memory, because original Mailbox // and Debug Port Handle buffer may be free at runtime, SMM debug agent needs to access them // Mailbox = GetMailboxPointer (); CopyMem (NewMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX)); CopyMem (NewMailbox + 1, (VOID *)(UINTN)Mailbox->DebugPortHandle, PcdGet16(PcdDebugPortHandleBufferSize)); // // Update Debug Port Handle in new Mailbox // UpdateMailboxContent (NewMailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, (UINT64)(UINTN)(NewMailbox + 1)); mMailboxPointer = NewMailbox; DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState); Status = gBS->InstallConfigurationTable (&gEfiDebugAgentGuid, (VOID *) mMailboxPointer); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "DebugAgent: Failed to install configuration for mailbox!\n")); CpuDeadLoop (); } }