// // Returns parsed hex integer key. // Plist - kext pist // Key - key to find // WholePlist - _PrelinkInfoDictionary, used to find referenced values // // Searches for Key in Plist and it's value: // a) <integer ID="26" size="64">0x2b000</integer> // returns 0x2b000 // b) <integer IDREF="26"/> // searches for <integer ID="26"... from WholePlist // and returns value from that referenced field // // Whole function is here since we should avoid ParseXML() and it's // memory allocations during ExitBootServices(). And it seems that // ParseXML() does not support IDREF. // This func is hard to read and debug and probably not reliable, // but it seems it works. // UINT64 GetPlistHexValue ( CHAR8 *Plist, CHAR8 *Key, CHAR8 *WholePlist ) { CHAR8 *Value; CHAR8 *IntTag; UINT64 NumValue; CHAR8 *IDStart; CHAR8 *IDEnd; UINTN IDLen; CHAR8 Buffer[48]; NumValue = 0; // search for Key Value = AsciiStrStr (Plist, Key); if (Value == NULL) { return 0; } // search for <integer IntTag = AsciiStrStr (Value, "<integer"); if (IntTag == NULL) { return 0; } // find <integer end Value = AsciiStrStr (IntTag, ">"); if (Value == NULL) { return 0; } // normal case: value is here if (Value[-1] != '/') { NumValue = AsciiStrHexToUint64 (Value + 1); return NumValue; } // it might be a reference: IDREF="173"/> Value = AsciiStrStr (IntTag, "<integer IDREF=\""); if (Value != IntTag) { return 0; } // compose <integer ID="xxx" in the Buffer IDStart = AsciiStrStr (IntTag, "\"") + 1; IDEnd = AsciiStrStr (IDStart, "\""); IDLen = IDEnd - IDStart; if (IDLen > 8) { return 0; } AsciiStrCpy (Buffer, "<integer ID=\""); AsciiStrnCat (Buffer, IDStart, IDLen); AsciiStrCat (Buffer, "\""); // and search whole plist for ID IntTag = AsciiStrStr (WholePlist, Buffer); if (IntTag == NULL) { return 0; } // got it. find closing > Value = AsciiStrStr (IntTag, ">"); if (Value == NULL) { return 0; } if (Value[-1] == '/') { return 0; } // we should have value now NumValue = AsciiStrHexToUint64 (Value + 1); return NumValue; }
/** Check every return package for update PRT @param AcpiSdt Pointer to Acpi SDT protocol @param ParentHandle ACPI pci device handle @param PciDeviceInfo Pointer to PCI_DEVICE_INFO **/ VOID SdtCheckReturnPackage ( IN EFI_ACPI_SDT_PROTOCOL *AcpiSdt, IN EFI_ACPI_HANDLE MethodHandle, IN PCI_DEVICE_INFO *PciDeviceInfo ) { EFI_ACPI_HANDLE PreviousHandle; EFI_ACPI_HANDLE ReturnHandle; EFI_ACPI_HANDLE PackageHandle; EFI_ACPI_HANDLE NamePkgHandle; EFI_STATUS Status; EFI_ACPI_DATA_TYPE DataType; UINT8 *Data; UINTN DataSize; CHAR8 NameStr[128]; ReturnHandle = NULL; while (TRUE) { PreviousHandle = ReturnHandle; Status = AcpiSdt->GetChild (MethodHandle, &ReturnHandle); ASSERT_EFI_ERROR (Status); if (PreviousHandle != NULL) { Status = AcpiSdt->Close (PreviousHandle); ASSERT_EFI_ERROR (Status); } if (ReturnHandle == NULL) { break; } Status = AcpiSdt->GetOption (ReturnHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize); ASSERT_EFI_ERROR (Status); ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE); if (*Data == AML_RETURN_OP) { // // Find the return method handle, then look for the returned package data // Status = AcpiSdt->GetOption (ReturnHandle, 1, &DataType, (CONST VOID **)&Data, &DataSize); ASSERT_EFI_ERROR (Status); if (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING) { ZeroMem (NameStr, 128); AsciiStrCpy (NameStr, "\\_SB."); DataSize = SdtGetNameStringSize (Data); AsciiStrnCat (NameStr, (CHAR8 *)Data, DataSize); NamePkgHandle = NULL; Status = AcpiSdt->FindPath (mDsdtHandle, NameStr, &NamePkgHandle); ASSERT_EFI_ERROR (Status); ASSERT (NamePkgHandle != NULL); Status = AcpiSdt->GetOption (NamePkgHandle, 0, &DataType, (CONST VOID **)&Data, &DataSize); ASSERT_EFI_ERROR (Status); ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE); ASSERT (*Data == AML_NAME_OP); Status = AcpiSdt->GetOption (NamePkgHandle, 2, &DataType, (CONST VOID **)&Data, &DataSize); ASSERT_EFI_ERROR (Status); ASSERT (DataType == EFI_ACPI_DATA_TYPE_CHILD); } ASSERT (DataType == EFI_ACPI_DATA_TYPE_CHILD); // // Get the parent package handle // PackageHandle = NULL; Status = AcpiSdt->Open (Data, &PackageHandle); ASSERT_EFI_ERROR (Status); // // Check the parent package for update pci routing // SdtCheckParentPackage (AcpiSdt, PackageHandle, PciDeviceInfo); Status = AcpiSdt->Close (PackageHandle); ASSERT_EFI_ERROR (Status); Status = AcpiSdt->Close (ReturnHandle); ASSERT_EFI_ERROR (Status); break; } // // Not ReturnOp, search it as parent // SdtCheckReturnPackage (AcpiSdt, ReturnHandle, PciDeviceInfo); } // // Done // return; }