acpi_status acpi_tb_get_this_table ( struct acpi_pointer *address, struct acpi_table_header *header, struct acpi_table_desc *table_info) { struct acpi_table_header *full_table = NULL; u8 allocation; acpi_status status = AE_OK; ACPI_FUNCTION_TRACE ("tb_get_this_table"); /* * Flags contains the current processor mode (Virtual or Physical addressing) * The pointer_type is either Logical or Physical */ switch (address->pointer_type) { case ACPI_PHYSMODE_PHYSPTR: case ACPI_LOGMODE_LOGPTR: /* Pointer matches processor mode, copy the table to a new buffer */ full_table = ACPI_MEM_ALLOCATE (header->length); if (!full_table) { ACPI_REPORT_ERROR (("Could not allocate table memory for [%4.4s] length %X\n", header->signature, header->length)); return_ACPI_STATUS (AE_NO_MEMORY); } /* Copy the entire table (including header) to the local buffer */ ACPI_MEMCPY (full_table, address->pointer.logical, header->length); /* Save allocation type */ allocation = ACPI_MEM_ALLOCATED; break; case ACPI_LOGMODE_PHYSPTR: /* * Just map the table's physical memory * into our address space. */ status = acpi_os_map_memory (address->pointer.physical, (acpi_size) header->length, (void *) &full_table); if (ACPI_FAILURE (status)) { ACPI_REPORT_ERROR (("Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X\n", header->signature, ACPI_FORMAT_UINT64 (address->pointer.physical), header->length)); return (status); } /* Save allocation type */ allocation = ACPI_MEM_MAPPED; break; default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid address flags %X\n", address->pointer_type)); return_ACPI_STATUS (AE_BAD_PARAMETER); } /* * Validate checksum for _most_ tables, * even the ones whose signature we don't recognize */ if (table_info->type != ACPI_TABLE_FACS) { status = acpi_tb_verify_table_checksum (full_table); #if (!ACPI_CHECKSUM_ABORT) if (ACPI_FAILURE (status)) { /* Ignore the error if configuration says so */ status = AE_OK; } #endif } /* Return values */ table_info->pointer = full_table; table_info->length = (acpi_size) header->length; table_info->allocation = allocation; ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Found table [%4.4s] at %8.8X%8.8X, mapped/copied to %p\n", full_table->signature, ACPI_FORMAT_UINT64 (address->pointer.physical), full_table)); return_ACPI_STATUS (status); }
/******************************************************************************* * * FUNCTION: acpi_ex_store_buffer_to_buffer * * PARAMETERS: source_desc - Source object to copy * target_desc - Destination object of the copy * * RETURN: Status * * DESCRIPTION: Copy a buffer object to another buffer object. * ******************************************************************************/ acpi_status acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc, union acpi_operand_object *target_desc) { u32 length; u8 *buffer; ACPI_FUNCTION_TRACE_PTR("ex_store_buffer_to_buffer", source_desc); /* We know that source_desc is a buffer by now */ buffer = ACPI_CAST_PTR(u8, source_desc->buffer.pointer); length = source_desc->buffer.length; /* * If target is a buffer of length zero or is a static buffer, * allocate a new buffer of the proper length */ if ((target_desc->buffer.length == 0) || (target_desc->common.flags & AOPOBJ_STATIC_POINTER)) { target_desc->buffer.pointer = ACPI_MEM_ALLOCATE(length); if (!target_desc->buffer.pointer) { return_ACPI_STATUS(AE_NO_MEMORY); } target_desc->buffer.length = length; } /* Copy source buffer to target buffer */ if (length <= target_desc->buffer.length) { /* Clear existing buffer and copy in the new one */ ACPI_MEMSET(target_desc->buffer.pointer, 0, target_desc->buffer.length); ACPI_MEMCPY(target_desc->buffer.pointer, buffer, length); #ifdef ACPI_OBSOLETE_BEHAVIOR /* * NOTE: ACPI versions up to 3.0 specified that the buffer must be * truncated if the string is smaller than the buffer. However, "other" * implementations of ACPI never did this and thus became the defacto * standard. ACPi 3.0_a changes this behavior such that the buffer * is no longer truncated. */ /* * OBSOLETE BEHAVIOR: * If the original source was a string, we must truncate the buffer, * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer * copy must not truncate the original buffer. */ if (original_src_type == ACPI_TYPE_STRING) { /* Set the new length of the target */ target_desc->buffer.length = length; } #endif } else { /* Truncate the source, copy only what will fit */ ACPI_MEMCPY(target_desc->buffer.pointer, buffer, target_desc->buffer.length); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Truncating source buffer from %X to %X\n", length, target_desc->buffer.length)); } /* Copy flags */ target_desc->buffer.flags = source_desc->buffer.flags; target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER; return_ACPI_STATUS(AE_OK); }
acpi_status acpi_get_firmware_table(acpi_string signature, u32 instance, u32 flags, struct acpi_table_header **table_pointer) { acpi_status status; struct acpi_pointer address; struct acpi_table_header *header = NULL; struct acpi_table_desc *table_info = NULL; struct acpi_table_desc *rsdt_info; u32 table_count; u32 i; u32 j; ACPI_FUNCTION_TRACE("acpi_get_firmware_table"); /* * Ensure that at least the table manager is initialized. We don't * require that the entire ACPI subsystem is up for this interface. * If we have a buffer, we must have a length too */ if ((instance == 0) || (!signature) || (!table_pointer)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* Ensure that we have a RSDP */ if (!acpi_gbl_RSDP) { /* Get the RSDP */ status = acpi_os_get_root_pointer(flags, &address); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "RSDP not found\n")); return_ACPI_STATUS(AE_NO_ACPI_TABLES); } /* Map and validate the RSDP */ if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { status = acpi_os_map_memory(address.pointer.physical, sizeof(struct rsdp_descriptor), (void *)&acpi_gbl_RSDP); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } else { acpi_gbl_RSDP = address.pointer.logical; } /* The RDSP signature and checksum must both be correct */ status = acpi_tb_validate_rsdp(acpi_gbl_RSDP); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* Get the RSDT address via the RSDP */ acpi_tb_get_rsdt_address(&address); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "RSDP located at %p, RSDT physical=%8.8X%8.8X \n", acpi_gbl_RSDP, ACPI_FORMAT_UINT64(address.pointer.value))); /* Insert processor_mode flags */ address.pointer_type |= flags; /* Get and validate the RSDT */ rsdt_info = ACPI_MEM_CALLOCATE(sizeof(struct acpi_table_desc)); if (!rsdt_info) { return_ACPI_STATUS(AE_NO_MEMORY); } status = acpi_tb_get_table(&address, rsdt_info); if (ACPI_FAILURE(status)) { goto cleanup; } status = acpi_tb_validate_rsdt(rsdt_info->pointer); if (ACPI_FAILURE(status)) { goto cleanup; } /* Allocate a scratch table header and table descriptor */ header = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_header)); if (!header) { status = AE_NO_MEMORY; goto cleanup; } table_info = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_desc)); if (!table_info) { status = AE_NO_MEMORY; goto cleanup; } /* Get the number of table pointers within the RSDT */ table_count = acpi_tb_get_table_count(acpi_gbl_RSDP, rsdt_info->pointer); address.pointer_type = acpi_gbl_table_flags | flags; /* * Search the RSDT/XSDT for the correct instance of the * requested table */ for (i = 0, j = 0; i < table_count; i++) { /* * Get the next table pointer, handle RSDT vs. XSDT * RSDT pointers are 32 bits, XSDT pointers are 64 bits */ if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { address.pointer.value = (ACPI_CAST_PTR (RSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i]; } else { address.pointer.value = (ACPI_CAST_PTR (XSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i]; } /* Get the table header */ status = acpi_tb_get_table_header(&address, header); if (ACPI_FAILURE(status)) { goto cleanup; } /* Compare table signatures and table instance */ if (!ACPI_STRNCMP(header->signature, signature, ACPI_NAME_SIZE)) { /* An instance of the table was found */ j++; if (j >= instance) { /* Found the correct instance, get the entire table */ status = acpi_tb_get_table_body(&address, header, table_info); if (ACPI_FAILURE(status)) { goto cleanup; } *table_pointer = table_info->pointer; goto cleanup; } } } /* Did not find the table */ status = AE_NOT_EXIST; cleanup: if (rsdt_info->pointer) { acpi_os_unmap_memory(rsdt_info->pointer, (acpi_size) rsdt_info->pointer->length); } ACPI_MEM_FREE(rsdt_info); if (header) { ACPI_MEM_FREE(header); } if (table_info) { ACPI_MEM_FREE(table_info); } return_ACPI_STATUS(status); }
acpi_status acpi_hw_initialize ( void) { acpi_status status = AE_OK; u32 index; FUNCTION_TRACE ("Hw_initialize"); /* We must have the ACPI tables by the time we get here */ if (!acpi_gbl_FADT) { acpi_gbl_restore_acpi_chipset = FALSE; ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No FADT!\n")); return_ACPI_STATUS (AE_NO_ACPI_TABLES); } /* Identify current ACPI/legacy mode */ switch (acpi_gbl_system_flags & SYS_MODES_MASK) { case (SYS_MODE_ACPI): acpi_gbl_original_mode = SYS_MODE_ACPI; ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "System supports ACPI mode only.\n")); break; case (SYS_MODE_LEGACY): acpi_gbl_original_mode = SYS_MODE_LEGACY; ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Tables loaded from buffer, hardware assumed to support LEGACY mode only.\n")); break; case (SYS_MODE_ACPI | SYS_MODE_LEGACY): if (acpi_hw_get_mode () == SYS_MODE_ACPI) { acpi_gbl_original_mode = SYS_MODE_ACPI; } else { acpi_gbl_original_mode = SYS_MODE_LEGACY; } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "System supports both ACPI and LEGACY modes.\n")); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "System is currently in %s mode.\n", (acpi_gbl_original_mode == SYS_MODE_ACPI) ? "ACPI" : "LEGACY")); break; } if (acpi_gbl_system_flags & SYS_MODE_ACPI) { /* Target system supports ACPI mode */ /* * The purpose of this code is to save the initial state * of the ACPI event enable registers. An exit function will be * registered which will restore this state when the application * exits. The exit function will also clear all of the ACPI event * status bits prior to restoring the original mode. * * The location of the PM1a_evt_blk enable registers is defined as the * base of PM1a_evt_blk + DIV_2(PM1a_evt_blk_length). Since the spec further * fully defines the PM1a_evt_blk to be a total of 4 bytes, the offset * for the enable registers is always 2 from the base. It is hard * coded here. If this changes in the spec, this code will need to * be modified. The PM1b_evt_blk behaves as expected. */ acpi_gbl_pm1_enable_register_save = (u16) acpi_hw_register_read ( ACPI_MTX_LOCK, PM1_EN); /* * The GPEs behave similarly, except that the length of the register * block is not fixed, so the buffer must be allocated with malloc */ if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) && acpi_gbl_FADT->gpe0blk_len) { /* GPE0 specified in FADT */ acpi_gbl_gpe0enable_register_save = ACPI_MEM_ALLOCATE ( DIV_2 (acpi_gbl_FADT->gpe0blk_len)); if (!acpi_gbl_gpe0enable_register_save) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Save state of GPE0 enable bits */ for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe0blk_len); index++) { acpi_gbl_gpe0enable_register_save[index] = (u8) acpi_hw_register_read (ACPI_MTX_LOCK, GPE0_EN_BLOCK | index); } } else { acpi_gbl_gpe0enable_register_save = NULL; } if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) && acpi_gbl_FADT->gpe1_blk_len) { /* GPE1 defined */ acpi_gbl_gpe1_enable_register_save = ACPI_MEM_ALLOCATE ( DIV_2 (acpi_gbl_FADT->gpe1_blk_len)); if (!acpi_gbl_gpe1_enable_register_save) { return_ACPI_STATUS (AE_NO_MEMORY); } /* save state of GPE1 enable bits */ for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe1_blk_len); index++) { acpi_gbl_gpe1_enable_register_save[index] = (u8) acpi_hw_register_read (ACPI_MTX_LOCK, GPE1_EN_BLOCK | index); } } else { acpi_gbl_gpe1_enable_register_save = NULL; } } return_ACPI_STATUS (status); }
acpi_status acpi_ex_store_buffer_to_buffer ( acpi_object_type original_src_type, union acpi_operand_object *source_desc, union acpi_operand_object *target_desc) { u32 length; u8 *buffer; ACPI_FUNCTION_TRACE_PTR ("ex_store_buffer_to_buffer", source_desc); /* * We know that source_desc is a buffer by now */ buffer = (u8 *) source_desc->buffer.pointer; length = source_desc->buffer.length; /* * If target is a buffer of length zero or is a static buffer, * allocate a new buffer of the proper length */ if ((target_desc->buffer.length == 0) || (target_desc->common.flags & AOPOBJ_STATIC_POINTER)) { target_desc->buffer.pointer = ACPI_MEM_ALLOCATE (length); if (!target_desc->buffer.pointer) { return_ACPI_STATUS (AE_NO_MEMORY); } target_desc->buffer.length = length; } /* Copy source buffer to target buffer */ if (length <= target_desc->buffer.length) { /* Clear existing buffer and copy in the new one */ ACPI_MEMSET (target_desc->buffer.pointer, 0, target_desc->buffer.length); ACPI_MEMCPY (target_desc->buffer.pointer, buffer, length); /* * If the original source was a string, we must truncate the buffer, * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer * copy must not truncate the original buffer. */ if (original_src_type == ACPI_TYPE_STRING) { /* Set the new length of the target */ target_desc->buffer.length = length; } } else { /* Truncate the source, copy only what will fit */ ACPI_MEMCPY (target_desc->buffer.pointer, buffer, target_desc->buffer.length); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Truncating source buffer from %X to %X\n", length, target_desc->buffer.length)); } /* Copy flags */ target_desc->buffer.flags = source_desc->buffer.flags; target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER; return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AcpiExDoConcatenate ( ACPI_OPERAND_OBJECT *ObjDesc1, ACPI_OPERAND_OBJECT *ObjDesc2, ACPI_OPERAND_OBJECT **ActualReturnDesc, ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status; UINT32 i; ACPI_INTEGER ThisInteger; ACPI_OPERAND_OBJECT *ReturnDesc; NATIVE_CHAR *NewBuf; ACPI_FUNCTION_ENTRY (); /* * 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 (ObjDesc1)) { case ACPI_TYPE_INTEGER: /* Result of two Integers is a Buffer */ /* Need enough buffer space for two integers */ ReturnDesc = AcpiUtCreateBufferObject (AcpiGbl_IntegerByteWidth * 2); if (!ReturnDesc) { return (AE_NO_MEMORY); } NewBuf = (NATIVE_CHAR *) ReturnDesc->Buffer.Pointer; /* Convert the first integer */ ThisInteger = ObjDesc1->Integer.Value; for (i = 0; i < AcpiGbl_IntegerByteWidth; i++) { NewBuf[i] = (NATIVE_CHAR) ThisInteger; ThisInteger >>= 8; } /* Convert the second integer */ ThisInteger = ObjDesc2->Integer.Value; for (; i < (ACPI_MUL_2 (AcpiGbl_IntegerByteWidth)); i++) { NewBuf[i] = (NATIVE_CHAR) ThisInteger; ThisInteger >>= 8; } break; case ACPI_TYPE_STRING: /* Result of two Strings is a String */ ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_STRING); if (!ReturnDesc) { return (AE_NO_MEMORY); } /* Operand0 is string */ NewBuf = ACPI_MEM_ALLOCATE ((ACPI_SIZE) ObjDesc1->String.Length + (ACPI_SIZE) ObjDesc2->String.Length + 1); if (!NewBuf) { ACPI_REPORT_ERROR (("ExDoConcatenate: String allocation failure\n")); Status = AE_NO_MEMORY; goto Cleanup; } /* Concatenate the strings */ ACPI_STRCPY (NewBuf, ObjDesc1->String.Pointer); ACPI_STRCPY (NewBuf + ObjDesc1->String.Length, ObjDesc2->String.Pointer); /* Complete the String object initialization */ ReturnDesc->String.Pointer = NewBuf; ReturnDesc->String.Length = ObjDesc1->String.Length + ObjDesc2->String.Length; break; case ACPI_TYPE_BUFFER: /* Result of two Buffers is a Buffer */ ReturnDesc = AcpiUtCreateBufferObject ( (ACPI_SIZE) ObjDesc1->Buffer.Length + (ACPI_SIZE) ObjDesc2->Buffer.Length); if (!ReturnDesc) { return (AE_NO_MEMORY); } NewBuf = (NATIVE_CHAR *) ReturnDesc->Buffer.Pointer; /* Concatenate the buffers */ ACPI_MEMCPY (NewBuf, ObjDesc1->Buffer.Pointer, ObjDesc1->Buffer.Length); ACPI_MEMCPY (NewBuf + ObjDesc1->Buffer.Length, ObjDesc2->Buffer.Pointer, ObjDesc2->Buffer.Length); break; default: /* Invalid object type, should not happen here */ Status = AE_AML_INTERNAL; ReturnDesc = NULL; } *ActualReturnDesc = ReturnDesc; return (AE_OK); Cleanup: AcpiUtRemoveReference (ReturnDesc); return (Status); }
acpi_status acpi_ex_do_concatenate ( acpi_operand_object *obj_desc, acpi_operand_object *obj_desc2, acpi_operand_object **actual_return_desc, acpi_walk_state *walk_state) { acpi_status status; u32 i; acpi_integer this_integer; acpi_operand_object *return_desc; NATIVE_CHAR *new_buf; u32 integer_size = sizeof (acpi_integer); FUNCTION_ENTRY (); /* * There are three cases to handle: * 1) Two Integers concatenated to produce a buffer * 2) Two Strings concatenated to produce a string * 3) Two Buffers concatenated to produce a buffer */ switch (obj_desc->common.type) { case ACPI_TYPE_INTEGER: /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */ if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) { /* * We are running a method that exists in a 32-bit ACPI table. * Truncate the value to 32 bits by zeroing out the upper * 32-bit field */ integer_size = sizeof (u32); } /* Result of two integers is a buffer */ return_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); if (!return_desc) { return (AE_NO_MEMORY); } /* Need enough space for two integers */ return_desc->buffer.length = integer_size * 2; new_buf = ACPI_MEM_CALLOCATE (return_desc->buffer.length); if (!new_buf) { REPORT_ERROR (("Ex_do_concatenate: Buffer allocation failure\n")); status = AE_NO_MEMORY; goto cleanup; } return_desc->buffer.pointer = (u8 *) new_buf; /* Convert the first integer */ this_integer = obj_desc->integer.value; for (i = 0; i < integer_size; i++) { new_buf[i] = (u8) this_integer; this_integer >>= 8; } /* Convert the second integer */ this_integer = obj_desc2->integer.value; for (; i < (integer_size * 2); i++) { new_buf[i] = (u8) this_integer; this_integer >>= 8; } break; case ACPI_TYPE_STRING: return_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING); if (!return_desc) { return (AE_NO_MEMORY); } /* Operand0 is string */ new_buf = ACPI_MEM_ALLOCATE (obj_desc->string.length + obj_desc2->string.length + 1); if (!new_buf) { REPORT_ERROR (("Ex_do_concatenate: String allocation failure\n")); status = AE_NO_MEMORY; goto cleanup; } STRCPY (new_buf, obj_desc->string.pointer); STRCPY (new_buf + obj_desc->string.length, obj_desc2->string.pointer); /* Point the return object to the new string */ return_desc->string.pointer = new_buf; return_desc->string.length = obj_desc->string.length += obj_desc2->string.length; break; case ACPI_TYPE_BUFFER: /* Operand0 is a buffer */ return_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); if (!return_desc) { return (AE_NO_MEMORY); } new_buf = ACPI_MEM_ALLOCATE (obj_desc->buffer.length + obj_desc2->buffer.length); if (!new_buf) { REPORT_ERROR (("Ex_do_concatenate: Buffer allocation failure\n")); status = AE_NO_MEMORY; goto cleanup; } MEMCPY (new_buf, obj_desc->buffer.pointer, obj_desc->buffer.length); MEMCPY (new_buf + obj_desc->buffer.length, obj_desc2->buffer.pointer, obj_desc2->buffer.length); /* * Point the return object to the new buffer */ return_desc->buffer.pointer = (u8 *) new_buf; return_desc->buffer.length = obj_desc->buffer.length + obj_desc2->buffer.length; break; default: status = AE_AML_INTERNAL; return_desc = NULL; } *actual_return_desc = return_desc; return (AE_OK); cleanup: acpi_ut_remove_reference (return_desc); return (status); }
static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs) { char *temp_ptr; char *name_string; u32 size_needed; ACPI_FUNCTION_TRACE("ex_allocate_name_string"); /* * Allow room for all \ and ^ prefixes, all segments and a multi_name_prefix. * Also, one byte for the null terminator. * This may actually be somewhat longer than needed. */ if (prefix_count == ACPI_UINT32_MAX) { /* Special case for root */ size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; } else { size_needed = prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; } /* * Allocate a buffer for the name. * This buffer must be deleted by the caller! */ name_string = ACPI_MEM_ALLOCATE(size_needed); if (!name_string) { ACPI_ERROR((AE_INFO, "Could not allocate size %d", size_needed)); return_PTR(NULL); } temp_ptr = name_string; /* Set up Root or Parent prefixes if needed */ if (prefix_count == ACPI_UINT32_MAX) { *temp_ptr++ = AML_ROOT_PREFIX; } else { while (prefix_count--) { *temp_ptr++ = AML_PARENT_PREFIX; } } /* Set up Dual or Multi prefixes if needed */ if (num_name_segs > 2) { /* Set up multi prefixes */ *temp_ptr++ = AML_MULTI_NAME_PREFIX_OP; *temp_ptr++ = (char)num_name_segs; } else if (2 == num_name_segs) { /* Set up dual prefixes */ *temp_ptr++ = AML_DUAL_NAME_PREFIX; } /* * Terminate string following prefixes. acpi_ex_name_segment() will * append the segment(s) */ *temp_ptr = 0; return_PTR(name_string); }
NATIVE_CHAR * AcpiExAllocateNameString ( UINT32 PrefixCount, UINT32 NumNameSegs) { NATIVE_CHAR *TempPtr; NATIVE_CHAR *NameString; UINT32 SizeNeeded; ACPI_FUNCTION_TRACE ("ExAllocateNameString"); /* * Allow room for all \ and ^ prefixes, all segments, and a MultiNamePrefix. * Also, one byte for the null terminator. * This may actually be somewhat longer than needed. */ if (PrefixCount == ACPI_UINT32_MAX) { /* Special case for root */ SizeNeeded = 1 + (ACPI_NAME_SIZE * NumNameSegs) + 2 + 1; } else { SizeNeeded = PrefixCount + (ACPI_NAME_SIZE * NumNameSegs) + 2 + 1; } /* * Allocate a buffer for the name. * This buffer must be deleted by the caller! */ NameString = ACPI_MEM_ALLOCATE (SizeNeeded); if (!NameString) { ACPI_REPORT_ERROR (("ExAllocateNameString: Could not allocate size %d\n", SizeNeeded)); return_PTR (NULL); } TempPtr = NameString; /* Set up Root or Parent prefixes if needed */ if (PrefixCount == ACPI_UINT32_MAX) { *TempPtr++ = AML_ROOT_PREFIX; } else { while (PrefixCount--) { *TempPtr++ = AML_PARENT_PREFIX; } } /* Set up Dual or Multi prefixes if needed */ if (NumNameSegs > 2) { /* Set up multi prefixes */ *TempPtr++ = AML_MULTI_NAME_PREFIX_OP; *TempPtr++ = (char) NumNameSegs; } else if (2 == NumNameSegs) { /* Set up dual prefixes */ *TempPtr++ = AML_DUAL_NAME_PREFIX; } /* * Terminate string following prefixes. AcpiExNameSegment() will * append the segment(s) */ *TempPtr = 0; return_PTR (NameString); }