xref: /linux/drivers/acpi/acpica/rsaddr.c (revision 11b3125073d16929403d3aa7b2ae6a482060a937)
195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /*******************************************************************************
395b482a8SLen Brown  *
495b482a8SLen Brown  * Module Name: rsaddr - Address resource descriptors (16/32/64)
595b482a8SLen Brown  *
695b482a8SLen Brown  ******************************************************************************/
795b482a8SLen Brown 
895b482a8SLen Brown #include <acpi/acpi.h>
9e2f7a777SLen Brown #include "accommon.h"
10e2f7a777SLen Brown #include "acresrc.h"
1195b482a8SLen Brown 
1295b482a8SLen Brown #define _COMPONENT          ACPI_RESOURCES
1395b482a8SLen Brown ACPI_MODULE_NAME("rsaddr")
1495b482a8SLen Brown 
1595b482a8SLen Brown /*******************************************************************************
1695b482a8SLen Brown  *
1795b482a8SLen Brown  * acpi_rs_convert_address16 - All WORD (16-bit) address resources
1895b482a8SLen Brown  *
1995b482a8SLen Brown  ******************************************************************************/
2095b482a8SLen Brown struct acpi_rsconvert_info acpi_rs_convert_address16[5] = {
2195b482a8SLen Brown 	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS16,
2295b482a8SLen Brown 	 ACPI_RS_SIZE(struct acpi_resource_address16),
2395b482a8SLen Brown 	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address16)},
2495b482a8SLen Brown 
2595b482a8SLen Brown 	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS16,
2695b482a8SLen Brown 	 sizeof(struct aml_resource_address16),
2795b482a8SLen Brown 	 0},
2895b482a8SLen Brown 
2995b482a8SLen Brown 	/* Resource Type, General Flags, and Type-Specific Flags */
3095b482a8SLen Brown 
3195b482a8SLen Brown 	{ACPI_RSC_ADDRESS, 0, 0, 0},
3295b482a8SLen Brown 
3395b482a8SLen Brown 	/*
3495b482a8SLen Brown 	 * These fields are contiguous in both the source and destination:
3595b482a8SLen Brown 	 * Address Granularity
3695b482a8SLen Brown 	 * Address Range Minimum
3795b482a8SLen Brown 	 * Address Range Maximum
3895b482a8SLen Brown 	 * Address Translation Offset
3995b482a8SLen Brown 	 * Address Length
4095b482a8SLen Brown 	 */
41a45de93eSLv Zheng 	{ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.address16.address.granularity),
4295b482a8SLen Brown 	 AML_OFFSET(address16.granularity),
4395b482a8SLen Brown 	 5},
4495b482a8SLen Brown 
4595b482a8SLen Brown 	/* Optional resource_source (Index and String) */
4695b482a8SLen Brown 
4795b482a8SLen Brown 	{ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address16.resource_source),
4895b482a8SLen Brown 	 0,
4995b482a8SLen Brown 	 sizeof(struct aml_resource_address16)}
5095b482a8SLen Brown };
5195b482a8SLen Brown 
5295b482a8SLen Brown /*******************************************************************************
5395b482a8SLen Brown  *
5495b482a8SLen Brown  * acpi_rs_convert_address32 - All DWORD (32-bit) address resources
5595b482a8SLen Brown  *
5695b482a8SLen Brown  ******************************************************************************/
5795b482a8SLen Brown 
5895b482a8SLen Brown struct acpi_rsconvert_info acpi_rs_convert_address32[5] = {
5995b482a8SLen Brown 	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS32,
6095b482a8SLen Brown 	 ACPI_RS_SIZE(struct acpi_resource_address32),
6195b482a8SLen Brown 	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address32)},
6295b482a8SLen Brown 
6395b482a8SLen Brown 	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS32,
6495b482a8SLen Brown 	 sizeof(struct aml_resource_address32),
6595b482a8SLen Brown 	 0},
6695b482a8SLen Brown 
6795b482a8SLen Brown 	/* Resource Type, General Flags, and Type-Specific Flags */
6895b482a8SLen Brown 
6995b482a8SLen Brown 	{ACPI_RSC_ADDRESS, 0, 0, 0},
7095b482a8SLen Brown 
7195b482a8SLen Brown 	/*
7295b482a8SLen Brown 	 * These fields are contiguous in both the source and destination:
7395b482a8SLen Brown 	 * Address Granularity
7495b482a8SLen Brown 	 * Address Range Minimum
7595b482a8SLen Brown 	 * Address Range Maximum
7695b482a8SLen Brown 	 * Address Translation Offset
7795b482a8SLen Brown 	 * Address Length
7895b482a8SLen Brown 	 */
79a45de93eSLv Zheng 	{ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.address32.address.granularity),
8095b482a8SLen Brown 	 AML_OFFSET(address32.granularity),
8195b482a8SLen Brown 	 5},
8295b482a8SLen Brown 
8395b482a8SLen Brown 	/* Optional resource_source (Index and String) */
8495b482a8SLen Brown 
8595b482a8SLen Brown 	{ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address32.resource_source),
8695b482a8SLen Brown 	 0,
8795b482a8SLen Brown 	 sizeof(struct aml_resource_address32)}
8895b482a8SLen Brown };
8995b482a8SLen Brown 
9095b482a8SLen Brown /*******************************************************************************
9195b482a8SLen Brown  *
9295b482a8SLen Brown  * acpi_rs_convert_address64 - All QWORD (64-bit) address resources
9395b482a8SLen Brown  *
9495b482a8SLen Brown  ******************************************************************************/
9595b482a8SLen Brown 
9695b482a8SLen Brown struct acpi_rsconvert_info acpi_rs_convert_address64[5] = {
9795b482a8SLen Brown 	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS64,
9895b482a8SLen Brown 	 ACPI_RS_SIZE(struct acpi_resource_address64),
9995b482a8SLen Brown 	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address64)},
10095b482a8SLen Brown 
10195b482a8SLen Brown 	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS64,
10295b482a8SLen Brown 	 sizeof(struct aml_resource_address64),
10395b482a8SLen Brown 	 0},
10495b482a8SLen Brown 
10595b482a8SLen Brown 	/* Resource Type, General Flags, and Type-Specific Flags */
10695b482a8SLen Brown 
10795b482a8SLen Brown 	{ACPI_RSC_ADDRESS, 0, 0, 0},
10895b482a8SLen Brown 
10995b482a8SLen Brown 	/*
11095b482a8SLen Brown 	 * These fields are contiguous in both the source and destination:
11195b482a8SLen Brown 	 * Address Granularity
11295b482a8SLen Brown 	 * Address Range Minimum
11395b482a8SLen Brown 	 * Address Range Maximum
11495b482a8SLen Brown 	 * Address Translation Offset
11595b482a8SLen Brown 	 * Address Length
11695b482a8SLen Brown 	 */
117a45de93eSLv Zheng 	{ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.address64.address.granularity),
11895b482a8SLen Brown 	 AML_OFFSET(address64.granularity),
11995b482a8SLen Brown 	 5},
12095b482a8SLen Brown 
12195b482a8SLen Brown 	/* Optional resource_source (Index and String) */
12295b482a8SLen Brown 
12395b482a8SLen Brown 	{ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address64.resource_source),
12495b482a8SLen Brown 	 0,
12595b482a8SLen Brown 	 sizeof(struct aml_resource_address64)}
12695b482a8SLen Brown };
12795b482a8SLen Brown 
12895b482a8SLen Brown /*******************************************************************************
12995b482a8SLen Brown  *
13095b482a8SLen Brown  * acpi_rs_convert_ext_address64 - All Extended (64-bit) address resources
13195b482a8SLen Brown  *
13295b482a8SLen Brown  ******************************************************************************/
13395b482a8SLen Brown 
13495b482a8SLen Brown struct acpi_rsconvert_info acpi_rs_convert_ext_address64[5] = {
13595b482a8SLen Brown 	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64,
13695b482a8SLen Brown 	 ACPI_RS_SIZE(struct acpi_resource_extended_address64),
13795b482a8SLen Brown 	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_ext_address64)},
13895b482a8SLen Brown 
13995b482a8SLen Brown 	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64,
14095b482a8SLen Brown 	 sizeof(struct aml_resource_extended_address64),
14195b482a8SLen Brown 	 0},
14295b482a8SLen Brown 
14395b482a8SLen Brown 	/* Resource Type, General Flags, and Type-Specific Flags */
14495b482a8SLen Brown 
14595b482a8SLen Brown 	{ACPI_RSC_ADDRESS, 0, 0, 0},
14695b482a8SLen Brown 
14795b482a8SLen Brown 	/* Revision ID */
14895b482a8SLen Brown 
149ba494beeSBob Moore 	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.ext_address64.revision_ID),
150ba494beeSBob Moore 	 AML_OFFSET(ext_address64.revision_ID),
15195b482a8SLen Brown 	 1},
15295b482a8SLen Brown 	/*
15395b482a8SLen Brown 	 * These fields are contiguous in both the source and destination:
15495b482a8SLen Brown 	 * Address Granularity
15595b482a8SLen Brown 	 * Address Range Minimum
15695b482a8SLen Brown 	 * Address Range Maximum
15795b482a8SLen Brown 	 * Address Translation Offset
15895b482a8SLen Brown 	 * Address Length
15995b482a8SLen Brown 	 * Type-Specific Attribute
16095b482a8SLen Brown 	 */
161a45de93eSLv Zheng 	{ACPI_RSC_MOVE64,
162a45de93eSLv Zheng 	 ACPI_RS_OFFSET(data.ext_address64.address.granularity),
16395b482a8SLen Brown 	 AML_OFFSET(ext_address64.granularity),
16495b482a8SLen Brown 	 6}
16595b482a8SLen Brown };
16695b482a8SLen Brown 
16795b482a8SLen Brown /*******************************************************************************
16895b482a8SLen Brown  *
16995b482a8SLen Brown  * acpi_rs_convert_general_flags - Flags common to all address descriptors
17095b482a8SLen Brown  *
17195b482a8SLen Brown  ******************************************************************************/
17295b482a8SLen Brown 
17395b482a8SLen Brown static struct acpi_rsconvert_info acpi_rs_convert_general_flags[6] = {
17495b482a8SLen Brown 	{ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.flags),
17595b482a8SLen Brown 	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_general_flags)},
17695b482a8SLen Brown 
17795b482a8SLen Brown 	/* Resource Type (Memory, Io, bus_number, etc.) */
17895b482a8SLen Brown 
17995b482a8SLen Brown 	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.address.resource_type),
18095b482a8SLen Brown 	 AML_OFFSET(address.resource_type),
18195b482a8SLen Brown 	 1},
18295b482a8SLen Brown 
183ba494beeSBob Moore 	/* General flags - Consume, Decode, min_fixed, max_fixed */
18495b482a8SLen Brown 
18595b482a8SLen Brown 	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.producer_consumer),
18695b482a8SLen Brown 	 AML_OFFSET(address.flags),
18795b482a8SLen Brown 	 0},
18895b482a8SLen Brown 
18995b482a8SLen Brown 	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.decode),
19095b482a8SLen Brown 	 AML_OFFSET(address.flags),
19195b482a8SLen Brown 	 1},
19295b482a8SLen Brown 
19395b482a8SLen Brown 	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.min_address_fixed),
19495b482a8SLen Brown 	 AML_OFFSET(address.flags),
19595b482a8SLen Brown 	 2},
19695b482a8SLen Brown 
19795b482a8SLen Brown 	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.max_address_fixed),
19895b482a8SLen Brown 	 AML_OFFSET(address.flags),
19995b482a8SLen Brown 	 3}
20095b482a8SLen Brown };
20195b482a8SLen Brown 
20295b482a8SLen Brown /*******************************************************************************
20395b482a8SLen Brown  *
20495b482a8SLen Brown  * acpi_rs_convert_mem_flags - Flags common to Memory address descriptors
20595b482a8SLen Brown  *
20695b482a8SLen Brown  ******************************************************************************/
20795b482a8SLen Brown 
20895b482a8SLen Brown static struct acpi_rsconvert_info acpi_rs_convert_mem_flags[5] = {
20995b482a8SLen Brown 	{ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.specific_flags),
21095b482a8SLen Brown 	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_mem_flags)},
21195b482a8SLen Brown 
21295b482a8SLen Brown 	/* Memory-specific flags */
21395b482a8SLen Brown 
21495b482a8SLen Brown 	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.write_protect),
21595b482a8SLen Brown 	 AML_OFFSET(address.specific_flags),
21695b482a8SLen Brown 	 0},
21795b482a8SLen Brown 
21895b482a8SLen Brown 	{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.caching),
21995b482a8SLen Brown 	 AML_OFFSET(address.specific_flags),
22095b482a8SLen Brown 	 1},
22195b482a8SLen Brown 
22295b482a8SLen Brown 	{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.range_type),
22395b482a8SLen Brown 	 AML_OFFSET(address.specific_flags),
22495b482a8SLen Brown 	 3},
22595b482a8SLen Brown 
22695b482a8SLen Brown 	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.translation),
22795b482a8SLen Brown 	 AML_OFFSET(address.specific_flags),
22895b482a8SLen Brown 	 5}
22995b482a8SLen Brown };
23095b482a8SLen Brown 
23195b482a8SLen Brown /*******************************************************************************
23295b482a8SLen Brown  *
23395b482a8SLen Brown  * acpi_rs_convert_io_flags - Flags common to I/O address descriptors
23495b482a8SLen Brown  *
23595b482a8SLen Brown  ******************************************************************************/
23695b482a8SLen Brown 
23795b482a8SLen Brown static struct acpi_rsconvert_info acpi_rs_convert_io_flags[4] = {
23895b482a8SLen Brown 	{ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.specific_flags),
23995b482a8SLen Brown 	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_io_flags)},
24095b482a8SLen Brown 
24195b482a8SLen Brown 	/* I/O-specific flags */
24295b482a8SLen Brown 
24395b482a8SLen Brown 	{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.io.range_type),
24495b482a8SLen Brown 	 AML_OFFSET(address.specific_flags),
24595b482a8SLen Brown 	 0},
24695b482a8SLen Brown 
24795b482a8SLen Brown 	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.io.translation),
24895b482a8SLen Brown 	 AML_OFFSET(address.specific_flags),
24995b482a8SLen Brown 	 4},
25095b482a8SLen Brown 
25195b482a8SLen Brown 	{ACPI_RSC_1BITFLAG,
25295b482a8SLen Brown 	 ACPI_RS_OFFSET(data.address.info.io.translation_type),
25395b482a8SLen Brown 	 AML_OFFSET(address.specific_flags),
25495b482a8SLen Brown 	 5}
25595b482a8SLen Brown };
25695b482a8SLen Brown 
25795b482a8SLen Brown /*******************************************************************************
25895b482a8SLen Brown  *
25995b482a8SLen Brown  * FUNCTION:    acpi_rs_get_address_common
26095b482a8SLen Brown  *
261ba494beeSBob Moore  * PARAMETERS:  resource            - Pointer to the internal resource struct
262ba494beeSBob Moore  *              aml                 - Pointer to the AML resource descriptor
26395b482a8SLen Brown  *
26495b482a8SLen Brown  * RETURN:      TRUE if the resource_type field is OK, FALSE otherwise
26595b482a8SLen Brown  *
26695b482a8SLen Brown  * DESCRIPTION: Convert common flag fields from a raw AML resource descriptor
26795b482a8SLen Brown  *              to an internal resource descriptor
26895b482a8SLen Brown  *
26995b482a8SLen Brown  ******************************************************************************/
27095b482a8SLen Brown 
27195b482a8SLen Brown u8
acpi_rs_get_address_common(struct acpi_resource * resource,union aml_resource * aml)27295b482a8SLen Brown acpi_rs_get_address_common(struct acpi_resource *resource,
27395b482a8SLen Brown 			   union aml_resource *aml)
27495b482a8SLen Brown {
27524d9609bSTamir Duberstein 	struct aml_resource_address address;
27624d9609bSTamir Duberstein 
27795b482a8SLen Brown 	ACPI_FUNCTION_ENTRY();
27895b482a8SLen Brown 
27924d9609bSTamir Duberstein 	/* Avoid undefined behavior: member access within misaligned address */
28024d9609bSTamir Duberstein 
28124d9609bSTamir Duberstein 	memcpy(&address, aml, sizeof(address));
28224d9609bSTamir Duberstein 
28395b482a8SLen Brown 	/* Validate the Resource Type */
28495b482a8SLen Brown 
285*cff8a9f6SAdam Young 	if ((address.resource_type > 2) &&
286*cff8a9f6SAdam Young 	    (address.resource_type < 0xC0) && (address.resource_type != 0x0A)) {
28795b482a8SLen Brown 		return (FALSE);
28895b482a8SLen Brown 	}
28995b482a8SLen Brown 
29095b482a8SLen Brown 	/* Get the Resource Type and General Flags */
29195b482a8SLen Brown 
29295b482a8SLen Brown 	(void)acpi_rs_convert_aml_to_resource(resource, aml,
29395b482a8SLen Brown 					      acpi_rs_convert_general_flags);
29495b482a8SLen Brown 
29595b482a8SLen Brown 	/* Get the Type-Specific Flags (Memory and I/O descriptors only) */
29695b482a8SLen Brown 
29795b482a8SLen Brown 	if (resource->data.address.resource_type == ACPI_MEMORY_RANGE) {
29895b482a8SLen Brown 		(void)acpi_rs_convert_aml_to_resource(resource, aml,
29995b482a8SLen Brown 						      acpi_rs_convert_mem_flags);
30095b482a8SLen Brown 	} else if (resource->data.address.resource_type == ACPI_IO_RANGE) {
30195b482a8SLen Brown 		(void)acpi_rs_convert_aml_to_resource(resource, aml,
30295b482a8SLen Brown 						      acpi_rs_convert_io_flags);
30395b482a8SLen Brown 	} else {
30495b482a8SLen Brown 		/* Generic resource type, just grab the type_specific byte */
30595b482a8SLen Brown 
30695b482a8SLen Brown 		resource->data.address.info.type_specific =
30724d9609bSTamir Duberstein 		    address.specific_flags;
30895b482a8SLen Brown 	}
30995b482a8SLen Brown 
31095b482a8SLen Brown 	return (TRUE);
31195b482a8SLen Brown }
31295b482a8SLen Brown 
31395b482a8SLen Brown /*******************************************************************************
31495b482a8SLen Brown  *
31595b482a8SLen Brown  * FUNCTION:    acpi_rs_set_address_common
31695b482a8SLen Brown  *
317ba494beeSBob Moore  * PARAMETERS:  aml                 - Pointer to the AML resource descriptor
318ba494beeSBob Moore  *              resource            - Pointer to the internal resource struct
31995b482a8SLen Brown  *
32095b482a8SLen Brown  * RETURN:      None
32195b482a8SLen Brown  *
32295b482a8SLen Brown  * DESCRIPTION: Convert common flag fields from a resource descriptor to an
32395b482a8SLen Brown  *              AML descriptor
32495b482a8SLen Brown  *
32595b482a8SLen Brown  ******************************************************************************/
32695b482a8SLen Brown 
32795b482a8SLen Brown void
acpi_rs_set_address_common(union aml_resource * aml,struct acpi_resource * resource)32895b482a8SLen Brown acpi_rs_set_address_common(union aml_resource *aml,
32995b482a8SLen Brown 			   struct acpi_resource *resource)
33095b482a8SLen Brown {
33195b482a8SLen Brown 	ACPI_FUNCTION_ENTRY();
33295b482a8SLen Brown 
33395b482a8SLen Brown 	/* Set the Resource Type and General Flags */
33495b482a8SLen Brown 
33595b482a8SLen Brown 	(void)acpi_rs_convert_resource_to_aml(resource, aml,
33695b482a8SLen Brown 					      acpi_rs_convert_general_flags);
33795b482a8SLen Brown 
33895b482a8SLen Brown 	/* Set the Type-Specific Flags (Memory and I/O descriptors only) */
33995b482a8SLen Brown 
34095b482a8SLen Brown 	if (resource->data.address.resource_type == ACPI_MEMORY_RANGE) {
34195b482a8SLen Brown 		(void)acpi_rs_convert_resource_to_aml(resource, aml,
34295b482a8SLen Brown 						      acpi_rs_convert_mem_flags);
34395b482a8SLen Brown 	} else if (resource->data.address.resource_type == ACPI_IO_RANGE) {
34495b482a8SLen Brown 		(void)acpi_rs_convert_resource_to_aml(resource, aml,
34595b482a8SLen Brown 						      acpi_rs_convert_io_flags);
34695b482a8SLen Brown 	} else {
34795b482a8SLen Brown 		/* Generic resource type, just copy the type_specific byte */
34895b482a8SLen Brown 
34995b482a8SLen Brown 		aml->address.specific_flags =
35095b482a8SLen Brown 		    resource->data.address.info.type_specific;
35195b482a8SLen Brown 	}
35295b482a8SLen Brown }
353