1/*
2 * Some or all of this work - Copyright (c) 2006 - 2016, Intel Corp.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * Neither the name of Intel Corporation nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29External (_ERR, MethodObj)
30
31/*
32 * Exceptional conditions support
33 */
34
35Name(z063, 63)
36
37// The current number of exceptions handled
38Name(EXC0, 0x0)
39
40// The total number of exceptions handled
41Name(EXC1, 0x0)
42
43// Opcode of the last exception
44Name(EX00, 0x0)
45
46// Name of the last exception
47Name(EX01, "")
48
49// Opcode of the first exception
50Name(EX04, 0x0)
51
52// Name of the first exception
53Name(EX05, "")
54
55
56/*
57 * Undefined opcodes of exception
58 */
59Name(EX0D, 0xfd)
60Name(EX0E, 0xfe)
61
62// Undefined opcode of exception means 'any exceptions'
63Name(EX0F, 0xff)
64
65// Description of all exceptional conditions
66Name(pf00, Package() {
67	//          ix opcodes      names
68	Package() { 0, 0x00000000, "AE_OK"},
69	Package() { 1, 0x00000001, "AE_ERROR"},
70	Package() { 2, 0x00000002, "AE_NO_ACPI_TABLES"},
71	Package() { 3, 0x00000003, "AE_NO_NAMESPACE"},
72	Package() { 4, 0x00000004, "AE_NO_MEMORY"},
73	Package() { 5, 0x00000005, "AE_NOT_FOUND"},
74	Package() { 6, 0x00000006, "AE_NOT_EXIST"},
75	Package() { 7, 0x00000007, "AE_ALREADY_EXISTS"},
76	Package() { 8, 0x00000008, "AE_TYPE"},
77	Package() { 9, 0x00000009, "AE_NULL_OBJECT"},
78	Package() {10, 0x0000000a, "AE_NULL_ENTRY"},
79	Package() {11, 0x0000000b, "AE_BUFFER_OVERFLOW"},
80	Package() {12, 0x0000000c, "AE_STACK_OVERFLOW"},
81	Package() {13, 0x0000000d, "AE_STACK_UNDERFLOW"},
82	Package() {14, 0x0000000e, "AE_NOT_IMPLEMENTED"},
83	Package() {15, 0x0000000f, "AE_VERSION_MISMATCH"}, /* obsolete */
84	Package() {16, 0x0000000f, "AE_SUPPORT"},
85	Package() {17, 0x00000011, "AE_SHARE"}, /* obsolete */
86	Package() {18, 0x00000010, "AE_LIMIT"},
87	Package() {19, 0x00000011, "AE_TIME"},
88	Package() {20, 0x00000014, "AE_UNKNOWN_STATUS"}, /* obsolete */
89	Package() {21, 0x00000012, "AE_ACQUIRE_DEADLOCK"},
90	Package() {22, 0x00000013, "AE_RELEASE_DEADLOCK"},
91	Package() {23, 0x00000014, "AE_NOT_ACQUIRED"},
92	Package() {24, 0x00000015, "AE_ALREADY_ACQUIRED"},
93	Package() {25, 0x00000016, "AE_NO_HARDWARE_RESPONSE"},
94	Package() {26, 0x00000017, "AE_NO_GLOBAL_LOCK"},
95	Package() {27, 0x00000018, "AE_ABORT_METHOD"},
96	Package() {28, 0x00001001, "AE_BAD_PARAMETER"},
97	Package() {29, 0x00001002, "AE_BAD_CHARACTER"},
98	Package() {30, 0x00001003, "AE_BAD_PATHNAME"},
99	Package() {31, 0x00001004, "AE_BAD_DATA"},
100	Package() {32, 0x00001005, "AE_BAD_ADDRESS"}, /* obsolete */
101	Package() {33, 0x00001006, "AE_ALIGNMENT"}, /* obsolete */
102	Package() {34, 0x00001005, "AE_BAD_HEX_CONSTANT"},
103	Package() {35, 0x00001006, "AE_BAD_OCTAL_CONSTANT"},
104	Package() {36, 0x00001007, "AE_BAD_DECIMAL_CONSTANT"},
105	Package() {37, 0x00002001, "AE_BAD_SIGNATURE"},
106	Package() {38, 0x00002002, "AE_BAD_HEADER"},
107	Package() {39, 0x00002003, "AE_BAD_CHECKSUM"},
108	Package() {40, 0x00002004, "AE_BAD_VALUE"},
109	Package() {41, 0x00002005, "AE_TABLE_NOT_SUPPORTED"}, /* obsolete */
110	Package() {42, 0x00002005, "AE_INVALID_TABLE_LENGTH"},
111	Package() {43, 0x00003001, "AE_AML_ERROR"}, /* obsolete */
112	Package() {44, 0x00003002, "AE_AML_PARSE"}, /* obsolete */
113	Package() {45, 0x00003001, "AE_AML_BAD_OPCODE"},
114	Package() {46, 0x00003002, "AE_AML_NO_OPERAND"},
115	Package() {47, 0x00003003, "AE_AML_OPERAND_TYPE"},
116	Package() {48, 0x00003004, "AE_AML_OPERAND_VALUE"},
117	Package() {49, 0x00003005, "AE_AML_UNINITIALIZED_LOCAL"},
118	Package() {50, 0x00003006, "AE_AML_UNINITIALIZED_ARG"},
119	Package() {51, 0x00003007, "AE_AML_UNINITIALIZED_ELEMENT"},
120	Package() {52, 0x00003008, "AE_AML_NUMERIC_OVERFLOW"},
121	Package() {53, 0x00003009, "AE_AML_REGION_LIMIT"},
122	Package() {54, 0x0000300a, "AE_AML_BUFFER_LIMIT"},
123	Package() {55, 0x0000300b, "AE_AML_PACKAGE_LIMIT"},
124	Package() {56, 0x0000300c, "AE_AML_DIVIDE_BY_ZERO"},
125	Package() {57, 0x0000300d, "AE_AML_BAD_NAME"},
126	Package() {58, 0x0000300e, "AE_AML_NAME_NOT_FOUND"},
127	Package() {59, 0x0000300f, "AE_AML_INTERNAL"},
128	Package() {60, 0x00003010, "AE_AML_INVALID_SPACE_ID"},
129	Package() {61, 0x00003011, "AE_AML_STRING_LIMIT"},
130	Package() {62, 0x00003012, "AE_AML_NO_RETURN_VALUE"},
131	Package() {63, 0x00003014, "AE_AML_NOT_OWNER"},
132	Package() {64, 0x00003015, "AE_AML_MUTEX_ORDER"},
133	Package() {65, 0x00003016, "AE_AML_MUTEX_NOT_ACQUIRED"},
134	Package() {66, 0x00003017, "AE_AML_INVALID_RESOURCE_TYPE"},
135	Package() {67, 0x00003018, "AE_AML_INVALID_INDEX"},
136	Package() {68, 0x00003019, "AE_AML_REGISTER_LIMIT"},
137	Package() {69, 0x0000301a, "AE_AML_NO_WHILE"},
138	Package() {70, 0x0000301b, "AE_AML_ALIGNMENT"},
139	Package() {71, 0x0000301c, "AE_AML_NO_RESOURCE_END_TAG"},
140	Package() {72, 0x0000301d, "AE_AML_BAD_RESOURCE_VALUE"},
141	Package() {73, 0x0000301e, "AE_AML_CIRCULAR_REFERENCE"},
142	Package() {74, 0x00004001, "AE_CTRL_RETURN_VALUE"},
143	Package() {75, 0x00004002, "AE_CTRL_PENDING"},
144	Package() {76, 0x00004003, "AE_CTRL_TERMINATE"},
145	Package() {77, 0x00004004, "AE_CTRL_TRUE"},
146	Package() {78, 0x00004005, "AE_CTRL_FALSE"},
147	Package() {79, 0x00004006, "AE_CTRL_DEPTH"},
148	Package() {80, 0x00004007, "AE_CTRL_END"},
149	Package() {81, 0x00004008, "AE_CTRL_TRANSFER"},
150	Package() {82, 0x00004009, "AE_CTRL_BREAK"},
151	Package() {83, 0x0000400a, "AE_CTRL_CONTINUE"},
152
153	/* New additional are here not to touch previous indexes */
154
155	Package() {84, 0x00003013, "AE_AML_METHOD_LIMIT"},
156	Package() {85, 0x0000100B, "AE_INDEX_TO_NOT_ATTACHED"},
157	Package() {86, 0x0000001B, "AE_OWNER_ID_LIMIT"}}
158)
159
160/*
161 * (multi-threading)
162 *
163 * Packages to store per-thread information about exceptions
164 * (used in mt-mode)
165 *
166 * EXC2 - maximal number of exception can be registered
167 * EX02 - package to store ID of thread where exception occurs
168 * EX03 - package to store opcode of exception
169 */
170Name(EXC2, 200)
171Name(EX02, Package(EXC2) {})
172Name(EX03, Package(EXC2) {})
173
174/*
175 * Exceptional conditions handler
176 *
177 * arg0 - AcpiStatus
178 * arg1 - AsciiExceptionString
179 * arg2 - ID of current thread
180 */
181Method(_ERR, 3)
182{
183	Store(arg0, EX00)
184	Store(arg1, EX01)
185
186	if (LEqual(EX04, 0)) {
187		Store(arg0, EX04)
188		Store(arg1, EX05)
189	}
190
191	/* multi-threading */
192	if (MTHR) {
193		/* If the current number of exceptions handled doesn't exceed EXC2 */
194		if (LLess(EXC0, EXC2)) {
195			Store(arg2, Index(EX02, EXC0))
196			Store(arg0, Index(EX03, EXC0))
197		} else {
198			Store("Maximal number of exceptions exceeded", Debug)
199			err("_ERR", z063, 0, 0, 0, EXC0, EXC2)
200		}
201	}
202
203	Increment(EXC0)
204	Increment(EXC1)
205
206//	Store("Run-time exception:", Debug)
207//	Store(arg0, Debug)
208//	Store(arg1, Debug)
209//	Store(arg2, Debug)
210
211	Return (0) // Map error to AE_OK
212}
213
214// Check that exceptions has not arisen at all
215Method(CH02)
216{
217	if (EXC1) {
218		Concatenate("Some unexpected exceptions were handled, 0x", EXC1, Local0)
219		err("CH02", z063, 1, 0, 0, Local0, 0)
220	}
221	Return(EXC1)
222}
223
224/*
225 * Check that the counter of current exceptions is zero. Set it to zero.
226 * arg0 - diagnostic message
227 * arg1 - absolute index of file initiating the checking
228 * arg2 - index of checking
229 * arg3 - arg5 of err, "received value"
230 * arg4 - arg6 of err, "expected value"
231 */
232Method(CH03, 5)
233{
234	Store(0, Local7)
235
236	if (EXC0) {
237		Concatenate("Unexpected exceptions (count ", EXC0, Local0)
238		Concatenate(Local0, "), the last is ", Local1)
239		Concatenate(Local1, EX01, Local0)
240		Concatenate(Local0, ", ", Local1)
241		Concatenate(Local1, EX00, Debug)
242		err(arg0, z063, 2, arg1, arg2, arg3, arg4)
243		Store(EXC0, Local7)
244	}
245	Store(0, EXC0)
246	Store(0, EX04)
247
248	return (Local7)
249}
250
251//
252// Convert 32/64 bit integer to 16-bit Hex value
253//
254Method(ST16, 1, Serialized)
255{
256    Name (EBUF, Buffer(ISZC){}) /* 8 or 16 bytes, depending on 32/64 mode */
257    Name (RBUF, Buffer(4){})
258
259    Store (ToHexString (Arg0), EBUF)
260    Mid (EBUF, Subtract(ISZC, 4), 4, RBUF)
261    Return (Concatenate ("0x", ToString (RBUF)))
262}
263
264/*
265 * Check that exceptions are handled as expected, report errors
266 * (if any) and set the current number of exceptions to zero.
267 *
268 * Verified:
269 * - exception has arisen
270 * - check the number of exceptions
271 * - the last arisen exception matches one described by arguments
272 *
273 * arg0 - diagnostic message
274 * arg1 -
275 *   zero means:
276 *        - check that only one exception has arisen (curent number is equal to 1)
277 *        - check that opcode is equal to that specified by arg2
278 *   non-zero means:
279 *        - check that the number of exception arisen is not less than 1
280 *          (curent number is equal to 1 or greater)
281 *     1:   check that the first opcode is equal to that specified by arg2
282 *     2:   check that the last opcode is equal to that specified by arg2
283 *
284 * arg2 - index of exception info in pf00 Package
285 * arg3 - absolute index of file initiating the checking
286 * arg4 - index of checking
287 * arg5 - arg5 of err, "received value"
288 * arg6 - arg6 of err, "expected value"
289 */
290Method(CH04, 7)
291{
292	Store(0, Local5)
293
294	if (LEqual(arg2, 0xff)) {
295
296	if (LEqual(EXC0, 0)) {
297		Store(1, Local5)
298		Store("ERROR: No ANY exception has arisen.", Debug)
299	}
300
301	} else {
302
303	// Determine opcode and name of the expected exception
304
305	Store(DeRefOf(Index (pf00, arg2)), Local2) // exception info
306	Store(DeRefOf(Index (Local2, 1)), Local3)  // opcode
307	Store(DeRefOf(Index (Local2, 2)), Local4)  // name
308
309	if (LEqual(EXC0, 0)) {
310		Store (1, Local5)
311		Concatenate("No exception - expected: ", Local4, Local0)
312		Concatenate(Local0, "-", Local0)
313		Concatenate(Local0, ST16(Local3), Local0)
314		Store(Local0, Debug)
315	} else {
316		if (LAnd(LNot(arg1), LGreater(EXC0, 1))) {
317			Store(1, Local5)
318			Concatenate("More than one exception: 0x", EXC0, Local0)
319			Store(Local0, Debug)
320		} else {
321			if (LEqual(arg1, 1)) {
322				/* Opcode of the first exception */
323				Store(EX04, Local6)
324				Store(EX05, Local7)
325			} else {
326				/* Opcode of the last exception */
327				Store(EX00, Local6)
328				Store(EX01, Local7)
329			}
330
331			if (LNotEqual(Local3, Local6)) {
332				Store(1, Local5)
333				Concatenate("Exception: ", Local7, Local0)
334
335				Concatenate(Local0, "-", Local0)
336				Concatenate(Local0, ST16(Local6), Local0)
337
338				Concatenate(" differs from expected: ", Local4, Local1)
339				Concatenate(Local0, Local1, Local0)
340
341				Concatenate(Local0, "-", Local0)
342				Concatenate(Local0, ST16(Local3), Local0)
343				Store(Local0, Debug)
344			}
345			if (LNotEqual(Local4, Local7)) {
346				Store(1, Local5)
347				Store("Unexpected exception:", Debug)
348				Store(Concatenate("Expected: ", Local4), Debug)
349				Store(Concatenate("Received: ", Local7), Debug)
350			}
351		}
352	}
353
354	} /* if(LNotEqual(arg2,0xff)) */
355
356	Store(0, EXC0)
357	Store(0, EX04)
358
359	if (Local5) {
360		err(arg0, z063, 3, arg3, arg4, arg5, arg6)
361	}
362
363	return (Local5)
364}
365
366Method(CH05)
367{
368	return (CH03("CH05", 0, 0, 0, 0))
369}
370
371Method(CH06, 3)
372{
373	if (EXCV) {
374		return (CH04(arg0, 0, arg2, 0, arg1, 0, 0))
375	} else {
376		// Just only presence of ANY exception(s)
377		return (CH04(arg0, 0, 0xff, 0, arg1, 0, 0))
378	}
379}
380
381/*
382 * Check for any exception when the slack mode is initiated
383 */
384Method(CH07, 7)
385{
386	if (SLCK) {
387		CH03(arg0, arg3, arg4, arg5, arg6)
388	} else {
389		CH04(arg0, arg1, arg2, arg3, arg4, arg5, arg6)
390	}
391}
392
393
394/* MULTI-THREADING */
395
396/*
397 * Report message of thread
398 * (adds ID of thread and reports the message)
399 *
400 * arg0 - ID of current thread
401 * arg1 - string
402 */
403Method(MSG0, 2)
404{
405	Concatenate("THREAD ID ", arg0, Local0)
406	Concatenate(Local0, ": ", Local1)
407	Concatenate(Local1, arg1, Local0)
408	Store(Local0, Debug)
409}
410
411/*
412 * Used in multi-threading mode
413 *
414 * Return the first encountered exception corresponding to this Thread ID
415 * and the total number of exceptions corresponding to this Thread ID.
416 * Reset all the entries corresponding to the thread identified by arg0.
417 *
418 * Note: this method is used in mt-mode (by several threads simultaneously)
419 *       but each of threads changes only its elements of EX02.
420 *
421 * arg0 - ID of current thread
422 */
423Method(MTEX, 1)
424{
425	Store(Package(2) {0,0}, Local2) // Package to be returned
426	Store(0, Local3) // found
427
428	Store(EXC0, Local4) // lpN0
429	Store(0, Local5)    // lpC0
430	While (Local4) {
431
432		Store(DeRefOf(Index(EX02, Local5)), Local0)
433
434		/* Matching ID of current thread */
435		if (LEqual(Local0, arg0)) {
436			Store(DeRefOf(Index(EX03, Local5)), Local1)
437			if (LEqual(Local3, 0)) {
438				/* Opcode of the first exception */
439				Store(Local1, Index(Local2, 0))
440			}
441			Increment(Local3)
442
443			/* Reset information about this exception */
444			Store(0, Index(EX02, Local5))
445		}
446
447		Decrement(Local4)
448		Increment(Local5)
449	}
450	Store(Local3, Index(Local2, 1))
451
452	return (Local2)
453}
454
455/*
456 * The same as CH03, but to be used in multi-threading mode
457 *
458 * arg0 - diagnostic message
459 * arg1 - ID of current thread
460 * arg2 - absolute index of file initiating the checking
461 * arg3 - index of checking
462 * arg4 - arg5 of err, "received value"
463 * arg5 - arg6 of err, "expected value"
464 *
465 * Return: current number of exceptions occur on this thread
466 */
467Method(CH08, 6)
468{
469	Store(MTEX(arg1), Local2)
470	Store(DeRefOf(Index(Local2, 0)), Local3) // opcode of the first exception
471	Store(DeRefOf(Index(Local2, 1)), Local4) // number of exceptions
472
473	Store(0, Local7)
474
475	if (Local4) {
476		Concatenate("Unexpected exception 0x", Local3, Local0)
477		Concatenate(Local0, ", number of exceptions 0x", Local1)
478		Concatenate(Local1, Local4, Local0)
479		MSG0(arg1, Local0)
480		err(arg0, z063, 4, arg2, arg3, arg4, arg5)
481		Store(1, Local7)
482	}
483
484	/*
485	 * Reset of EXC0 should be done by Control thread
486	 * Store(0, EXC0)
487	 */
488
489	return (Local4)
490}
491
492/*
493 * The same as CH04, but to be used in multi-threading mode
494 *
495 * arg0 - non-zero means to treat "More than one exceptions" as error
496 * arg1 - ID of current thread
497 * arg2 - index of exception info in pf00 Package
498 * arg3 - absolute index of file initiating the checking
499 * arg4 - index of checking
500 * arg5 - RefOf to Integer to return 'current number of exceptions occur on this thread'
501 *
502 * Return: non-zero when errors detected
503 */
504Method(CH09, 6)
505{
506	Store(MTEX(arg1), Local7)
507	Store(DeRefOf(Index(Local7, 0)), Local6) // opcode of the first exception
508	Store(DeRefOf(Index(Local7, 1)), Local7) // number of exceptions
509
510	Store(0, Local5)
511
512	if (LEqual(arg2, 0xff)) {
513		if (LEqual(Local7, 0)) {
514			/* No exceptions */
515			Store(1, Local5)
516			MSG0(arg1, "ERROR: No ANY exception has arisen.")
517		}
518	} else {
519
520	// Determine opcode and name of the expected exception
521
522	Store(DeRefOf(Index (pf00, arg2)), Local2) // exception info
523	Store(DeRefOf(Index (Local2, 1)), Local3)  // opcode
524	Store(DeRefOf(Index (Local2, 2)), Local4)  // name
525
526	if (LEqual(Local7, 0)) {
527		/* No exceptions */
528		Store (1, Local5)
529		Concatenate("No exception has arisen, expected: ", Local4, Local0)
530		Concatenate(", opcode 0x", Local3, Local1)
531		Concatenate(Local0, Local1, Local0)
532		MSG0(arg1, Local0)
533	} else {
534		if (LAnd(arg0, LGreater(Local7, 1))) {
535			Store(1, Local5)
536			Concatenate("More than one exception has arisen: 0x", Local7, Local0)
537			MSG0(arg1, Local0)
538		} else {
539
540			/* Opcode of the first exception */
541
542			if (LNotEqual(Local3, Local6)) {
543				Store(1, Local5)
544				Concatenate("The exception 0x", Local6, Local0)
545				Concatenate(Local0, " differs from expected ", Local1)
546				Concatenate(Local1, ST16 (Local3), Local0)
547				MSG0(arg1, Local0)
548			}
549		}
550	}
551
552	} /* if(LNotEqual(arg2,0xff)) */
553
554	/*
555	 * Reset of EXC0 should be done by Control thread
556	 * Store(0, EXC0)
557	 */
558
559	if (Local5) {
560		err("", z063, 5, arg3, arg4, 0, 0)
561	}
562
563	Store(Local7, arg5)
564
565	return (Local5)
566}
567
568/*
569 * Reset EXC0 (the current number of exceptions handled)
570 *
571 * It should be invoked by the Control thread.
572 */
573Method(CH0A)
574{
575	Store(0, EXC0)
576}
577