/** Runs diagnostics on a controller. @param This A pointer to the EFI_DRIVER_DIAGNOSTICS_PROTOCOLinstance. @param ControllerHandle The handle of the controller to run diagnostics on. @param ChildHandle The handle of the child controller to run diagnostics on This is an optional parameter that may be NULL. It will be NULL for device drivers. It will also be NULL for a bus drivers that wish to run diagnostics on the bus controller. It will not be NULL for a bus driver that wishes to run diagnostics on one of its child controllers. @param DiagnosticType Indicates type of diagnostics to perform on the controller specified by ControllerHandle and ChildHandle. @param Language A pointer to a three character ISO 639-2 language identifier. This is the language in which the optional error message should be returned in Buffer, and it must match one of the languages specified in SupportedLanguages. The number of languages supported by a driver is up to the driver writer. @param ErrorType A GUID that defines the format of the data returned in Buffer. @param BufferSize The size, in bytes, of the data returned in Buffer. @param Buffer A buffer that contains a Null-terminated Unicode string plus some additional data whose format is defined by ErrorType. Buffer is allocated by this function with AllocatePool(), and it is the caller's responsibility to free it with a call to FreePool(). @retval EFI_SUCCESS The controller specified by ControllerHandle and ChildHandle passed the diagnostic. @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. @retval EFI_INVALID_PARAMETER Language is NULL. @retval EFI_INVALID_PARAMETER ErrorType is NULL. @retval EFI_INVALID_PARAMETER BufferType is NULL. @retval EFI_INVALID_PARAMETER Buffer is NULL. @retval EFI_UNSUPPORTED The driver specified by This does not support running diagnostics for the controller specified by ControllerHandle and ChildHandle. @retval EFI_UNSUPPORTED The driver specified by This does not support the type of diagnostic specified by DiagnosticType. @retval EFI_UNSUPPORTED The driver specified by This does not support the language specified by Language. @retval EFI_OUT_OF_RESOURCES There are not enough resources available to complete the diagnostics. @retval EFI_OUT_OF_RESOURCES There are not enough resources available to return the status information in ErrorType, BufferSize,and Buffer. @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and ChildHandle did not pass the diagnostic. **/ EFI_STATUS EFIAPI IDEBusDriverDiagnosticsRunDiagnostics ( IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_HANDLE ChildHandle OPTIONAL, IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType, IN CHAR8 *Language, OUT EFI_GUID **ErrorType, OUT UINTN *BufferSize, OUT CHAR16 **Buffer ) { EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; EFI_BLOCK_IO_PROTOCOL *BlkIo; IDE_BLK_IO_DEV *IdeBlkIoDevice; UINT32 VendorDeviceId; VOID *BlockBuffer; CHAR8 *SupportedLanguages; BOOLEAN Iso639Language; BOOLEAN Found; UINTN Index; if (Language == NULL || ErrorType == NULL || Buffer == NULL || ControllerHandle == NULL || BufferSize == NULL) { return EFI_INVALID_PARAMETER; } SupportedLanguages = This->SupportedLanguages; Iso639Language = (BOOLEAN)(This == &gIDEBusDriverDiagnostics); // // Make sure Language is in the set of Supported Languages // Found = FALSE; while (*SupportedLanguages != 0) { if (Iso639Language) { if (CompareMem (Language, SupportedLanguages, 3) == 0) { Found = TRUE; break; } SupportedLanguages += 3; } else { for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++); if ((AsciiStrnCmp(SupportedLanguages, Language, Index) == 0) && (Language[Index] == 0)) { Found = TRUE; break; } SupportedLanguages += Index; for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++); } } // // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED // if (!Found) { return EFI_UNSUPPORTED; } *ErrorType = NULL; *BufferSize = 0; if (ChildHandle == NULL) { Status = gBS->OpenProtocol ( ControllerHandle, &gEfiCallerIdGuid, NULL, gIDEBusDriverBinding.DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); if (EFI_ERROR (Status)) { return Status; } Status = gBS->OpenProtocol ( ControllerHandle, &gEfiPciIoProtocolGuid, (VOID **) &PciIo, gIDEBusDriverBinding.DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } // // Use services of PCI I/O Protocol to test the PCI IDE/ATAPI Controller // The following test simply reads the Device ID and Vendor ID. // It should never fail. A real test would perform more advanced // diagnostics. // Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, 1, &VendorDeviceId); if (EFI_ERROR (Status) || VendorDeviceId == 0xffffffff) { return EFI_DEVICE_ERROR; } return EFI_SUCCESS; } Status = gBS->OpenProtocol ( ChildHandle, &gEfiBlockIoProtocolGuid, (VOID **) &BlkIo, gIDEBusDriverBinding.DriverBindingHandle, ChildHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return Status; } IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo); // // Use services available from IdeBlkIoDevice to test the IDE/ATAPI device // Status = gBS->AllocatePool ( EfiBootServicesData, IdeBlkIoDevice->BlkMedia.BlockSize, (VOID **) &BlockBuffer ); if (EFI_ERROR (Status)) { return Status; } Status = IdeBlkIoDevice->BlkIo.ReadBlocks ( &IdeBlkIoDevice->BlkIo, IdeBlkIoDevice->BlkMedia.MediaId, 0, IdeBlkIoDevice->BlkMedia.BlockSize, BlockBuffer ); if (EFI_ERROR (Status)) { *ErrorType = &gEfiCallerIdGuid; *BufferSize = sizeof (IDE_BUS_DIAGNOSTIC_ERROR); Status = gBS->AllocatePool ( EfiBootServicesData, (UINTN) (*BufferSize), (VOID **) Buffer ); if (EFI_ERROR (Status)) { return Status; } CopyMem (*Buffer, IDE_BUS_DIAGNOSTIC_ERROR, *BufferSize); Status = EFI_DEVICE_ERROR; } gBS->FreePool (BlockBuffer); return Status; }
/** Initialize the system (or sometimes called permanent) memory This memory is generally represented by the DRAM. This function is called from InitializeMemory() in MemoryInitPeim, in the PEI phase. **/ VOID ArmPlatformInitializeSystemMemory ( VOID ) { VOID *DeviceTreeBase; INT32 Node, Prev; UINT64 NewBase; UINT64 NewSize; CONST CHAR8 *Type; INT32 Len; CONST UINT64 *RegProp; NewBase = 0; NewSize = 0; DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress); ASSERT (DeviceTreeBase != NULL); // // Make sure we have a valid device tree blob // ASSERT (fdt_check_header (DeviceTreeBase) == 0); // // Look for a memory node // for (Prev = 0;; Prev = Node) { Node = fdt_next_node (DeviceTreeBase, Prev, NULL); if (Node < 0) { break; } // // Check for memory node // Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len); if (Type && AsciiStrnCmp (Type, "memory", Len) == 0) { // // Get the 'reg' property of this node. For now, we will assume // two 8 byte quantities for base and size, respectively. // RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len); if (RegProp != 0 && Len == (2 * sizeof (UINT64))) { NewBase = fdt64_to_cpu (ReadUnaligned64 (RegProp)); NewSize = fdt64_to_cpu (ReadUnaligned64 (RegProp + 1)); // // Make sure the start of DRAM matches our expectation // ASSERT (FixedPcdGet64 (PcdSystemMemoryBase) == NewBase); PcdSet64 (PcdSystemMemorySize, NewSize); DEBUG ((EFI_D_INFO, "%a: System RAM @ 0x%lx - 0x%lx\n", __FUNCTION__, NewBase, NewBase + NewSize - 1)); } else { DEBUG ((EFI_D_ERROR, "%a: Failed to parse FDT memory node\n", __FUNCTION__)); } break; } } // // We need to make sure that the machine we are running on has at least // 128 MB of memory configured, and is currently executing this binary from // NOR flash. This prevents a device tree image in DRAM from getting // clobbered when our caller installs permanent PEI RAM, before we have a // chance of marking its location as reserved or copy it to a freshly // allocated block in the permanent PEI RAM in the platform PEIM. // ASSERT (NewSize >= SIZE_128MB); ASSERT ( (((UINT64)PcdGet64 (PcdFdBaseAddress) + (UINT64)PcdGet32 (PcdFdSize)) <= NewBase) || ((UINT64)PcdGet64 (PcdFdBaseAddress) >= (NewBase + NewSize))); }
EFI_STATUS EFIAPI EmuBlockIoDriverDiagnosticsRunDiagnostics ( IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_HANDLE ChildHandle OPTIONAL, IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType, IN CHAR8 *Language, OUT EFI_GUID **ErrorType, OUT UINTN *BufferSize, OUT CHAR16 **Buffer ) /*++ Routine Description: Runs diagnostics on a controller. Arguments: This - A pointer to the EFI_DRIVER_DIAGNOSTICS_PROTOCOL instance. ControllerHandle - The handle of the controller to run diagnostics on. ChildHandle - The handle of the child controller to run diagnostics on This is an optional parameter that may be NULL. It will be NULL for device drivers. It will also be NULL for a bus drivers that wish to run diagnostics on the bus controller. It will not be NULL for a bus driver that wishes to run diagnostics on one of its child controllers. DiagnosticType - Indicates type of diagnostics to perform on the controller specified by ControllerHandle and ChildHandle. See "Related Definitions" for the list of supported types. Language - A pointer to a three character ISO 639-2 language identifier or a Null-terminated ASCII string array indicating the language. This is the language in which the optional error message should be returned in Buffer, and it must match one of the languages specified in SupportedLanguages. The number of languages supported by a driver is up to the driver writer. ErrorType - A GUID that defines the format of the data returned in Buffer. BufferSize - The size, in bytes, of the data returned in Buffer. Buffer - A buffer that contains a Null-terminated Unicode string plus some additional data whose format is defined by ErrorType. Buffer is allocated by this function with AllocatePool(), and it is the caller's responsibility to free it with a call to FreePool(). Returns: EFI_SUCCESS - The controller specified by ControllerHandle and ChildHandle passed the diagnostic. EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. EFI_INVALID_PARAMETER - Language is NULL. EFI_INVALID_PARAMETER - ErrorType is NULL. EFI_INVALID_PARAMETER - BufferType is NULL. EFI_INVALID_PARAMETER - Buffer is NULL. EFI_UNSUPPORTED - The driver specified by This does not support running diagnostics for the controller specified by ControllerHandle and ChildHandle. EFI_UNSUPPORTED - The driver specified by This does not support the type of diagnostic specified by DiagnosticType. EFI_UNSUPPORTED - The driver specified by This does not support the language specified by Language. EFI_OUT_OF_RESOURCES - There are not enough resources available to complete the diagnostics. EFI_OUT_OF_RESOURCES - There are not enough resources available to return the status information in ErrorType, BufferSize, and Buffer. EFI_DEVICE_ERROR - The controller specified by ControllerHandle and ChildHandle did not pass the diagnostic. --*/ { EFI_STATUS Status; EFI_BLOCK_IO_PROTOCOL *BlockIo; CHAR8 *SupportedLanguages; BOOLEAN Iso639Language; BOOLEAN Found; UINTN Index; if (Language == NULL || ErrorType == NULL || Buffer == NULL || ControllerHandle == NULL || BufferSize == NULL) { return EFI_INVALID_PARAMETER; } SupportedLanguages = This->SupportedLanguages; Iso639Language = (BOOLEAN)(This == &gEmuBlockIoDriverDiagnostics); // // Make sure Language is in the set of Supported Languages // Found = FALSE; while (*SupportedLanguages != 0) { if (Iso639Language) { if (CompareMem (Language, SupportedLanguages, 3) == 0) { Found = TRUE; break; } SupportedLanguages += 3; } else { for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++); if ((AsciiStrnCmp(SupportedLanguages, Language, Index) == 0) && (Language[Index] == 0)) { Found = TRUE; break; } SupportedLanguages += Index; for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++); } } // // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED // if (!Found) { return EFI_UNSUPPORTED; } *ErrorType = NULL; *BufferSize = 0; if (DiagnosticType != EfiDriverDiagnosticTypeStandard) { *ErrorType = &gEfiBlockIoProtocolGuid; *BufferSize = 0x60; Buffer = AllocatePool ((UINTN) (*BufferSize)); CopyMem (*Buffer, L"Windows Block I/O Driver Diagnostics Failed\n", *BufferSize); return EFI_DEVICE_ERROR; } // // This is a device driver, so ChildHandle must be NULL. // if (ChildHandle != NULL) { return EFI_UNSUPPORTED; } // // Validate controller handle // Status = gBS->OpenProtocol ( ControllerHandle, &gEmuIoThunkProtocolGuid, (VOID **)&BlockIo, gEmuBlockIoDriverBinding.DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (!EFI_ERROR (Status)) { gBS->CloseProtocol ( ControllerHandle, &gEmuIoThunkProtocolGuid, gEmuBlockIoDriverBinding.DriverBindingHandle, ControllerHandle ); return EFI_UNSUPPORTED; } if (Status == EFI_UNSUPPORTED) { return Status; } else if (Status != EFI_ALREADY_STARTED) { return EFI_INVALID_PARAMETER; } return EFI_SUCCESS; }
/*++ Check whether the language is supported for given HII handle @param HiiHandle The HII package list handle. @param Offset The offest of current lanague in the supported languages. @param CurrentLang The language code. @retval TRUE Supported. @retval FALSE Not Supported. --*/ VOID EFIAPI CurrentLanguageMatch ( IN EFI_HII_HANDLE HiiHandle, OUT UINT16 *Offset, OUT CHAR8 *CurrentLang ) { CHAR8 *DefaultLang; CHAR8 *BestLanguage; CHAR8 *Languages; CHAR8 *MatchLang; CHAR8 *EndMatchLang; UINTN CompareLength; Languages = HiiGetSupportedLanguages (HiiHandle); if (Languages == NULL) { return; } CurrentLang = GetEfiGlobalVariable (L"PlatformLang"); DefaultLang = (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang); BestLanguage = GetBestLanguage ( Languages, FALSE, (CurrentLang != NULL) ? CurrentLang : "", DefaultLang, NULL ); if (BestLanguage != NULL) { // // Find the best matching RFC 4646 language, compute the offset. // CompareLength = AsciiStrLen (BestLanguage); for (MatchLang = Languages, (*Offset) = 0; MatchLang != '\0'; (*Offset)++) { // // Seek to the end of current match language. // for (EndMatchLang = MatchLang; *EndMatchLang != '\0' && *EndMatchLang != ';'; EndMatchLang++); if ((EndMatchLang == MatchLang + CompareLength) && AsciiStrnCmp(MatchLang, BestLanguage, CompareLength) == 0) { // // Find the current best Language in the supported languages // break; } // // best language match be in the supported language. // ASSERT (*EndMatchLang == ';'); MatchLang = EndMatchLang + 1; } FreePool (BestLanguage); } FreePool (Languages); if (CurrentLang != NULL) { FreePool (CurrentLang); } return ; }
/** Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed ACPI tables are: FACP, APIC, HPET, WAET, SSDT, FACS, DSDT. @param AcpiProtocol Protocol instance pointer. @return EFI_SUCCESS The table was successfully inserted. @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableHandle is NULL, or AcpiTableBufferSize and the size field embedded in the ACPI table pointed to by AcpiTableBuffer are not in sync. @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request. **/ EFI_STATUS EFIAPI InstallXenTables ( IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol ) { EFI_STATUS Status; UINTN TableHandle; EFI_ACPI_DESCRIPTION_HEADER *Rsdt; EFI_ACPI_DESCRIPTION_HEADER *Xsdt; VOID *CurrentTableEntry; UINTN CurrentTablePointer; EFI_ACPI_DESCRIPTION_HEADER *CurrentTable; UINTN Index; UINTN NumberOfTableEntries; EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt2Table; EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt1Table; EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs2Table; EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs1Table; EFI_ACPI_DESCRIPTION_HEADER *DsdtTable; Fadt2Table = NULL; Fadt1Table = NULL; Facs2Table = NULL; Facs1Table = NULL; DsdtTable = NULL; TableHandle = 0; NumberOfTableEntries = 0; // // Try to find Xen ACPI tables // Status = GetXenAcpiRsdp (&XenAcpiRsdpStructurePtr); if (EFI_ERROR (Status)) { return Status; } // // If XSDT table is find, just install its tables. // Otherwise, try to find and install the RSDT tables. // if (XenAcpiRsdpStructurePtr->XsdtAddress) { // // Retrieve the addresses of XSDT and // calculate the number of its table entries. // Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) XenAcpiRsdpStructurePtr->XsdtAddress; NumberOfTableEntries = (Xsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof (UINT64); // // Install ACPI tables found in XSDT. // for (Index = 0; Index < NumberOfTableEntries; Index++) { // // Get the table entry from XSDT // CurrentTableEntry = (VOID *) ((UINT8 *) Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + Index * sizeof (UINT64)); CurrentTablePointer = (UINTN) *(UINT64 *)CurrentTableEntry; CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTablePointer; // // Install the XSDT tables // Status = InstallAcpiTable ( AcpiProtocol, CurrentTable, CurrentTable->Length, &TableHandle ); if (EFI_ERROR (Status)) { return Status; } // // Get the FACS and DSDT table address from the table FADT // if (!AsciiStrnCmp ((CHAR8 *) &CurrentTable->Signature, "FACP", 4)) { Fadt2Table = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) (UINTN) CurrentTablePointer; Facs2Table = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) (UINTN) Fadt2Table->FirmwareCtrl; DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Fadt2Table->Dsdt; } } } else if (XenAcpiRsdpStructurePtr->RsdtAddress) { // // Retrieve the addresses of RSDT and // calculate the number of its table entries. // Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) XenAcpiRsdpStructurePtr->RsdtAddress; NumberOfTableEntries = (Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof (UINT32); // // Install ACPI tables found in XSDT. // for (Index = 0; Index < NumberOfTableEntries; Index++) { // // Get the table entry from RSDT // CurrentTableEntry = (UINT32 *) ((UINT8 *) Rsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + Index * sizeof (UINT32)); CurrentTablePointer = *(UINT32 *)CurrentTableEntry; CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTablePointer; // // Install the RSDT tables // Status = InstallAcpiTable ( AcpiProtocol, CurrentTable, CurrentTable->Length, &TableHandle ); if (EFI_ERROR (Status)) { return Status; } // // Get the FACS and DSDT table address from the table FADT // if (!AsciiStrnCmp ((CHAR8 *) &CurrentTable->Signature, "FACP", 4)) { Fadt1Table = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *) (UINTN) CurrentTablePointer; Facs1Table = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) (UINTN) Fadt1Table->FirmwareCtrl; DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Fadt1Table->Dsdt; } } } // // Install the FACS table. // if (Fadt2Table) { // // FACS 2.0 // Status = InstallAcpiTable ( AcpiProtocol, Facs2Table, Facs2Table->Length, &TableHandle ); if (EFI_ERROR (Status)) { return Status; } } else if (Fadt1Table) { // // FACS 1.0 // Status = InstallAcpiTable ( AcpiProtocol, Facs1Table, Facs1Table->Length, &TableHandle ); if (EFI_ERROR (Status)) { return Status; } } // // Install DSDT table. // Status = InstallAcpiTable ( AcpiProtocol, DsdtTable, DsdtTable->Length, &TableHandle ); if (EFI_ERROR (Status)) { return Status; } return EFI_SUCCESS; }
/** Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed ACPI tables are: FACP, APIC, GTDT, DSDT. @param AcpiProtocol Protocol instance pointer. @return EFI_SUCCESS The table was successfully inserted. @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableHandle is NULL, or AcpiTableBufferSize and the size field embedded in the ACPI table pointed to by AcpiTableBuffer are not in sync. @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request. **/ STATIC EFI_STATUS EFIAPI InstallXenArmTables ( IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol ) { EFI_STATUS Status; UINTN TableHandle; VOID *CurrentTableEntry; UINTN CurrentTablePointer; EFI_ACPI_DESCRIPTION_HEADER *CurrentTable; UINTN Index; UINTN NumberOfTableEntries; EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *XenAcpiRsdpStructurePtr; EFI_ACPI_DESCRIPTION_HEADER *Xsdt; EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtTable; EFI_ACPI_DESCRIPTION_HEADER *DsdtTable; XenAcpiRsdpStructurePtr = NULL; FadtTable = NULL; DsdtTable = NULL; TableHandle = 0; NumberOfTableEntries = 0; // // Try to find Xen ARM ACPI tables // Status = GetXenArmAcpiRsdp (&XenAcpiRsdpStructurePtr); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_INFO, "%a: No RSDP table found\n", __FUNCTION__)); return Status; } // // If XSDT table is find, just install its tables. // if (XenAcpiRsdpStructurePtr->XsdtAddress) { // // Retrieve the addresses of XSDT and // calculate the number of its table entries. // Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) XenAcpiRsdpStructurePtr->XsdtAddress; NumberOfTableEntries = (Xsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof (UINT64); // // Install ACPI tables found in XSDT. // for (Index = 0; Index < NumberOfTableEntries; Index++) { // // Get the table entry from XSDT // CurrentTableEntry = (VOID *) ((UINT8 *) Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + Index * sizeof (UINT64)); CurrentTablePointer = (UINTN) *(UINT64 *)CurrentTableEntry; CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTablePointer; // // Install the XSDT tables // Status = AcpiProtocol->InstallAcpiTable ( AcpiProtocol, CurrentTable, CurrentTable->Length, &TableHandle ); if (EFI_ERROR (Status)) { return Status; } // // Get the FACS and DSDT table address from the table FADT // if (!AsciiStrnCmp ((CHAR8 *) &CurrentTable->Signature, "FACP", 4)) { FadtTable = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) (UINTN) CurrentTablePointer; DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) FadtTable->Dsdt; } } } // // Install DSDT table. // Status = AcpiProtocol->InstallAcpiTable ( AcpiProtocol, DsdtTable, DsdtTable->Length, &TableHandle ); if (EFI_ERROR (Status)) { return Status; } return EFI_SUCCESS; }
/** Worker function that get the size in numbers of bytes of a file from a TFTP server before to download the file. @param[in] Mtftp4 MTFTP4 protocol interface @param[in] FilePath Path of the file, Ascii encoded @param[out] FileSize Address where to store the file size in number of bytes. @retval EFI_SUCCESS The size of the file was returned. @retval !EFI_SUCCESS The size of the file was not returned. **/ STATIC EFI_STATUS Mtftp4GetFileSize ( IN EFI_MTFTP4_PROTOCOL *Mtftp4, IN CHAR8 *FilePath, OUT UINT64 *FileSize ) { EFI_STATUS Status; EFI_MTFTP4_OPTION ReqOpt[1]; EFI_MTFTP4_PACKET *Packet; UINT32 PktLen; EFI_MTFTP4_OPTION *TableOfOptions; EFI_MTFTP4_OPTION *Option; UINT32 OptCnt; UINT8 OptBuf[128]; ReqOpt[0].OptionStr = (UINT8*)"tsize"; OptBuf[0] = '0'; OptBuf[1] = 0; ReqOpt[0].ValueStr = OptBuf; Status = Mtftp4->GetInfo ( Mtftp4, NULL, (UINT8*)FilePath, NULL, 1, ReqOpt, &PktLen, &Packet ); if (EFI_ERROR (Status)) { goto Error; } Status = Mtftp4->ParseOptions ( Mtftp4, PktLen, Packet, (UINT32 *) &OptCnt, &TableOfOptions ); if (EFI_ERROR (Status)) { goto Error; } Option = TableOfOptions; while (OptCnt != 0) { if (AsciiStrnCmp ((CHAR8 *)Option->OptionStr, "tsize", 5) == 0) { *FileSize = AsciiStrDecimalToUint64 ((CHAR8 *)Option->ValueStr); break; } OptCnt--; Option++; } FreePool (TableOfOptions); if (OptCnt == 0) { Status = EFI_UNSUPPORTED; } Error : return Status; }
/** Gather and print PEIM data. Only prints complete PEIM records **/ VOID ProcessPeims( VOID ) { MEASUREMENT_RECORD Measurement; UINT64 Duration; UINT64 ElapsedTime; EFI_STRING StringPtr; UINTN LogEntryKey; UINTN TIndex; EFI_STRING StringPtrUnknown; StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PEIMS), NULL); PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), (StringPtr == NULL) ? StringPtrUnknown : StringPtr); FreePool (StringPtr); FreePool (StringPtrUnknown); if (mShowId) { PrintToken (STRING_TOKEN (STR_DP_PEIM_SECTION2)); } else { PrintToken (STRING_TOKEN (STR_DP_PEIM_SECTION)); } PrintToken (STRING_TOKEN (STR_DP_DASHES)); TIndex = 0; LogEntryKey = 0; while ((LogEntryKey = GetPerformanceMeasurementEx ( LogEntryKey, &Measurement.Handle, &Measurement.Token, &Measurement.Module, &Measurement.StartTimeStamp, &Measurement.EndTimeStamp, &Measurement.Identifier)) != 0) { TIndex++; if ((Measurement.EndTimeStamp == 0) || (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) != 0) ) { continue; } Duration = GetDuration (&Measurement); ElapsedTime = DurationInMicroSeconds ( Duration ); // Calculate elapsed time in microseconds if (ElapsedTime >= mInterestThreshold) { // PEIM FILE Handle is the start address of its FFS file that contains its file guid. if (mShowId) { PrintToken (STRING_TOKEN (STR_DP_PEIM_VARS2), TIndex, // 1 based, Which measurement record is being printed Measurement.Handle, // base address Measurement.Handle, // file guid ElapsedTime, Measurement.Identifier ); } else { PrintToken (STRING_TOKEN (STR_DP_PEIM_VARS), TIndex, // 1 based, Which measurement record is being printed Measurement.Handle, // base address Measurement.Handle, // file guid ElapsedTime ); } } } }
/** This function is to get size of a file using Tftp. @param[in] Private Pointer to PxeBc private data. @param[in] Config Pointer to EFI_MTFTP4_CONFIG_DATA. @param[in] Filename Pointer to boot file name. @param[in] BlockSize Pointer to required block size. @param[in, out] BufferSize Pointer to buffer size. @retval EFI_SUCCESS Successfully obtained the size of file. @retval EFI_NOT_FOUND Parse the tftp options failed. @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. @retval Others Did not obtain the size of the file. **/ EFI_STATUS PxeBcMtftp4GetFileSize ( IN PXEBC_PRIVATE_DATA *Private, IN EFI_MTFTP4_CONFIG_DATA *Config, IN UINT8 *Filename, IN UINTN *BlockSize, IN OUT UINT64 *BufferSize ) { EFI_MTFTP4_PROTOCOL *Mtftp4; EFI_MTFTP4_OPTION ReqOpt[2]; EFI_MTFTP4_PACKET *Packet; EFI_MTFTP4_OPTION *Option; UINT32 PktLen; UINT8 OptBuf[128]; UINT32 OptCnt; EFI_STATUS Status; *BufferSize = 0; Status = EFI_DEVICE_ERROR; Mtftp4 = Private->Mtftp4; Packet = NULL; Option = NULL; PktLen = 0; OptCnt = 1; Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; Status = Mtftp4->Configure (Mtftp4, Config); if (EFI_ERROR (Status)) { return Status; } // // Build the required options for get info. // ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_TSIZE_INDEX]; PxeBcUintnToAscDec (0, OptBuf); ReqOpt[0].ValueStr = OptBuf; if (BlockSize != NULL) { ReqOpt[1].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; ReqOpt[1].ValueStr = (UINT8 *) (ReqOpt[0].ValueStr + AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1); PxeBcUintnToAscDec (*BlockSize, ReqOpt[1].ValueStr); OptCnt++; } Status = Mtftp4->GetInfo ( Mtftp4, FALSE, Filename, NULL, (UINT8) OptCnt, ReqOpt, &PktLen, &Packet ); if (EFI_ERROR (Status)) { if (Status == EFI_TFTP_ERROR) { // // Store the tftp error message into mode data and set the received flag. // Private->Mode.TftpErrorReceived = TRUE; Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode; AsciiStrnCpy ( Private->Mode.TftpError.ErrorString, (CHAR8 *) Packet->Error.ErrorMessage, PXE_MTFTP_ERROR_STRING_LENGTH ); } goto ON_ERROR; } // // Parse the options in the reply packet. // OptCnt = 0; Status = Mtftp4->ParseOptions ( Mtftp4, PktLen, Packet, (UINT32 *) &OptCnt, &Option ); if (EFI_ERROR (Status)) { goto ON_ERROR; } // // Parse out the value of "tsize" option. // Status = EFI_NOT_FOUND; while (OptCnt != 0) { if (AsciiStrnCmp ((CHAR8 *) Option[OptCnt - 1].OptionStr, "tsize", 5) == 0) { *BufferSize = AsciiStrDecimalToUint64 ((CHAR8 *) (Option[OptCnt - 1].ValueStr)); Status = EFI_SUCCESS; } OptCnt--; } FreePool (Option); ON_ERROR: if (Packet != NULL) { FreePool (Packet); } Mtftp4->Configure (Mtftp4, NULL); return Status; }
/** Gather and print Major Phase metrics. @param[in] Ticker The timer value for the END of Shell phase **/ VOID ProcessPhases( IN UINT64 Ticker ) { MEASUREMENT_RECORD Measurement; UINT64 BdsTimeoutValue; UINT64 SecTime; UINT64 PeiTime; UINT64 DxeTime; UINT64 BdsTime; UINT64 ShellTime; UINT64 ElapsedTime; UINT64 Duration; UINT64 Total; EFI_STRING StringPtr; UINTN LogEntryKey; EFI_STRING StringPtrUnknown; BdsTimeoutValue = 0; SecTime = 0; PeiTime = 0; DxeTime = 0; BdsTime = 0; ShellTime = 0; // // Get Execution Phase Statistics // StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PHASES), NULL); PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), (StringPtr == NULL) ? StringPtrUnknown : StringPtr); FreePool (StringPtr); FreePool (StringPtrUnknown); LogEntryKey = 0; while ((LogEntryKey = GetPerformanceMeasurementEx ( LogEntryKey, &Measurement.Handle, &Measurement.Token, &Measurement.Module, &Measurement.StartTimeStamp, &Measurement.EndTimeStamp, &Measurement.Identifier)) != 0) { if (AsciiStrnCmp (Measurement.Token, ALit_SHELL, PERF_TOKEN_LENGTH) == 0) { Measurement.EndTimeStamp = Ticker; } if (Measurement.EndTimeStamp == 0) { // Skip "incomplete" records continue; } Duration = GetDuration (&Measurement); if ( Measurement.Handle != NULL && (AsciiStrnCmp (Measurement.Token, ALit_BdsTO, PERF_TOKEN_LENGTH) == 0) ) { BdsTimeoutValue = Duration; } else if (AsciiStrnCmp (Measurement.Token, ALit_SEC, PERF_TOKEN_LENGTH) == 0) { SecTime = Duration; } else if (AsciiStrnCmp (Measurement.Token, ALit_PEI, PERF_TOKEN_LENGTH) == 0) { PeiTime = Duration; } else if (AsciiStrnCmp (Measurement.Token, ALit_DXE, PERF_TOKEN_LENGTH) == 0) { DxeTime = Duration; } else if (AsciiStrnCmp (Measurement.Token, ALit_BDS, PERF_TOKEN_LENGTH) == 0) { BdsTime = Duration; } else if (AsciiStrnCmp (Measurement.Token, ALit_SHELL, PERF_TOKEN_LENGTH) == 0) { ShellTime = Duration; } } Total = 0; // print SEC phase duration time // if (SecTime > 0) { ElapsedTime = DurationInMicroSeconds ( SecTime ); // Calculate elapsed time in microseconds Total += DivU64x32 (ElapsedTime, 1000); // Accumulate time in milliseconds PrintToken (STRING_TOKEN (STR_DP_SEC_PHASE), ElapsedTime); } // print PEI phase duration time // if (PeiTime > 0) { ElapsedTime = DivU64x32 ( PeiTime, (UINT32)TimerInfo.Frequency ); Total += ElapsedTime; PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_PEI, ElapsedTime); } // print DXE phase duration time // if (DxeTime > 0) { ElapsedTime = DivU64x32 ( DxeTime, (UINT32)TimerInfo.Frequency ); Total += ElapsedTime; PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_DXE, ElapsedTime); } // print BDS phase duration time // if (BdsTime > 0) { ElapsedTime = DivU64x32 ( BdsTime, (UINT32)TimerInfo.Frequency ); Total += ElapsedTime; PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_BDS, ElapsedTime); } if (BdsTimeoutValue > 0) { ElapsedTime = DivU64x32 ( BdsTimeoutValue, (UINT32)TimerInfo.Frequency ); PrintToken (STRING_TOKEN (STR_DP_PHASE_BDSTO), ALit_BdsTO, ElapsedTime); } // print SHELL phase duration time // if (ShellTime > 0) { ElapsedTime = DivU64x32 ( ShellTime, (UINT32)TimerInfo.Frequency ); Total += ElapsedTime; PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_SHELL, ElapsedTime); } PrintToken (STRING_TOKEN (STR_DP_TOTAL_DURATION), Total); }
/** Gather and print ALL Trace Records. Displays all "interesting" Trace measurements in order.<BR> The number of records displayed is controlled by: - records with a duration less than mInterestThreshold microseconds are not displayed. - No more than Limit records are displayed. A Limit of zero will not limit the output. - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not displayed. @pre The mInterestThreshold global variable is set to the shortest duration to be printed. The mGaugeString and mUnicodeToken global arrays are used for temporary string storage. They must not be in use by a calling function. @param[in] Limit The number of records to print. Zero is ALL. @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. **/ VOID DumpAllTrace( IN UINTN Limit, IN BOOLEAN ExcludeFlag ) { MEASUREMENT_RECORD Measurement; UINT64 ElapsedTime; UINT64 Duration; const CHAR16 *IncFlag; UINTN LogEntryKey; UINTN Count; UINTN Index; UINTN TIndex; EFI_HANDLE *HandleBuffer; UINTN Size; EFI_HANDLE TempHandle; EFI_STATUS Status; EFI_STRING StringPtrUnknown; StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_ALL), NULL); PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), (IncFlag == NULL) ? StringPtrUnknown : IncFlag); FreePool (StringPtrUnknown); // Get Handle information // Size = 0; HandleBuffer = &TempHandle; Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, &TempHandle); if (Status == EFI_BUFFER_TOO_SMALL) { HandleBuffer = AllocatePool (Size); ASSERT (HandleBuffer != NULL); if (HandleBuffer == NULL) { return; } Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, HandleBuffer); } if (EFI_ERROR (Status)) { PrintToken (STRING_TOKEN (STR_DP_HANDLES_ERROR), Status); } else { // We have successfully populated the HandleBuffer // Display ALL Measurement Records // Up to Limit lines displayed // Display only records with Elapsed times >= mInterestThreshold // Display driver names in Module field for records with Handles. // if (mShowId) { PrintToken (STRING_TOKEN (STR_DP_ALL_HEADR2) ); PrintToken (STRING_TOKEN (STR_DP_ALL_DASHES2) ); } else { PrintToken (STRING_TOKEN (STR_DP_ALL_HEADR) ); PrintToken (STRING_TOKEN (STR_DP_DASHES) ); } LogEntryKey = 0; Count = 0; Index = 0; while ( WITHIN_LIMIT(Count, Limit) && ((LogEntryKey = GetPerformanceMeasurementEx ( LogEntryKey, &Measurement.Handle, &Measurement.Token, &Measurement.Module, &Measurement.StartTimeStamp, &Measurement.EndTimeStamp, &Measurement.Identifier)) != 0) ) { ++Index; // Count every record. First record is 1. ElapsedTime = 0; SafeFreePool ((VOID *) IncFlag); if (Measurement.EndTimeStamp != 0) { Duration = GetDuration (&Measurement); ElapsedTime = DurationInMicroSeconds ( Duration ); IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_COMPLETE), NULL); } else { IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_INCOMPLETE), NULL); // Mark incomplete records } if (((Measurement.EndTimeStamp != 0) && (ElapsedTime < mInterestThreshold)) || ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0)) ) { // Ignore "uninteresting" or excluded records continue; } ++Count; // Count the number of records printed // If Handle is non-zero, see if we can determine a name for the driver AsciiStrToUnicodeStr (Measurement.Module, mGaugeString); // Use Module by default AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken); if (Measurement.Handle != NULL) { // See if the Handle is in the HandleBuffer for (TIndex = 0; TIndex < (Size / sizeof(HandleBuffer[0])); TIndex++) { if (Measurement.Handle == HandleBuffer[TIndex]) { GetNameFromHandle (HandleBuffer[TIndex]); break; } } } if (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) == 0) { UnicodeSPrint (mGaugeString, sizeof (mGaugeString), L"%g", Measurement.Handle); } // Ensure that the argument strings are not too long. mGaugeString[DP_GAUGE_STRING_LENGTH] = 0; mUnicodeToken[13] = 0; if (mShowId) { PrintToken( STRING_TOKEN (STR_DP_ALL_VARS2), Index, // 1 based, Which measurement record is being printed IncFlag, Measurement.Handle, mGaugeString, mUnicodeToken, ElapsedTime, Measurement.Identifier ); } else { PrintToken( STRING_TOKEN (STR_DP_ALL_VARS), Index, // 1 based, Which measurement record is being printed IncFlag, Measurement.Handle, mGaugeString, mUnicodeToken, ElapsedTime ); } } } if (HandleBuffer != &TempHandle) { FreePool (HandleBuffer); } SafeFreePool ((VOID *) IncFlag); }
/** This function is to get size of a file by Tftp. @param Private Pointer to PxeBc private data @param Config Pointer to Mtftp configuration data @param Filename Pointer to file name @param BlockSize Pointer to block size @param BufferSize Pointer to buffer size @retval EFI_SUCCESS Get the size of file success @retval EFI_NOT_FOUND Parse the tftp ptions failed. @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. @retval Other Has not get the size of the file. **/ EFI_STATUS PxeBcTftpGetFileSize ( IN PXEBC_PRIVATE_DATA *Private, IN EFI_MTFTP4_CONFIG_DATA *Config, IN UINT8 *Filename, IN UINTN *BlockSize, IN OUT UINT64 *BufferSize ) { EFI_MTFTP4_PROTOCOL *Mtftp4; EFI_MTFTP4_OPTION ReqOpt[2]; EFI_MTFTP4_PACKET *Packet; EFI_MTFTP4_OPTION *Option; UINT32 PktLen; UINT8 OptBuf[128]; UINT32 OptCnt; EFI_STATUS Status; *BufferSize = 0; Status = EFI_DEVICE_ERROR; Mtftp4 = Private->Mtftp4; Packet = NULL; Option = NULL; PktLen = 0; OptCnt = 1; Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; Status = Mtftp4->Configure (Mtftp4, Config); if (EFI_ERROR (Status)) { return Status; } ReqOpt[0].OptionStr = (UINT8*)mMtftpOptions[PXE_MTFTP_OPTION_TSIZE_INDEX]; UtoA10 (0, (CHAR8 *) OptBuf); ReqOpt[0].ValueStr = OptBuf; if (BlockSize != NULL) { ReqOpt[1].OptionStr = (UINT8*)mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; ReqOpt[1].ValueStr = ReqOpt[0].ValueStr + AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1; UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[1].ValueStr); OptCnt++; } Status = Mtftp4->GetInfo ( Mtftp4, FALSE, Filename, NULL, (UINT8) OptCnt, ReqOpt, &PktLen, &Packet ); if (EFI_ERROR (Status)) { if (Status == EFI_TFTP_ERROR) { Private->Mode.TftpErrorReceived = TRUE; Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode; AsciiStrnCpy ( Private->Mode.TftpError.ErrorString, (CHAR8 *) Packet->Error.ErrorMessage, 127 ); } goto ON_ERROR; } OptCnt = 0; Status = Mtftp4->ParseOptions ( Mtftp4, PktLen, Packet, (UINT32 *) &OptCnt, &Option ); if (EFI_ERROR (Status)) { goto ON_ERROR; } Status = EFI_NOT_FOUND; while (OptCnt != 0) { if (AsciiStrnCmp ((CHAR8 *) Option[OptCnt - 1].OptionStr, "tsize", 5) == 0) { *BufferSize = AtoU64 (Option[OptCnt - 1].ValueStr); Status = EFI_SUCCESS; } OptCnt--; } FreePool (Option); ON_ERROR: if (Packet != NULL) { FreePool (Packet); } Mtftp4->Configure (Mtftp4, NULL); return Status; }
/** Performance measure function to get S3 detailed performance data. This function will getS3 detailed performance data and saved in pre-reserved ACPI memory. **/ VOID WriteToOsS3PerformanceData ( VOID ) { EFI_STATUS Status; EFI_PHYSICAL_ADDRESS mAcpiLowMemoryBase; PERF_HEADER *PerfHeader; PERF_DATA *PerfData; UINT64 Ticker; UINTN Index; EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices; UINTN VarSize; UINTN LogEntryKey; CONST VOID *Handle; CONST CHAR8 *Token; CONST CHAR8 *Module; UINT64 StartTicker; UINT64 EndTicker; UINT64 StartValue; UINT64 EndValue; BOOLEAN CountUp; UINT64 Freq; // // Retrive time stamp count as early as possilbe // Ticker = GetPerformanceCounter (); Freq = GetPerformanceCounterProperties (&StartValue, &EndValue); Freq = DivU64x32 (Freq, 1000); Status = PeiServicesLocatePpi ( &gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **) &VariableServices ); ASSERT_EFI_ERROR (Status); VarSize = sizeof (EFI_PHYSICAL_ADDRESS); Status = VariableServices->GetVariable ( VariableServices, L"PerfDataMemAddr", &gPerformanceProtocolGuid, NULL, &VarSize, &mAcpiLowMemoryBase ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Fail to retrieve variable to log S3 performance data \n")); return; } PerfHeader = (PERF_HEADER *) (UINTN) mAcpiLowMemoryBase; if (PerfHeader->Signiture != PERFORMANCE_SIGNATURE) { DEBUG ((EFI_D_ERROR, "Performance data in ACPI memory get corrupted! \n")); return; } // // Record total S3 resume time. // if (EndValue >= StartValue) { PerfHeader->S3Resume = Ticker - StartValue; CountUp = TRUE; } else { PerfHeader->S3Resume = StartValue - Ticker; CountUp = FALSE; } // // Get S3 detailed performance data // Index = 0; LogEntryKey = 0; while ((LogEntryKey = GetPerformanceMeasurement ( LogEntryKey, &Handle, &Token, &Module, &StartTicker, &EndTicker)) != 0) { if (EndTicker != 0) { PerfData = &PerfHeader->S3Entry[Index]; // // Use File Handle to specify the different performance log for PEIM. // File Handle is the base address of PEIM FFS file. // if ((AsciiStrnCmp (Token, "PEIM", PEI_PERFORMANCE_STRING_SIZE) == 0) && (Handle != NULL)) { AsciiSPrint (PerfData->Token, PERF_TOKEN_LENGTH, "0x%11p", Handle); } else { AsciiStrnCpy (PerfData->Token, Token, PERF_TOKEN_LENGTH); } if (StartTicker == 1) { StartTicker = StartValue; } if (EndTicker == 1) { EndTicker = StartValue; } Ticker = CountUp? (EndTicker - StartTicker) : (StartTicker - EndTicker); PerfData->Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq); // // Only Record > 1ms performance data so that more big performance can be recorded. // if ((Ticker > Freq) && (++Index >= PERF_PEI_ENTRY_MAX_NUM)) { // // Reach the maximum number of PEI performance log entries. // break; } } } PerfHeader->S3EntryNum = (UINT32) Index; }
EFI_STATUS XMLParseNextTag(CHAR8* buffer, TagPtr * tag, UINT32* lenPtr) { EFI_STATUS Status; UINT32 length=0; UINT32 pos=0; CHAR8* tagName=NULL; *lenPtr=0; Status = GetNextTag((UINT8*)buffer, &tagName, 0, &length); if (EFI_ERROR(Status)) return Status; pos = length; if (!AsciiStrnCmp(tagName, kXMLTagPList, 6)) { length=0; Status=EFI_SUCCESS; } /***** dict ****/ else if (!AsciiStrCmp(tagName, kXMLTagDict)) { Status = ParseTagList(buffer + pos, tag, kTagTypeDict, 0, &length); } else if (!AsciiStrCmp(tagName, kXMLTagDict "/")) { Status = ParseTagList(buffer + pos, tag, kTagTypeDict, 1, &length); } else if (!AsciiStrCmp(tagName, kXMLTagDict " ")) { Status = ParseTagList(buffer + pos, tag, kTagTypeDict, 0, &length); } /***** key ****/ else if (!AsciiStrCmp(tagName, kXMLTagKey)) { Status = ParseTagKey(buffer + pos, tag,&length); } /***** string ****/ else if (!AsciiStrCmp(tagName, kXMLTagString)) { Status = ParseTagString(buffer + pos, tag, &length); } /***** integer ****/ else if (!AsciiStrCmp(tagName, kXMLTagInteger)) { Status = ParseTagInteger(buffer + pos, tag, &length); } else if (!AsciiStrCmp(tagName, kXMLTagInteger " ")) { Status = ParseTagInteger(buffer + pos, tag, &length); } /***** data ****/ else if (!AsciiStrCmp(tagName, kXMLTagData)) { Status = ParseTagData(buffer + pos, tag,&length); } else if (!AsciiStrCmp(tagName, kXMLTagData " ")) { Status = ParseTagData(buffer + pos, tag, &length); } /***** date ****/ else if (!AsciiStrCmp(tagName, kXMLTagDate)) { Status = ParseTagDate(buffer + pos, tag, &length); } /***** FALSE ****/ else if (!AsciiStrCmp(tagName, kXMLTagFalse)) { Status = ParseTagBoolean(buffer + pos, tag, kTagTypeFalse, &length); } /***** TRUE ****/ else if (!AsciiStrCmp(tagName, kXMLTagTrue)) { Status = ParseTagBoolean(buffer + pos, tag, kTagTypeTrue, &length); } /***** array ****/ else if (!AsciiStrCmp(tagName, kXMLTagArray)) { Status = ParseTagList(buffer + pos, tag, kTagTypeArray, 0, &length); } else if (!AsciiStrCmp(tagName, kXMLTagArray " ")) { Status = ParseTagList(buffer + pos, tag, kTagTypeArray, 0, &length); } else if (!AsciiStrCmp(tagName, kXMLTagArray "/")) { Status = ParseTagList(buffer + pos, tag, kTagTypeArray, 1, &length); } /***** unknown ****/ else { *tag = NULL; length = 0; } if (EFI_ERROR(Status)) return EFI_UNSUPPORTED; *lenPtr=pos + length; return EFI_SUCCESS; }