static ACPI_STATUS AcpiExConvertToObjectTypeString ( ACPI_OPERAND_OBJECT *ObjDesc, ACPI_OPERAND_OBJECT **ResultDesc) { ACPI_OPERAND_OBJECT *ReturnDesc; const char *TypeString; TypeString = AcpiUtGetTypeName (ObjDesc->Common.Type); ReturnDesc = AcpiUtCreateStringObject ( ((ACPI_SIZE) strlen (TypeString) + 9)); /* 9 For "[ Object]" */ if (!ReturnDesc) { return (AE_NO_MEMORY); } strcpy (ReturnDesc->String.Pointer, "["); strcat (ReturnDesc->String.Pointer, TypeString); strcat (ReturnDesc->String.Pointer, " Object]"); *ResultDesc = ReturnDesc; return (AE_OK); }
ACPI_STATUS AcpiExConvertToString ( ACPI_OPERAND_OBJECT *ObjDesc, ACPI_OPERAND_OBJECT **ResultDesc, UINT32 Type) { ACPI_OPERAND_OBJECT *ReturnDesc; UINT8 *NewBuf; UINT32 i; UINT32 StringLength = 0; UINT16 Base = 16; UINT8 Separator = ','; ACPI_FUNCTION_TRACE_PTR (ExConvertToString, ObjDesc); switch (ObjDesc->Common.Type) { case ACPI_TYPE_STRING: /* No conversion necessary */ *ResultDesc = ObjDesc; return_ACPI_STATUS (AE_OK); case ACPI_TYPE_INTEGER: switch (Type) { case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Make room for maximum decimal number */ StringLength = ACPI_MAX_DECIMAL_DIGITS; Base = 10; break; default: /* Two hex string characters for each integer byte */ StringLength = ACPI_MUL_2 (AcpiGbl_IntegerByteWidth); break; } /* * Create a new String * Need enough space for one ASCII integer (plus null terminator) */ ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) StringLength); if (!ReturnDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } NewBuf = ReturnDesc->Buffer.Pointer; /* Convert integer to string */ StringLength = AcpiExConvertToAscii (ObjDesc->Integer.Value, Base, NewBuf, AcpiGbl_IntegerByteWidth); /* Null terminate at the correct place */ ReturnDesc->String.Length = StringLength; NewBuf [StringLength] = 0; break; case ACPI_TYPE_BUFFER: /* Setup string length, base, and separator */ switch (Type) { case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by ToDecimalString */ /* * From ACPI: "If Data is a buffer, it is converted to a string of * decimal values separated by commas." */ Base = 10; /* * Calculate the final string length. Individual string values * are variable length (include separator for each) */ for (i = 0; i < ObjDesc->Buffer.Length; i++) { if (ObjDesc->Buffer.Pointer[i] >= 100) { StringLength += 4; } else if (ObjDesc->Buffer.Pointer[i] >= 10) { StringLength += 3; } else { StringLength += 2; } } break; case ACPI_IMPLICIT_CONVERT_HEX: /* * From the ACPI spec: *"The entire contents of the buffer are converted to a string of * two-character hexadecimal numbers, each separated by a space." */ Separator = ' '; StringLength = (ObjDesc->Buffer.Length * 3); break; case ACPI_EXPLICIT_CONVERT_HEX: /* Used by ToHexString */ /* * From ACPI: "If Data is a buffer, it is converted to a string of * hexadecimal values separated by commas." */ StringLength = (ObjDesc->Buffer.Length * 3); break; default: return_ACPI_STATUS (AE_BAD_PARAMETER); } /* * Create a new string object and string buffer * (-1 because of extra separator included in StringLength from above) * Allow creation of zero-length strings from zero-length buffers. */ if (StringLength) { StringLength--; } ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) StringLength); if (!ReturnDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } NewBuf = ReturnDesc->Buffer.Pointer; /* * Convert buffer bytes to hex or decimal values * (separated by commas or spaces) */ for (i = 0; i < ObjDesc->Buffer.Length; i++) { NewBuf += AcpiExConvertToAscii ( (UINT64) ObjDesc->Buffer.Pointer[i], Base, NewBuf, 1); *NewBuf++ = Separator; /* each separated by a comma or space */ } /* * Null terminate the string * (overwrites final comma/space from above) */ if (ObjDesc->Buffer.Length) { NewBuf--; } *NewBuf = 0; break; default: return_ACPI_STATUS (AE_TYPE); } *ResultDesc = ReturnDesc; return_ACPI_STATUS (AE_OK); }
static ACPI_STATUS AcpiNsRepair_HID ( ACPI_EVALUATE_INFO *Info, ACPI_OPERAND_OBJECT **ReturnObjectPtr) { ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; ACPI_OPERAND_OBJECT *NewString; char *Source; char *Dest; ACPI_FUNCTION_NAME (NsRepair_HID); /* We only care about string _HID objects (not integers) */ if (ReturnObject->Common.Type != ACPI_TYPE_STRING) { return (AE_OK); } if (ReturnObject->String.Length == 0) { ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, "Invalid zero-length _HID or _CID string")); /* Return AE_OK anyway, let driver handle it */ Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; return (AE_OK); } /* It is simplest to always create a new string object */ NewString = AcpiUtCreateStringObject (ReturnObject->String.Length); if (!NewString) { return (AE_NO_MEMORY); } /* * Remove a leading asterisk if present. For some unknown reason, there * are many machines in the field that contains IDs like this. * * Examples: "*PNP0C03", "*ACPI0003" */ Source = ReturnObject->String.Pointer; if (*Source == '*') { Source++; NewString->String.Length--; ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, "%s: Removed invalid leading asterisk\n", Info->FullPathname)); } /* * Copy and uppercase the string. From the ACPI 5.0 specification: * * A valid PNP ID must be of the form "AAA####" where A is an uppercase * letter and # is a hex digit. A valid ACPI ID must be of the form * "NNNN####" where N is an uppercase letter or decimal digit, and * # is a hex digit. */ for (Dest = NewString->String.Pointer; *Source; Dest++, Source++) { *Dest = (char) toupper ((int) *Source); } AcpiUtRemoveReference (ReturnObject); *ReturnObjectPtr = NewString; return (AE_OK); }
ACPI_STATUS AcpiExDoConcatenate ( ACPI_OPERAND_OBJECT *Operand0, ACPI_OPERAND_OBJECT *Operand1, ACPI_OPERAND_OBJECT **ActualReturnDesc, ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT *LocalOperand0 = Operand0; ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1; ACPI_OPERAND_OBJECT *TempOperand1 = NULL; ACPI_OPERAND_OBJECT *ReturnDesc; char *Buffer; ACPI_OBJECT_TYPE Operand0Type; ACPI_OBJECT_TYPE Operand1Type; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (ExDoConcatenate); /* Operand 0 preprocessing */ switch (Operand0->Common.Type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: Operand0Type = Operand0->Common.Type; break; default: /* For all other types, get the "object type" string */ Status = AcpiExConvertToObjectTypeString ( Operand0, &LocalOperand0); if (ACPI_FAILURE (Status)) { goto Cleanup; } Operand0Type = ACPI_TYPE_STRING; break; } /* Operand 1 preprocessing */ switch (Operand1->Common.Type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: Operand1Type = Operand1->Common.Type; break; default: /* For all other types, get the "object type" string */ Status = AcpiExConvertToObjectTypeString ( Operand1, &LocalOperand1); if (ACPI_FAILURE (Status)) { goto Cleanup; } Operand1Type = ACPI_TYPE_STRING; break; } /* * Convert the second operand if necessary. The first operand (0) * determines the type of the second operand (1) (See the Data Types * section of the ACPI specification). Both object types are * guaranteed to be either Integer/String/Buffer by the operand * resolution mechanism. */ switch (Operand0Type) { case ACPI_TYPE_INTEGER: Status = AcpiExConvertToInteger (LocalOperand1, &TempOperand1, ACPI_STRTOUL_BASE16); break; case ACPI_TYPE_BUFFER: Status = AcpiExConvertToBuffer (LocalOperand1, &TempOperand1); break; case ACPI_TYPE_STRING: switch (Operand1Type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* Other types have already been converted to string */ Status = AcpiExConvertToString ( LocalOperand1, &TempOperand1, ACPI_IMPLICIT_CONVERT_HEX); break; default: Status = AE_OK; break; } break; default: ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X", Operand0->Common.Type)); Status = AE_AML_INTERNAL; } if (ACPI_FAILURE (Status)) { goto Cleanup; } /* Take care with any newly created operand objects */ if ((LocalOperand1 != Operand1) && (LocalOperand1 != TempOperand1)) { AcpiUtRemoveReference (LocalOperand1); } LocalOperand1 = TempOperand1; /* * Both operands are now known to be the same object type * (Both are Integer, String, or Buffer), and we can now perform * the concatenation. * * There are three cases to handle, as per the ACPI spec: * * 1) Two Integers concatenated to produce a new Buffer * 2) Two Strings concatenated to produce a new String * 3) Two Buffers concatenated to produce a new Buffer */ switch (Operand0Type) { case ACPI_TYPE_INTEGER: /* Result of two Integers is a Buffer */ /* Need enough buffer space for two integers */ ReturnDesc = AcpiUtCreateBufferObject ( (ACPI_SIZE) ACPI_MUL_2 (AcpiGbl_IntegerByteWidth)); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } Buffer = (char *) ReturnDesc->Buffer.Pointer; /* Copy the first integer, LSB first */ memcpy (Buffer, &Operand0->Integer.Value, AcpiGbl_IntegerByteWidth); /* Copy the second integer (LSB first) after the first */ memcpy (Buffer + AcpiGbl_IntegerByteWidth, &LocalOperand1->Integer.Value, AcpiGbl_IntegerByteWidth); break; case ACPI_TYPE_STRING: /* Result of two Strings is a String */ ReturnDesc = AcpiUtCreateStringObject ( ((ACPI_SIZE) LocalOperand0->String.Length + LocalOperand1->String.Length)); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } Buffer = ReturnDesc->String.Pointer; /* Concatenate the strings */ strcpy (Buffer, LocalOperand0->String.Pointer); strcat (Buffer, LocalOperand1->String.Pointer); break; case ACPI_TYPE_BUFFER: /* Result of two Buffers is a Buffer */ ReturnDesc = AcpiUtCreateBufferObject ( ((ACPI_SIZE) Operand0->Buffer.Length + LocalOperand1->Buffer.Length)); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } Buffer = (char *) ReturnDesc->Buffer.Pointer; /* Concatenate the buffers */ memcpy (Buffer, Operand0->Buffer.Pointer, Operand0->Buffer.Length); memcpy (Buffer + Operand0->Buffer.Length, LocalOperand1->Buffer.Pointer, LocalOperand1->Buffer.Length); break; default: /* Invalid object type, should not happen here */ ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X", Operand0->Common.Type)); Status = AE_AML_INTERNAL; goto Cleanup; } *ActualReturnDesc = ReturnDesc; Cleanup: if (LocalOperand0 != Operand0) { AcpiUtRemoveReference (LocalOperand0); } if (LocalOperand1 != Operand1) { AcpiUtRemoveReference (LocalOperand1); } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExOpcode_2A_1T_1R ( ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; ACPI_OPERAND_OBJECT *ReturnDesc = NULL; UINT64 Index; ACPI_STATUS Status = AE_OK; ACPI_SIZE Length = 0; ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_1T_1R, AcpiPsGetOpcodeName (WalkState->Opcode)); /* Execute the opcode */ if (WalkState->OpInfo->Flags & AML_MATH) { /* All simple math opcodes (add, etc.) */ ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } ReturnDesc->Integer.Value = AcpiExDoMathOp (WalkState->Opcode, Operand[0]->Integer.Value, Operand[1]->Integer.Value); goto StoreResultToTarget; } switch (WalkState->Opcode) { case AML_MOD_OP: /* Mod (Dividend, Divisor, RemainderResult (ACPI 2.0) */ ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } /* ReturnDesc will contain the remainder */ Status = AcpiUtDivide (Operand[0]->Integer.Value, Operand[1]->Integer.Value, NULL, &ReturnDesc->Integer.Value); break; case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */ Status = AcpiExDoConcatenate (Operand[0], Operand[1], &ReturnDesc, WalkState); break; case AML_TO_STRING_OP: /* ToString (Buffer, Length, Result) (ACPI 2.0) */ /* * Input object is guaranteed to be a buffer at this point (it may have * been converted.) Copy the raw buffer data to a new object of * type String. */ /* * Get the length of the new string. It is the smallest of: * 1) Length of the input buffer * 2) Max length as specified in the ToString operator * 3) Length of input buffer up to a zero byte (null terminator) * * NOTE: A length of zero is ok, and will create a zero-length, null * terminated string. */ while ((Length < Operand[0]->Buffer.Length) && (Length < Operand[1]->Integer.Value) && (Operand[0]->Buffer.Pointer[Length])) { Length++; } /* Allocate a new string object */ ReturnDesc = AcpiUtCreateStringObject (Length); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } /* * Copy the raw buffer data with no transform. * (NULL terminated already) */ ACPI_MEMCPY (ReturnDesc->String.Pointer, Operand[0]->Buffer.Pointer, Length); break; case AML_CONCAT_RES_OP: /* ConcatenateResTemplate (Buffer, Buffer, Result) (ACPI 2.0) */ Status = AcpiExConcatTemplate (Operand[0], Operand[1], &ReturnDesc, WalkState); break; case AML_INDEX_OP: /* Index (Source Index Result) */ /* Create the internal return object */ ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } /* Initialize the Index reference object */ Index = Operand[1]->Integer.Value; ReturnDesc->Reference.Value = (UINT32) Index; ReturnDesc->Reference.Class = ACPI_REFCLASS_INDEX; /* * At this point, the Source operand is a String, Buffer, or Package. * Verify that the index is within range. */ switch ((Operand[0])->Common.Type) { case ACPI_TYPE_STRING: if (Index >= Operand[0]->String.Length) { Length = Operand[0]->String.Length; Status = AE_AML_STRING_LIMIT; } ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD; break; case ACPI_TYPE_BUFFER: if (Index >= Operand[0]->Buffer.Length) { Length = Operand[0]->Buffer.Length; Status = AE_AML_BUFFER_LIMIT; } ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD; break; case ACPI_TYPE_PACKAGE: if (Index >= Operand[0]->Package.Count) { Length = Operand[0]->Package.Count; Status = AE_AML_PACKAGE_LIMIT; } ReturnDesc->Reference.TargetType = ACPI_TYPE_PACKAGE; ReturnDesc->Reference.Where = &Operand[0]->Package.Elements [Index]; break; default: Status = AE_AML_INTERNAL; goto Cleanup; } /* Failure means that the Index was beyond the end of the object */ if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "Index (0x%X%8.8X) is beyond end of object (length 0x%X)", ACPI_FORMAT_UINT64 (Index), (UINT32) Length)); goto Cleanup; } /* * Save the target object and add a reference to it for the life * of the index */ ReturnDesc->Reference.Object = Operand[0]; AcpiUtAddReference (Operand[0]); /* Store the reference to the Target */ Status = AcpiExStore (ReturnDesc, Operand[2], WalkState); /* Return the reference */ WalkState->ResultObj = ReturnDesc; goto Cleanup; default: ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", WalkState->Opcode)); Status = AE_AML_BAD_OPCODE; break; } StoreResultToTarget: if (ACPI_SUCCESS (Status)) { /* * Store the result of the operation (which is now in ReturnDesc) into * the Target descriptor. */ Status = AcpiExStore (ReturnDesc, Operand[2], WalkState); if (ACPI_FAILURE (Status)) { goto Cleanup; } if (!WalkState->ResultObj) { WalkState->ResultObj = ReturnDesc; } } Cleanup: /* Delete return object on error */ if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ReturnDesc); WalkState->ResultObj = NULL; } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiNsConvertToString ( ACPI_OPERAND_OBJECT *OriginalObject, ACPI_OPERAND_OBJECT **ReturnObject) { ACPI_OPERAND_OBJECT *NewObject; ACPI_SIZE Length; ACPI_STATUS Status; switch (OriginalObject->Common.Type) { case ACPI_TYPE_INTEGER: /* * Integer-to-String conversion. Commonly, convert * an integer of value 0 to a NULL string. The last element of * _BIF and _BIX packages occasionally need this fix. */ if (OriginalObject->Integer.Value == 0) { /* Allocate a new NULL string object */ NewObject = AcpiUtCreateStringObject (0); if (!NewObject) { return (AE_NO_MEMORY); } } else { Status = AcpiExConvertToString (OriginalObject, &NewObject, ACPI_IMPLICIT_CONVERT_HEX); if (ACPI_FAILURE (Status)) { return (Status); } } break; case ACPI_TYPE_BUFFER: /* * Buffer-to-String conversion. Use a ToString * conversion, no transform performed on the buffer data. The best * example of this is the _BIF method, where the string data from * the battery is often (incorrectly) returned as buffer object(s). */ Length = 0; while ((Length < OriginalObject->Buffer.Length) && (OriginalObject->Buffer.Pointer[Length])) { Length++; } /* Allocate a new string object */ NewObject = AcpiUtCreateStringObject (Length); if (!NewObject) { return (AE_NO_MEMORY); } /* * Copy the raw buffer data with no transform. String is already NULL * terminated at Length+1. */ memcpy (NewObject->String.Pointer, OriginalObject->Buffer.Pointer, Length); break; default: return (AE_AML_OPERAND_TYPE); } *ReturnObject = NewObject; return (AE_OK); }
ACPI_STATUS AcpiExDoConcatenate ( ACPI_OPERAND_OBJECT *Operand0, ACPI_OPERAND_OBJECT *Operand1, ACPI_OPERAND_OBJECT **ActualReturnDesc, ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1; ACPI_OPERAND_OBJECT *ReturnDesc; char *NewBuf; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (ExDoConcatenate); /* * Convert the second operand if necessary. The first operand * determines the type of the second operand, (See the Data Types * section of the ACPI specification.) Both object types are * guaranteed to be either Integer/String/Buffer by the operand * resolution mechanism. */ switch (ACPI_GET_OBJECT_TYPE (Operand0)) { case ACPI_TYPE_INTEGER: Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16); break; case ACPI_TYPE_STRING: Status = AcpiExConvertToString (Operand1, &LocalOperand1, ACPI_IMPLICIT_CONVERT_HEX); break; case ACPI_TYPE_BUFFER: Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1); break; default: ACPI_ERROR ((AE_INFO, "Invalid object type: %X", ACPI_GET_OBJECT_TYPE (Operand0))); Status = AE_AML_INTERNAL; } if (ACPI_FAILURE (Status)) { goto Cleanup; } /* * Both operands are now known to be the same object type * (Both are Integer, String, or Buffer), and we can now perform the * concatenation. */ /* * There are three cases to handle: * * 1) Two Integers concatenated to produce a new Buffer * 2) Two Strings concatenated to produce a new String * 3) Two Buffers concatenated to produce a new Buffer */ switch (ACPI_GET_OBJECT_TYPE (Operand0)) { case ACPI_TYPE_INTEGER: /* Result of two Integers is a Buffer */ /* Need enough buffer space for two integers */ ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE) ACPI_MUL_2 (AcpiGbl_IntegerByteWidth)); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } NewBuf = (char *) ReturnDesc->Buffer.Pointer; /* Copy the first integer, LSB first */ ACPI_MEMCPY (NewBuf, &Operand0->Integer.Value, AcpiGbl_IntegerByteWidth); /* Copy the second integer (LSB first) after the first */ ACPI_MEMCPY (NewBuf + AcpiGbl_IntegerByteWidth, &LocalOperand1->Integer.Value, AcpiGbl_IntegerByteWidth); break; case ACPI_TYPE_STRING: /* Result of two Strings is a String */ ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) (Operand0->String.Length + LocalOperand1->String.Length)); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } NewBuf = ReturnDesc->String.Pointer; /* Concatenate the strings */ ACPI_STRCPY (NewBuf, Operand0->String.Pointer); ACPI_STRCPY (NewBuf + Operand0->String.Length, LocalOperand1->String.Pointer); break; case ACPI_TYPE_BUFFER: /* Result of two Buffers is a Buffer */ ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE) (Operand0->Buffer.Length + LocalOperand1->Buffer.Length)); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } NewBuf = (char *) ReturnDesc->Buffer.Pointer; /* Concatenate the buffers */ ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, Operand0->Buffer.Length); ACPI_MEMCPY (NewBuf + Operand0->Buffer.Length, LocalOperand1->Buffer.Pointer, LocalOperand1->Buffer.Length); break; default: /* Invalid object type, should not happen here */ ACPI_ERROR ((AE_INFO, "Invalid object type: %X", ACPI_GET_OBJECT_TYPE (Operand0))); Status =AE_AML_INTERNAL; goto Cleanup; } *ActualReturnDesc = ReturnDesc; Cleanup: if (LocalOperand1 != Operand1) { AcpiUtRemoveReference (LocalOperand1); } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiNsRepairNullElement ( ACPI_EVALUATE_INFO *Info, UINT32 ExpectedBtypes, UINT32 PackageIndex, ACPI_OPERAND_OBJECT **ReturnObjectPtr) { ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; ACPI_OPERAND_OBJECT *NewObject; ACPI_FUNCTION_NAME (NsRepairNullElement); /* No repair needed if return object is non-NULL */ if (ReturnObject) { return (AE_OK); } /* * Attempt to repair a NULL element of a Package object. This applies to * predefined names that return a fixed-length package and each element * is required. It does not apply to variable-length packages where NULL * elements are allowed, especially at the end of the package. */ if (ExpectedBtypes & ACPI_RTYPE_INTEGER) { /* Need an Integer - create a zero-value integer */ NewObject = AcpiUtCreateIntegerObject ((UINT64) 0); } else if (ExpectedBtypes & ACPI_RTYPE_STRING) { /* Need a String - create a NULL string */ NewObject = AcpiUtCreateStringObject (0); } else if (ExpectedBtypes & ACPI_RTYPE_BUFFER) { /* Need a Buffer - create a zero-length buffer */ NewObject = AcpiUtCreateBufferObject (0); } else { /* Error for all other expected types */ return (AE_AML_OPERAND_TYPE); } if (!NewObject) { return (AE_NO_MEMORY); } /* Set the reference count according to the parent Package object */ NewObject->Common.ReferenceCount = Info->ParentPackage->Common.ReferenceCount; ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, "%s: Converted NULL package element to expected %s at index %u\n", Info->FullPathname, AcpiUtGetObjectTypeName (NewObject), PackageIndex)); *ReturnObjectPtr = NewObject; Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; return (AE_OK); }
ACPI_STATUS AcpiDsCreateOperand ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Arg, UINT32 ArgIndex) { ACPI_STATUS Status = AE_OK; char *NameString; UINT32 NameLength; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_PARSE_OBJECT *ParentOp; UINT16 Opcode; ACPI_INTERPRETER_MODE InterpreterMode; const ACPI_OPCODE_INFO *OpInfo; ACPI_FUNCTION_TRACE_PTR (DsCreateOperand, Arg); /* A valid name must be looked up in the namespace */ if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && (Arg->Common.Value.String) && !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", Arg)); /* Get the entire name string from the AML stream */ Status = AcpiExGetNameString (ACPI_TYPE_ANY, Arg->Common.Value.Buffer, &NameString, &NameLength); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* All prefixes have been handled, and the name is in NameString */ /* * Special handling for BufferField declarations. This is a deferred * opcode that unfortunately defines the field name as the last * parameter instead of the first. We get here when we are performing * the deferred execution, so the actual name of the field is already * in the namespace. We don't want to attempt to look it up again * because we may be executing in a different scope than where the * actual opcode exists. */ if ((WalkState->DeferredNode) && (WalkState->DeferredNode->Type == ACPI_TYPE_BUFFER_FIELD) && (ArgIndex == (UINT32) ((WalkState->Opcode == AML_CREATE_FIELD_OP) ? 3 : 2))) { ObjDesc = ACPI_CAST_PTR ( ACPI_OPERAND_OBJECT, WalkState->DeferredNode); Status = AE_OK; } else /* All other opcodes */ { /* * Differentiate between a namespace "create" operation * versus a "lookup" operation (IMODE_LOAD_PASS2 vs. * IMODE_EXECUTE) in order to support the creation of * namespace objects during the execution of control methods. */ ParentOp = Arg->Common.Parent; OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode); if ((OpInfo->Flags & AML_NSNODE) && (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) && (ParentOp->Common.AmlOpcode != AML_REGION_OP) && (ParentOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)) { /* Enter name into namespace if not found */ InterpreterMode = ACPI_IMODE_LOAD_PASS2; } else { /* Return a failure if name not found */ InterpreterMode = ACPI_IMODE_EXECUTE; } Status = AcpiNsLookup (WalkState->ScopeInfo, NameString, ACPI_TYPE_ANY, InterpreterMode, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, WalkState, ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc)); /* * The only case where we pass through (ignore) a NOT_FOUND * error is for the CondRefOf opcode. */ if (Status == AE_NOT_FOUND) { if (ParentOp->Common.AmlOpcode == AML_COND_REF_OF_OP) { /* * For the Conditional Reference op, it's OK if * the name is not found; We just need a way to * indicate this to the interpreter, set the * object to the root */ ObjDesc = ACPI_CAST_PTR ( ACPI_OPERAND_OBJECT, AcpiGbl_RootNode); Status = AE_OK; } else if (ParentOp->Common.AmlOpcode == AML_EXTERNAL_OP) { /* TBD: May only be temporary */ ObjDesc = AcpiUtCreateStringObject ((ACPI_SIZE) NameLength); strncpy (ObjDesc->String.Pointer, NameString, NameLength); Status = AE_OK; } else { /* * We just plain didn't find it -- which is a * very serious error at this point */ Status = AE_AML_NAME_NOT_FOUND; } } if (ACPI_FAILURE (Status)) { ACPI_ERROR_NAMESPACE (NameString, Status); } } /* Free the namestring created above */ ACPI_FREE (NameString); /* Check status from the lookup */ if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Put the resulting object onto the current object stack */ Status = AcpiDsObjStackPush (ObjDesc, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState)); } else { /* Check for null name case */ if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) { /* * If the name is null, this means that this is an * optional result parameter that was not specified * in the original ASL. Create a Zero Constant for a * placeholder. (Store to a constant is a Noop.) */ Opcode = AML_ZERO_OP; /* Has no arguments! */ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Null namepath: Arg=%p\n", Arg)); } else { Opcode = Arg->Common.AmlOpcode; } /* Get the object type of the argument */ OpInfo = AcpiPsGetOpcodeInfo (Opcode); if (OpInfo->ObjectType == ACPI_TYPE_INVALID) { return_ACPI_STATUS (AE_NOT_IMPLEMENTED); } if ((OpInfo->Flags & AML_HAS_RETVAL) || (Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Argument previously created, already stacked\n")); ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject ( WalkState->Operands [WalkState->NumOperands - 1], WalkState)); /* * Use value that was already previously returned * by the evaluation of this argument */ Status = AcpiDsResultPop (&ObjDesc, WalkState); if (ACPI_FAILURE (Status)) { /* * Only error is underflow, and this indicates * a missing or null operand! */ ACPI_EXCEPTION ((AE_INFO, Status, "Missing or null operand")); return_ACPI_STATUS (Status); } } else { /* Create an ACPI_INTERNAL_OBJECT for the argument */ ObjDesc = AcpiUtCreateInternalObject (OpInfo->ObjectType); if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Initialize the new object */ Status = AcpiDsInitObjectFromOp ( WalkState, Arg, Opcode, &ObjDesc); if (ACPI_FAILURE (Status)) { AcpiUtDeleteObjectDesc (ObjDesc); return_ACPI_STATUS (Status); } } /* Put the operand object on the object stack */ Status = AcpiDsObjStackPush (ObjDesc, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState)); } return_ACPI_STATUS (AE_OK); }