示例#1
0
//
// 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;
}
示例#2
0
/**
  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;

}