/// <summary> /// parse a acpi method arguments /// </summary> /// <param name="pkg">data package</param> /// <param name="PkgByte">raw data</param> private void AcpiMethodArg(AcpiPackage pkg, byte[] PkgByte) { int Offset = 0; int Length = PkgByte.Length; AcpiPackage val = null; // handle the pkg while (Offset < Length) { UInt16 Type = BitConverter.ToUInt16(PkgByte, Offset); Offset += 2; UInt16 DataLength = BitConverter.ToUInt16(PkgByte, Offset); if (DataLength < 4) { /* * from acpiioct.h, at least 4 bytes for union type combined with ULONG and UCHAR * typedef struct _ACPI_METHOD_ARGUMENT_V1 { * USHORT Type; * USHORT DataLength; * union { * ULONG Argument; * _Field_size_bytes_(DataLength) * UCHAR Data[ANYSIZE_ARRAY]; * } DUMMYUNIONNAME; * } ACPI_METHOD_ARGUMENT_V1; */ DataLength = 4; } Offset += 2; // handle package switch (Type) { case 0: if (Length < 8) { val = new AcpiPackage( (UInt64)BitConverter.ToUInt32(PkgByte, Offset)); } else { val = new AcpiPackage( BitConverter.ToUInt64(PkgByte, Offset)); } pkg.pkgs.Add(val); break; case 1: val = new AcpiPackage(BitConverter.ToString(PkgByte, Offset, DataLength)); pkg.pkgs.Add(val); break; case 2: byte[] bufferData = new byte[DataLength]; Array.Copy(PkgByte, Offset, bufferData, 0, DataLength); val = new AcpiPackage(bufferData); pkg.pkgs.Add(val); break; case 3: case 4: byte[] packageData = new byte[DataLength]; Array.Copy(PkgByte, Offset, packageData, 0, DataLength); val = new AcpiPackage(); val.Type = AcpiDataType.Packge; pkg.pkgs.Add(val); AcpiMethodArg(val, packageData); break; } Offset += DataLength; //ACPI_METHOD_NEXT_ARGUMENT } }
/// <summary> /// set new value of acpi data with same type /// </summary> /// <param name="acpiData"></param> public void SetValue(AcpiData acpiData) { if (this.Type == AcpiDataType.FieldUnit) { // TODO: Write the field ojbect... this.Value = acpiData.Value; } else { // Local Data can be assigned to any type, if not the type must be mathcing if (this.Name != null) { if (this.Name.StartsWith("InternalLocalData") || this.Name.StartsWith("InternalMethodArg")) { this.Type = acpiData.Type; } } // Int To Int // String to string // String to Buffer // Buffer to String // Package to Buffer // Buffer to Package if (this.Type == acpiData.Type) { this.Value = acpiData.Value; if (acpiData.strValue != null) { this.strValue = new string(acpiData.strValue.ToArray()); } if (acpiData.bpValue != null) { this.bpValue = new byte[acpiData.bpValue.Length]; Array.Copy(acpiData.bpValue, 0, this.bpValue, 0, acpiData.bpValue.Length); } this.Pkg = acpiData.Pkg; } else if (this.Type == AcpiDataType.String && acpiData.Type == AcpiDataType.Buffer) { // Buffer to string this.strValue = BitConverter.ToString(acpiData.bpValue); } else if ((this.Type == AcpiDataType.Packge && acpiData.Type == AcpiDataType.Buffer) || acpiData.Type == AcpiDataType.Packge && this.Type == AcpiDataType.Buffer) { // Buffer to Package // or package to buffer this.bpValue = new byte[acpiData.bpValue.Length]; Array.Copy(acpiData.bpValue, 0, this.bpValue, 0, acpiData.bpValue.Length); } else if (acpiData.Type == AcpiDataType.String && this.Type == AcpiDataType.Buffer) { // string to buffer //this.bpValue = new byte[acpiData.strValue.Length]; this.bpValue = ASCIIEncoding.ASCII.GetBytes(acpiData.strValue); } else { //System.Diagnostics.Debug.Assert(false, "Wrong ACPI Data Type Assignment" + this.ToString() + acpiData.ToString()); Log.Logs("Wrong ACPI Data Type Assignment" + this.ToString() + acpiData.ToString()); } } }
/// <summary> /// get acpi data from a acpi output of acpilib /// </summary> /// <param name="intPtr"></param> /// <returns></returns> public Boolean FromAcpiOutput(IntPtr intPtr) { UInt32 val = (UInt32)Marshal.ReadInt32(intPtr); if (val != 0x426F6541) { return(false); } // // Check the data length.. // int Length = Marshal.ReadInt32(intPtr + 0x4); int Count = Marshal.ReadInt32(intPtr + 0x8); // 0xC is type and Element Data Length; //DbgMessage("acpi output arg count " + Count.ToString()); short Type = Marshal.ReadInt16(intPtr + 0xC); if (Count > 1) { Type = 3; // count is more than 1, it's a package } if (Count > 0) { // get the type of data short DataLength = Marshal.ReadInt16(intPtr + 0xE); switch (Type) { case 0: this.Value = (UInt64)Marshal.ReadInt64(intPtr + 0x10); this.Type = AcpiDataType.Int; break; case 1: this.Type = AcpiDataType.String; this.strValue = Marshal.PtrToStringAnsi(intPtr + 0x10); break; case 2: this.Type = AcpiDataType.Buffer; bpValue = new byte[DataLength]; Marshal.Copy(intPtr + 0x10, bpValue, 0, DataLength); break; case 3: this.Type = AcpiDataType.Packge; bpValue = new byte[Length]; Marshal.Copy(intPtr, bpValue, 0, Length); if (ValidAcpiOutput()) { Pkg = new AcpiPackage(); UInt32 pkgLength = BitConverter.ToUInt32(bpValue, 4); byte[] pkgData = new byte[pkgLength - 12]; Array.Copy(bpValue, 12, pkgData, 0, pkgLength - 12); AcpiMethodArg(Pkg, pkgData); } break; case 4: this.Type = AcpiDataType.Packge; DbgMessage("PACKAGE EX TYPE"); bpValue = new byte[Length]; Marshal.Copy(intPtr, bpValue, 0, Length); if (ValidAcpiOutput()) { Pkg = new AcpiPackage(); UInt32 pkgLength = BitConverter.ToUInt32(bpValue, 4); byte[] pkgData = new byte[pkgLength - 12]; Array.Copy(bpValue, 12, pkgData, 0, pkgLength - 12); AcpiMethodArg(Pkg, pkgData); } break; default: DbgMessage("Not a valid data type"); break; } } return(true); }