1  // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2  /*******************************************************************************
3   *
4   * Module Name: rsaddr - Address resource descriptors (16/32/64)
5   *
6   ******************************************************************************/
7  
8  #include <acpi/acpi.h>
9  #include "accommon.h"
10  #include "acresrc.h"
11  
12  #define _COMPONENT          ACPI_RESOURCES
13  ACPI_MODULE_NAME("rsaddr")
14  
15  /*******************************************************************************
16   *
17   * acpi_rs_convert_address16 - All WORD (16-bit) address resources
18   *
19   ******************************************************************************/
20  struct acpi_rsconvert_info acpi_rs_convert_address16[5] = {
21  	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS16,
22  	 ACPI_RS_SIZE(struct acpi_resource_address16),
23  	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address16)},
24  
25  	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS16,
26  	 sizeof(struct aml_resource_address16),
27  	 0},
28  
29  	/* Resource Type, General Flags, and Type-Specific Flags */
30  
31  	{ACPI_RSC_ADDRESS, 0, 0, 0},
32  
33  	/*
34  	 * These fields are contiguous in both the source and destination:
35  	 * Address Granularity
36  	 * Address Range Minimum
37  	 * Address Range Maximum
38  	 * Address Translation Offset
39  	 * Address Length
40  	 */
41  	{ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.address16.address.granularity),
42  	 AML_OFFSET(address16.granularity),
43  	 5},
44  
45  	/* Optional resource_source (Index and String) */
46  
47  	{ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address16.resource_source),
48  	 0,
49  	 sizeof(struct aml_resource_address16)}
50  };
51  
52  /*******************************************************************************
53   *
54   * acpi_rs_convert_address32 - All DWORD (32-bit) address resources
55   *
56   ******************************************************************************/
57  
58  struct acpi_rsconvert_info acpi_rs_convert_address32[5] = {
59  	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS32,
60  	 ACPI_RS_SIZE(struct acpi_resource_address32),
61  	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address32)},
62  
63  	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS32,
64  	 sizeof(struct aml_resource_address32),
65  	 0},
66  
67  	/* Resource Type, General Flags, and Type-Specific Flags */
68  
69  	{ACPI_RSC_ADDRESS, 0, 0, 0},
70  
71  	/*
72  	 * These fields are contiguous in both the source and destination:
73  	 * Address Granularity
74  	 * Address Range Minimum
75  	 * Address Range Maximum
76  	 * Address Translation Offset
77  	 * Address Length
78  	 */
79  	{ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.address32.address.granularity),
80  	 AML_OFFSET(address32.granularity),
81  	 5},
82  
83  	/* Optional resource_source (Index and String) */
84  
85  	{ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address32.resource_source),
86  	 0,
87  	 sizeof(struct aml_resource_address32)}
88  };
89  
90  /*******************************************************************************
91   *
92   * acpi_rs_convert_address64 - All QWORD (64-bit) address resources
93   *
94   ******************************************************************************/
95  
96  struct acpi_rsconvert_info acpi_rs_convert_address64[5] = {
97  	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS64,
98  	 ACPI_RS_SIZE(struct acpi_resource_address64),
99  	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address64)},
100  
101  	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS64,
102  	 sizeof(struct aml_resource_address64),
103  	 0},
104  
105  	/* Resource Type, General Flags, and Type-Specific Flags */
106  
107  	{ACPI_RSC_ADDRESS, 0, 0, 0},
108  
109  	/*
110  	 * These fields are contiguous in both the source and destination:
111  	 * Address Granularity
112  	 * Address Range Minimum
113  	 * Address Range Maximum
114  	 * Address Translation Offset
115  	 * Address Length
116  	 */
117  	{ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.address64.address.granularity),
118  	 AML_OFFSET(address64.granularity),
119  	 5},
120  
121  	/* Optional resource_source (Index and String) */
122  
123  	{ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address64.resource_source),
124  	 0,
125  	 sizeof(struct aml_resource_address64)}
126  };
127  
128  /*******************************************************************************
129   *
130   * acpi_rs_convert_ext_address64 - All Extended (64-bit) address resources
131   *
132   ******************************************************************************/
133  
134  struct acpi_rsconvert_info acpi_rs_convert_ext_address64[5] = {
135  	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64,
136  	 ACPI_RS_SIZE(struct acpi_resource_extended_address64),
137  	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_ext_address64)},
138  
139  	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64,
140  	 sizeof(struct aml_resource_extended_address64),
141  	 0},
142  
143  	/* Resource Type, General Flags, and Type-Specific Flags */
144  
145  	{ACPI_RSC_ADDRESS, 0, 0, 0},
146  
147  	/* Revision ID */
148  
149  	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.ext_address64.revision_ID),
150  	 AML_OFFSET(ext_address64.revision_ID),
151  	 1},
152  	/*
153  	 * These fields are contiguous in both the source and destination:
154  	 * Address Granularity
155  	 * Address Range Minimum
156  	 * Address Range Maximum
157  	 * Address Translation Offset
158  	 * Address Length
159  	 * Type-Specific Attribute
160  	 */
161  	{ACPI_RSC_MOVE64,
162  	 ACPI_RS_OFFSET(data.ext_address64.address.granularity),
163  	 AML_OFFSET(ext_address64.granularity),
164  	 6}
165  };
166  
167  /*******************************************************************************
168   *
169   * acpi_rs_convert_general_flags - Flags common to all address descriptors
170   *
171   ******************************************************************************/
172  
173  static struct acpi_rsconvert_info acpi_rs_convert_general_flags[6] = {
174  	{ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.flags),
175  	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_general_flags)},
176  
177  	/* Resource Type (Memory, Io, bus_number, etc.) */
178  
179  	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.address.resource_type),
180  	 AML_OFFSET(address.resource_type),
181  	 1},
182  
183  	/* General flags - Consume, Decode, min_fixed, max_fixed */
184  
185  	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.producer_consumer),
186  	 AML_OFFSET(address.flags),
187  	 0},
188  
189  	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.decode),
190  	 AML_OFFSET(address.flags),
191  	 1},
192  
193  	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.min_address_fixed),
194  	 AML_OFFSET(address.flags),
195  	 2},
196  
197  	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.max_address_fixed),
198  	 AML_OFFSET(address.flags),
199  	 3}
200  };
201  
202  /*******************************************************************************
203   *
204   * acpi_rs_convert_mem_flags - Flags common to Memory address descriptors
205   *
206   ******************************************************************************/
207  
208  static struct acpi_rsconvert_info acpi_rs_convert_mem_flags[5] = {
209  	{ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.specific_flags),
210  	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_mem_flags)},
211  
212  	/* Memory-specific flags */
213  
214  	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.write_protect),
215  	 AML_OFFSET(address.specific_flags),
216  	 0},
217  
218  	{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.caching),
219  	 AML_OFFSET(address.specific_flags),
220  	 1},
221  
222  	{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.range_type),
223  	 AML_OFFSET(address.specific_flags),
224  	 3},
225  
226  	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.translation),
227  	 AML_OFFSET(address.specific_flags),
228  	 5}
229  };
230  
231  /*******************************************************************************
232   *
233   * acpi_rs_convert_io_flags - Flags common to I/O address descriptors
234   *
235   ******************************************************************************/
236  
237  static struct acpi_rsconvert_info acpi_rs_convert_io_flags[4] = {
238  	{ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.specific_flags),
239  	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_io_flags)},
240  
241  	/* I/O-specific flags */
242  
243  	{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.io.range_type),
244  	 AML_OFFSET(address.specific_flags),
245  	 0},
246  
247  	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.io.translation),
248  	 AML_OFFSET(address.specific_flags),
249  	 4},
250  
251  	{ACPI_RSC_1BITFLAG,
252  	 ACPI_RS_OFFSET(data.address.info.io.translation_type),
253  	 AML_OFFSET(address.specific_flags),
254  	 5}
255  };
256  
257  /*******************************************************************************
258   *
259   * FUNCTION:    acpi_rs_get_address_common
260   *
261   * PARAMETERS:  resource            - Pointer to the internal resource struct
262   *              aml                 - Pointer to the AML resource descriptor
263   *
264   * RETURN:      TRUE if the resource_type field is OK, FALSE otherwise
265   *
266   * DESCRIPTION: Convert common flag fields from a raw AML resource descriptor
267   *              to an internal resource descriptor
268   *
269   ******************************************************************************/
270  
271  u8
acpi_rs_get_address_common(struct acpi_resource * resource,union aml_resource * aml)272  acpi_rs_get_address_common(struct acpi_resource *resource,
273  			   union aml_resource *aml)
274  {
275  	struct aml_resource_address address;
276  
277  	ACPI_FUNCTION_ENTRY();
278  
279  	/* Avoid undefined behavior: member access within misaligned address */
280  
281  	memcpy(&address, aml, sizeof(address));
282  
283  	/* Validate the Resource Type */
284  
285  	if ((address.resource_type > 2) &&
286  	    (address.resource_type < 0xC0) && (address.resource_type != 0x0A)) {
287  		return (FALSE);
288  	}
289  
290  	/* Get the Resource Type and General Flags */
291  
292  	(void)acpi_rs_convert_aml_to_resource(resource, aml,
293  					      acpi_rs_convert_general_flags);
294  
295  	/* Get the Type-Specific Flags (Memory and I/O descriptors only) */
296  
297  	if (resource->data.address.resource_type == ACPI_MEMORY_RANGE) {
298  		(void)acpi_rs_convert_aml_to_resource(resource, aml,
299  						      acpi_rs_convert_mem_flags);
300  	} else if (resource->data.address.resource_type == ACPI_IO_RANGE) {
301  		(void)acpi_rs_convert_aml_to_resource(resource, aml,
302  						      acpi_rs_convert_io_flags);
303  	} else {
304  		/* Generic resource type, just grab the type_specific byte */
305  
306  		resource->data.address.info.type_specific =
307  		    address.specific_flags;
308  	}
309  
310  	return (TRUE);
311  }
312  
313  /*******************************************************************************
314   *
315   * FUNCTION:    acpi_rs_set_address_common
316   *
317   * PARAMETERS:  aml                 - Pointer to the AML resource descriptor
318   *              resource            - Pointer to the internal resource struct
319   *
320   * RETURN:      None
321   *
322   * DESCRIPTION: Convert common flag fields from a resource descriptor to an
323   *              AML descriptor
324   *
325   ******************************************************************************/
326  
327  void
acpi_rs_set_address_common(union aml_resource * aml,struct acpi_resource * resource)328  acpi_rs_set_address_common(union aml_resource *aml,
329  			   struct acpi_resource *resource)
330  {
331  	ACPI_FUNCTION_ENTRY();
332  
333  	/* Set the Resource Type and General Flags */
334  
335  	(void)acpi_rs_convert_resource_to_aml(resource, aml,
336  					      acpi_rs_convert_general_flags);
337  
338  	/* Set the Type-Specific Flags (Memory and I/O descriptors only) */
339  
340  	if (resource->data.address.resource_type == ACPI_MEMORY_RANGE) {
341  		(void)acpi_rs_convert_resource_to_aml(resource, aml,
342  						      acpi_rs_convert_mem_flags);
343  	} else if (resource->data.address.resource_type == ACPI_IO_RANGE) {
344  		(void)acpi_rs_convert_resource_to_aml(resource, aml,
345  						      acpi_rs_convert_io_flags);
346  	} else {
347  		/* Generic resource type, just copy the type_specific byte */
348  
349  		aml->address.specific_flags =
350  		    resource->data.address.info.type_specific;
351  	}
352  }
353