ReactOS 0.4.17-dev-1190-g4c812f4
interpreter.c
Go to the documentation of this file.
11#include <uacpi/kernel_api.h>
14#include <uacpi/internal/io.h>
19#include <uacpi/internal/osi.h>
20
21#ifndef UACPI_BAREBONES_MODE
22
30};
31
35};
36
37struct item {
39 union {
46 };
47};
48
49DYNAMIC_ARRAY_WITH_INLINE_STORAGE(item_array, struct item, 8)
51
55
56 /*
57 * == 0 -> none
58 * >= 1 -> item[idx - 1]
59 */
61
63
64 const struct uacpi_op_spec *op;
65 struct item_array items;
66};
67
68DYNAMIC_ARRAY_WITH_INLINE_STORAGE(op_context_array, struct op_context, 8)
70 op_context_array, struct op_context, static
71)
72
73static struct op_context *op_context_array_one_before_last(
74 struct op_context_array *arr
75)
76{
78
79 size = op_context_array_size(arr);
80
81 if (size < 2)
82 return UACPI_NULL;
83
84 return op_context_array_at(arr, size - 2);
85}
86
92};
93
94struct code_block {
97 union {
100 };
101};
102
103DYNAMIC_ARRAY_WITH_INLINE_STORAGE(code_block_array, struct code_block, 8)
105 code_block_array, struct code_block, static
106)
107
108DYNAMIC_ARRAY_WITH_INLINE_STORAGE(held_mutexes_array, uacpi_mutex*, 8)
110 held_mutexes_array, uacpi_mutex*, static
111)
112
113static uacpi_status held_mutexes_array_push(
114 struct held_mutexes_array *arr, uacpi_mutex *mutex
115)
116{
118
119 slot = held_mutexes_array_alloc(arr);
122
123 *slot = mutex;
125 return UACPI_STATUS_OK;
126}
127
129 struct held_mutexes_array *arr, uacpi_size i
130)
131{
133
134 size = held_mutexes_array_inline_capacity(arr);
135
136 // Only the dynamic array part is affected
137 if (i >= size) {
138 i -= size;
139 size = arr->size_including_inline - size;
140 size -= i + 1;
141
143 &arr->dynamic_storage[i], &arr->dynamic_storage[i + 1],
144 size * sizeof(arr->inline_storage[0])
145 );
146
147 held_mutexes_array_pop(arr);
148 return;
149 }
150
151 size = UACPI_MIN(held_mutexes_array_inline_capacity(arr),
152 arr->size_including_inline);
153 size -= i + 1;
155 &arr->inline_storage[i], &arr->inline_storage[i + 1],
156 size * sizeof(arr->inline_storage[0])
157 );
158
159 size = held_mutexes_array_size(arr);
160 i = held_mutexes_array_inline_capacity(arr);
161
162 /*
163 * This array has dynamic storage as well, now we have to take the first
164 * dynamic item, move it to the top of inline storage, and then shift all
165 * dynamic items backward by 1 as well.
166 */
167 if (size > i) {
168 arr->inline_storage[i - 1] = arr->dynamic_storage[0];
169 size -= i + 1;
170
172 &arr->dynamic_storage[0], &arr->dynamic_storage[1],
173 size * sizeof(arr->inline_storage[0])
174 );
175 }
176
177 held_mutexes_array_pop(arr);
178}
179
183};
184
186 struct held_mutexes_array *arr, uacpi_mutex *mutex,
188)
189{
192
193 if (uacpi_unlikely(held_mutexes_array_size(arr) == 0))
195
196 item = *held_mutexes_array_last(arr);
197
198 if (uacpi_unlikely(item->sync_level != mutex->sync_level &&
201 "ignoring mutex @%p release due to sync level mismatch: %d vs %d",
202 mutex, mutex->sync_level, item->sync_level
203 );
204
205 // We still return OK because we don't want to abort because of this
206 return UACPI_STATUS_OK;
207 }
208
209 if (mutex->depth > 1 && force == FORCE_RELEASE_NO) {
211 return UACPI_STATUS_OK;
212 }
213
214 // Fast path for well-behaved AML that releases mutexes in descending order
215 if (uacpi_likely(item == mutex)) {
216 held_mutexes_array_pop(arr);
217 goto do_release;
218 }
219
220 /*
221 * The mutex being released is not the last one acquired, although we did
222 * verify that at least it has the same sync level. Anyway, now we have
223 * to search for it and then remove it from the array while shifting
224 * everything backwards.
225 */
226 i = held_mutexes_array_size(arr);
227 for (;;) {
228 item = *held_mutexes_array_at(arr, --i);
229 if (item == mutex)
230 break;
231
232 if (uacpi_unlikely(i == 0))
234 }
235
237
238do_release:
239 // This is either a force release, or depth was already 1 to begin with
240 mutex->depth = 1;
242
244 return UACPI_STATUS_OK;
245}
246
248 temp_namespace_node_array, uacpi_namespace_node*, 8)
250 temp_namespace_node_array, uacpi_namespace_node*, static
251)
252
253static uacpi_status temp_namespace_node_array_push(
254 struct temp_namespace_node_array *arr, uacpi_namespace_node *node
255)
256{
258
259 slot = temp_namespace_node_array_alloc(arr);
262
263 *slot = node;
264 return UACPI_STATUS_OK;
265}
266
269
272
273 struct op_context_array pending_ops;
274 struct code_block_array code_blocks;
275 struct temp_namespace_node_array temp_nodes;
276
277 // 0 -> none, N -> N - 1
279
282
284
286
287 // Only used if the method is serialized
289};
290
291static void *call_frame_cursor(struct call_frame *frame)
292{
293 return frame->method->code + frame->code_offset;
294}
295
297{
298 return frame->method->size - frame->code_offset;
299}
300
302{
303 return call_frame_code_bytes_left(frame) > 0;
304}
305
306DYNAMIC_ARRAY_WITH_INLINE_STORAGE(call_frame_array, struct call_frame, 4)
308 call_frame_array, struct call_frame, static
309)
310
311static struct call_frame *call_frame_array_one_before_last(
312 struct call_frame_array *arr
313)
314{
316
317 size = call_frame_array_size(arr);
318
319 if (size < 2)
320 return UACPI_NULL;
321
322 return call_frame_array_at(arr, size - 2);
323}
324
325// NOTE: Try to keep size under 2 pages
328 struct call_frame_array call_stack;
329 struct held_mutexes_array held_mutexes;
330
333 const struct uacpi_op_spec *cur_op;
336
338};
339
340#define AML_READ(ptr, offset) (*(((uacpi_u8*)(ptr)) + offset))
341
343 uacpi_object_name *out_name)
344{
347
348 uacpi_memcpy(&out_name->id, cursor, 4);
349 return UACPI_STATUS_OK;
350}
351
352/*
353 * -------------------------------------------------------------
354 * RootChar := ‘\’
355 * ParentPrefixChar := ‘^’
356 * ‘\’ := 0x5C
357 * ‘^’ := 0x5E
358 * ------------------------------------------------------------
359 * NameSeg := <leadnamechar namechar namechar namechar>
360 * NameString := <rootchar namepath> | <prefixpath namepath>
361 * PrefixPath := Nothing | <’^’ prefixpath>
362 * NamePath := NameSeg | DualNamePath | MultiNamePath | NullName
363 * DualNamePath := DualNamePrefix NameSeg NameSeg
364 * MultiNamePath := MultiNamePrefix SegCount NameSeg(SegCount)
365 */
366
368 struct call_frame *frame, uacpi_size offset,
369 uacpi_char **out_string, uacpi_size *out_size
370)
371{
372 uacpi_size bytes_left, prefix_bytes, nameseg_bytes = 0, namesegs;
373 uacpi_char *base_cursor, *cursor;
374 uacpi_char prev_char;
375
376 bytes_left = frame->method->size - offset;
377 cursor = (uacpi_char*)frame->method->code + offset;
378 base_cursor = cursor;
379 namesegs = 0;
380
381 prefix_bytes = 0;
382 for (;;) {
383 if (uacpi_unlikely(bytes_left == 0))
385
386 prev_char = *cursor;
387
388 switch (prev_char) {
389 case '^':
390 case '\\':
391 prefix_bytes++;
392 cursor++;
393 bytes_left--;
394 break;
395 default:
396 break;
397 }
398
399 if (prev_char != '^')
400 break;
401 }
402
403 // At least a NullName byte is expected here
404 if (uacpi_unlikely(bytes_left == 0))
406
407 namesegs = 0;
408 bytes_left--;
409 switch (*cursor++)
410 {
412 namesegs = 2;
413 break;
415 if (uacpi_unlikely(bytes_left == 0))
417
418 namesegs = *(uacpi_u8*)cursor;
419 if (uacpi_unlikely(namesegs == 0)) {
420 uacpi_error("MultiNamePrefix but SegCount is 0");
422 }
423
424 cursor++;
425 bytes_left--;
426 break;
427 case UACPI_NULL_NAME:
428 break;
429 default:
430 /*
431 * Might be an invalid byte, but assume single nameseg for now,
432 * the code below will validate it for us.
433 */
434 cursor--;
435 bytes_left++;
436 namesegs = 1;
437 break;
438 }
439
440 if (uacpi_unlikely((namesegs * 4) > bytes_left))
442
443 if (namesegs) {
444 // 4 chars per nameseg
445 nameseg_bytes = namesegs * 4;
446
447 // dot separator for every nameseg
448 nameseg_bytes += namesegs - 1;
449 }
450
451 *out_size = nameseg_bytes + prefix_bytes + 1;
452
453 *out_string = uacpi_kernel_alloc(*out_size);
454 if (*out_string == UACPI_NULL)
456
457 uacpi_memcpy(*out_string, base_cursor, prefix_bytes);
458
459 base_cursor = *out_string;
460 base_cursor += prefix_bytes;
461
462 while (namesegs-- > 0) {
463 uacpi_memcpy(base_cursor, cursor, 4);
464 cursor += 4;
465 base_cursor += 4;
466
467 if (namesegs)
468 *base_cursor++ = '.';
469 }
470
471 *base_cursor = '\0';
472 return UACPI_STATUS_OK;
473}
474
478};
479
481 struct call_frame *frame,
482 enum resolve_behavior behavior,
483 struct uacpi_namespace_node **out_node
484)
485{
488 uacpi_size bytes_left, namesegs = 0;
489 struct uacpi_namespace_node *parent, *cur_node = frame->cur_scope;
490 uacpi_char prev_char = 0;
491 uacpi_bool just_one_nameseg = UACPI_TRUE;
492
493 bytes_left = call_frame_code_bytes_left(frame);
494 cursor = call_frame_cursor(frame);
495
496 for (;;) {
497 if (uacpi_unlikely(bytes_left == 0))
499
500 switch (*cursor) {
501 case '\\':
502 if (prev_char == '^')
504
505 cur_node = uacpi_namespace_root();
506 break;
507 case '^':
508 // Tried to go behind root
509 if (uacpi_unlikely(cur_node == uacpi_namespace_root()))
511
512 cur_node = cur_node->parent;
513 break;
514 default:
515 break;
516 }
517
518 prev_char = *cursor;
519
520 switch (prev_char) {
521 case '^':
522 case '\\':
523 just_one_nameseg = UACPI_FALSE;
524 cursor++;
525 bytes_left--;
526 break;
527 default:
528 break;
529 }
530
531 if (prev_char != '^')
532 break;
533 }
534
535 // At least a NullName byte is expected here
536 if (uacpi_unlikely(bytes_left == 0))
538
539 bytes_left--;
540 switch (*cursor++)
541 {
543 namesegs = 2;
544 just_one_nameseg = UACPI_FALSE;
545 break;
547 if (uacpi_unlikely(bytes_left == 0))
549
550 namesegs = *cursor;
551 if (uacpi_unlikely(namesegs == 0)) {
552 uacpi_error("MultiNamePrefix but SegCount is 0");
554 }
555
556 cursor++;
557 bytes_left--;
558 just_one_nameseg = UACPI_FALSE;
559 break;
560 case UACPI_NULL_NAME:
562 just_one_nameseg)
564
565 goto out;
566 default:
567 /*
568 * Might be an invalid byte, but assume single nameseg for now,
569 * the code below will validate it for us.
570 */
571 cursor--;
572 bytes_left++;
573 namesegs = 1;
574 break;
575 }
576
577 if (uacpi_unlikely((namesegs * 4) > bytes_left))
579
580 for (; namesegs; cursor += 4, namesegs--) {
582
585 return ret;
586
587 parent = cur_node;
589
590 switch (behavior) {
592 if (namesegs == 1) {
593 if (cur_node) {
594 cur_node = UACPI_NULL;
596 goto out;
597 }
598
599 // Create the node and link to parent but don't install YET
601 if (uacpi_unlikely(cur_node == UACPI_NULL)) {
603 goto out;
604 }
605
606 cur_node->parent = parent;
607 }
608 break;
610 if (just_one_nameseg) {
611 while (!cur_node && parent != uacpi_namespace_root()) {
612 cur_node = parent;
613 parent = cur_node->parent;
614
616 }
617 }
618 break;
619 default:
621 }
622
623 if (cur_node == UACPI_NULL) {
625 break;
626 }
627 }
628
629out:
630 cursor += namesegs * 4;
631 frame->code_offset = cursor - frame->method->code;
632
634 uacpi_shareable_ref(cur_node);
635
636 *out_node = cur_node;
637 return ret;
638}
639
641 struct item *item)
642{
644
647 return ret;
648
649 if (!frame->method->named_objects_persist)
650 ret = temp_namespace_node_array_push(&frame->temp_nodes, item->node);
651
654
655 return ret;
656}
657
658static uacpi_u8 peek_next_op(struct call_frame *frame, uacpi_aml_op *out_op)
659{
661 uacpi_size bytes_left;
662 uacpi_u8 length = 0;
664 struct code_block *block;
665
666 block = code_block_array_last(&frame->code_blocks);
667 bytes_left = block->end - frame->code_offset;
668 if (bytes_left == 0)
669 return 0;
670
671 cursor = call_frame_cursor(frame);
672
673 op = AML_READ(cursor, length++);
674 if (op == UACPI_EXT_PREFIX) {
675 if (uacpi_unlikely(bytes_left < 2))
676 return 0;
677
678 op <<= 8;
679 op |= AML_READ(cursor, length++);
680 }
681
682 *out_op = op;
683 return length;
684}
685
686static inline bool op_is_internal(const struct uacpi_op_spec *op)
687{
688 return (op->properties & UACPI_OP_PROPERTY_INTERNAL) != 0;
689}
690
691static inline bool op_is_invalid(const struct uacpi_op_spec *op)
692{
693 return (op->properties & UACPI_OP_PROPERTY_INVALID) != 0;
694}
695
697{
700
701 length = peek_next_op(ctx->cur_frame, &op);
702 if (uacpi_unlikely(length == 0))
704
705 ctx->cur_op = uacpi_get_op_spec(op);
706 if (uacpi_unlikely(op_is_internal(ctx->cur_op) ||
707 op_is_invalid(ctx->cur_op))) {
709 "invalid opcode '%s' (0x%04X) at AML offset %u",
710 ctx->cur_op->name, op, ctx->cur_frame->code_offset
711 );
713 }
714
715 ctx->cur_frame->code_offset += length;
716 g_uacpi_rt_ctx.opcodes_executed++;
717
718 return UACPI_STATUS_OK;
719}
720
722{
723 struct package_length *pkg;
724 uacpi_u8 *src;
725 uacpi_object *dst, *declared_size;
726 uacpi_u32 buffer_size, init_size, aml_offset;
727 struct op_context *op_ctx = ctx->cur_op_ctx;
728
729 aml_offset = item_array_at(&op_ctx->items, 2)->immediate;
730 src = ctx->cur_frame->method->code;
731 src += aml_offset;
732
733 pkg = &item_array_at(&op_ctx->items, 0)->pkg;
734 init_size = pkg->end - aml_offset;
735
736 // TODO: do package bounds checking at parse time
737 if (uacpi_unlikely(pkg->end > ctx->cur_frame->method->size))
739
740 declared_size = item_array_at(&op_ctx->items, 1)->obj;
741
742 if (uacpi_unlikely(declared_size->integer > 0xE0000000)) {
744 "buffer is too large (%"UACPI_PRIu64"), assuming corrupted "
745 "bytestream", UACPI_FMT64(declared_size->integer)
746 );
748 }
749
750 buffer_size = declared_size->integer;
751 if (uacpi_unlikely(init_size > buffer_size)) {
753 "too many buffer initializers: %u (size is %u)",
754 init_size, buffer_size
755 );
757 }
758
759 /*
760 * NT allows empty buffers, these still get a byte of storage, same as the
761 * ones made by make_null_buffer().
762 */
763 dst = item_array_at(&op_ctx->items, 3)->obj;
764 dst->buffer->data = uacpi_kernel_alloc(UACPI_MAX(buffer_size, 1));
765 if (uacpi_unlikely(dst->buffer->data == UACPI_NULL))
767 dst->buffer->size = buffer_size;
768
769 uacpi_memcpy_zerout(dst->buffer->data, src, buffer_size, init_size);
770 return UACPI_STATUS_OK;
771}
772
774{
775 struct call_frame *frame = ctx->cur_frame;
777
779 uacpi_size length, max_bytes;
780
781 obj = item_array_last(&ctx->cur_op_ctx->items)->obj;
782 string = call_frame_cursor(frame);
783
784 // TODO: sanitize string for valid UTF-8
785 max_bytes = call_frame_code_bytes_left(frame);
786 length = uacpi_strnlen(string, max_bytes);
787
788 if (uacpi_unlikely((length == max_bytes) || (string[length++] != 0x00)))
790
791 obj->buffer->text = uacpi_kernel_alloc(length);
792 if (uacpi_unlikely(obj->buffer->text == UACPI_NULL))
794
795 uacpi_memcpy(obj->buffer->text, string, length);
796 obj->buffer->size = length;
797 frame->code_offset += length;
798 return UACPI_STATUS_OK;
799}
800
802{
803 struct op_context *op_ctx = ctx->cur_op_ctx;
804 uacpi_package *package;
805 uacpi_u32 num_elements, num_defined_elements, i;
806
807 /*
808 * Layout of items here:
809 * [0] -> Package length, not interesting
810 * [1] -> Immediate or integer object, depending on PackageOp/VarPackageOp
811 * [2..N-2] -> AML pc+Package element pairs
812 * [N-1] -> The resulting package object that we're constructing
813 */
814 package = item_array_last(&op_ctx->items)->obj->package;
815
816 // 1. Detect how many elements we have, do sanity checking
817 if (op_ctx->op->code == UACPI_AML_OP_VarPackageOp) {
818 uacpi_object *var_num_elements;
819
820 var_num_elements = item_array_at(&op_ctx->items, 1)->obj;
821 if (uacpi_unlikely(var_num_elements->integer > 0xE0000000)) {
823 "package is too large (%"UACPI_PRIu64"), assuming "
824 "corrupted bytestream", UACPI_FMT64(var_num_elements->integer)
825 );
827 }
828 num_elements = var_num_elements->integer;
829 } else {
830 num_elements = item_array_at(&op_ctx->items, 1)->immediate;
831 }
832
833 num_defined_elements = (item_array_size(&op_ctx->items) - 3) / 2;
834 if (uacpi_unlikely(num_defined_elements > num_elements)) {
836 "too many package initializers: %u, truncating to %u",
837 num_defined_elements, num_elements
838 );
839
840 num_defined_elements = num_elements;
841 }
842
843 // 2. Create every object in the package, start as uninitialized
844 if (uacpi_unlikely(!uacpi_package_fill(package, num_elements,
847
848 // 3. Go through every defined object and copy it into the package
849 for (i = 0; i < num_defined_elements; ++i) {
850 uacpi_size base_pkg_index;
852 struct item *item;
854
855 base_pkg_index = (i * 2) + 2;
856 item = item_array_at(&op_ctx->items, base_pkg_index + 1);
857 obj = item->obj;
858
859 if (obj != UACPI_NULL && obj->type == UACPI_OBJECT_REFERENCE) {
860 /*
861 * For named objects we don't actually need the object itself, but
862 * simply the path to it. Often times objects referenced by the
863 * package are not defined until later so it's not possible to
864 * resolve them. For uniformity and to follow the behavior of NT,
865 * simply convert the name string to a path string object to be
866 * resolved later when actually needed.
867 */
868 if (obj->flags == UACPI_REFERENCE_KIND_NAMED) {
871 obj = UACPI_NULL;
872 } else {
874 }
875 }
876
877 if (obj == UACPI_NULL) {
880
884
886 ctx->cur_frame,
887 item_array_at(&op_ctx->items, base_pkg_index)->immediate,
888 &path, &length
889 );
892 return ret;
893 }
894
896 obj->buffer->text = path;
897 obj->buffer->size = length;
898
899 item->obj = obj;
901 }
902
903 ret = uacpi_object_assign(package->objects[i], obj,
906 return ret;
907 }
908
909 return UACPI_STATUS_OK;
910}
911
913{
914 return g_uacpi_rt_ctx.is_rev1 ? 4 : 8;
915}
916
918 uacpi_object *obj, uacpi_data_view *out_buf, uacpi_bool include_null
919)
920{
921 switch (obj->type) {
923 out_buf->length = sizeof_int();
924 out_buf->data = &obj->integer;
925 break;
927 out_buf->length = obj->buffer->size;
928 if (out_buf->length && !include_null)
929 out_buf->length--;
930
931 out_buf->text = obj->buffer->text;
932 break;
934 if (obj->buffer->size == 0) {
935 out_buf->bytes = UACPI_NULL;
936 out_buf->length = 0;
937 break;
938 }
939
940 out_buf->length = obj->buffer->size;
941 out_buf->bytes = obj->buffer->data;
942 break;
945 default:
947 }
948
949 return UACPI_STATUS_OK;
950}
951
953{
954 uacpi_u8 *out_cursor;
955
956 out_cursor = buf_idx->buffer->data;
957 out_cursor += buf_idx->idx;
958
959 return out_cursor;
960}
961
963 uacpi_data_view *src_buf)
964{
966 1, src_buf->length);
967}
968
969/*
970 * NT stores a String or a Buffer to a field one field-sized chunk at a time,
971 * see uacpi_write_field_unit_in_chunks(). For anything that's plain memory
972 * only the last chunk makes a difference, and an empty source doesn't change
973 * it at all. Returns whether there's anything left to write.
974 */
977)
978{
980
981 // Nothing to write to an empty buffer field, or from an empty source
982 if (chunk_size == 0 || buf->length == 0)
983 return UACPI_FALSE;
984 if (src->type == UACPI_OBJECT_INTEGER)
985 return UACPI_TRUE;
986
987 offset = (buf->length - 1) / chunk_size * chunk_size;
988 buf->bytes += offset;
989 buf->length -= offset;
990 return UACPI_TRUE;
991}
992
995 uacpi_data_view *wtr_response
996)
997{
998 // An Integer is always written in one go
999 if (src->type == UACPI_OBJECT_INTEGER)
1001 field, buf->bytes, buf->length, wtr_response
1002 );
1003
1005 field, buf->bytes, buf->length, wtr_response
1006 );
1007}
1008
1009/*
1010 * The word "implicit cast" here is only because it's called that in
1011 * the specification. In reality, we just copy one buffer to another
1012 * because that's what NT does.
1013 */
1016)
1017{
1019 uacpi_data_view src_buf;
1020
1021 ret = get_object_storage(src, &src_buf, UACPI_FALSE);
1023 goto out_bad_cast;
1024
1025 switch (dst->type) {
1028 case UACPI_OBJECT_BUFFER: {
1029 uacpi_data_view dst_buf;
1030
1031 ret = get_object_storage(dst, &dst_buf, UACPI_FALSE);
1033 goto out_bad_cast;
1034
1036 dst_buf.bytes, src_buf.bytes, dst_buf.length, src_buf.length
1037 );
1038 break;
1039 }
1040
1042 uacpi_size chunk_size;
1043
1044 chunk_size = uacpi_round_up_bits_to_bytes(
1045 dst->buffer_field.bit_length
1046 );
1047 if (!trim_to_last_chunk(src, &src_buf, chunk_size))
1048 break;
1049
1051 &dst->buffer_field, src_buf.bytes, src_buf.length
1052 );
1053 break;
1054 }
1055
1057 /*
1058 * The namespace is unlocked for as long as the address space handler
1059 * is running, which makes it possible for someone else to get rid of
1060 * the object that we're writing from, e.g. by overwriting it via
1061 * CopyObject. All of the references that we have to it are gone if
1062 * that happens, so take one that is ours alone.
1063 */
1066 dst->field_unit, src, &src_buf, wtr_response
1067 );
1069 return ret;
1070
1072 if (!trim_to_last_chunk(src, &src_buf, 1))
1073 break;
1074
1075 write_buffer_index(&dst->buffer_index, &src_buf);
1076 break;
1077
1078 default:
1080 goto out_bad_cast;
1081 }
1082
1083 return ret;
1084
1085out_bad_cast:
1087 "attempted to perform an invalid implicit cast (%s -> %s)",
1090 );
1091 return ret;
1092}
1093
1097};
1098
1100 struct execution_context *ctx,
1102)
1103{
1104 uacpi_object **src;
1105 struct item *dst;
1106 enum uacpi_reference_kind kind;
1107
1108 if (type == ARGX) {
1109 src = &ctx->cur_frame->args[idx];
1111 } else {
1112 src = &ctx->cur_frame->locals[idx];
1114 }
1115
1116 if (*src == UACPI_NULL) {
1117 uacpi_object *default_value;
1118
1120 if (uacpi_unlikely(default_value == UACPI_NULL))
1122
1123 *src = uacpi_create_internal_reference(kind, default_value);
1124 if (uacpi_unlikely(*src == UACPI_NULL))
1126
1127 uacpi_object_unref(default_value);
1128 }
1129
1130 dst = item_array_last(&ctx->cur_op_ctx->items);
1131 dst->obj = *src;
1132 dst->type = ITEM_OBJECT;
1133 uacpi_object_ref(dst->obj);
1134
1135 return UACPI_STATUS_OK;
1136}
1137
1139{
1141 struct op_context *op_ctx = ctx->cur_op_ctx;
1142
1143 idx = op_ctx->op->code - UACPI_AML_OP_Local0Op;
1145}
1146
1148{
1150 struct op_context *op_ctx = ctx->cur_op_ctx;
1151
1152 idx = op_ctx->op->code - UACPI_AML_OP_Arg0Op;
1153 return handle_arg_or_local(ctx, idx, ARGX);
1154}
1155
1157{
1158 struct uacpi_namespace_node *src;
1159 struct item *dst;
1160
1161 src = item_array_at(&ctx->cur_op_ctx->items, 0)->node;
1162 dst = item_array_at(&ctx->cur_op_ctx->items, 1);
1163
1164 dst->obj = src->object;
1165 dst->type = ITEM_OBJECT;
1166 uacpi_object_ref(dst->obj);
1167
1168 return UACPI_STATUS_OK;
1169}
1170
1172{
1174
1175 src = item_array_at(&ctx->cur_op_ctx->items, 0)->node;
1176 dst = item_array_at(&ctx->cur_op_ctx->items, 1)->node;
1177
1178 dst->object = src->object;
1180 uacpi_object_ref(dst->object);
1181
1182 return UACPI_STATUS_OK;
1183}
1184
1186{
1189 uacpi_operation_region *op_region;
1190 uacpi_u64 region_end;
1191
1192 node = item_array_at(&ctx->cur_op_ctx->items, 0)->node;
1193 obj = item_array_at(&ctx->cur_op_ctx->items, 4)->obj;
1194 op_region = obj->op_region;
1195
1196 op_region->space = item_array_at(&ctx->cur_op_ctx->items, 1)->immediate;
1197 op_region->offset = item_array_at(&ctx->cur_op_ctx->items, 2)->obj->integer;
1198 op_region->length = item_array_at(&ctx->cur_op_ctx->items, 3)->obj->integer;
1199 region_end = op_region->offset + op_region->length;
1200
1201 if (uacpi_unlikely(op_region->length == 0)) {
1202 // Don't abort here, as long as it's never accessed we don't care
1203 uacpi_warn("unusable/empty operation region %.4s", node->name.text);
1204 } else if (uacpi_unlikely(op_region->offset > region_end)) {
1206 "invalid operation region %.4s bounds: offset=0x%"UACPI_PRIX64
1207 " length=0x%"UACPI_PRIX64"", node->name.text,
1208 UACPI_FMT64(op_region->offset), UACPI_FMT64(op_region->length)
1209 );
1211 }
1212
1213 if (op_region->space == UACPI_ADDRESS_SPACE_PCC && op_region->offset > 255) {
1214 uacpi_warn(
1215 "invalid PCC operation region %.4s subspace %"UACPI_PRIX64,
1216 node->name.text, UACPI_FMT64(op_region->offset)
1217 );
1218 }
1219
1222 );
1223 if (uacpi_unlikely(node->object == UACPI_NULL))
1225
1227 return UACPI_STATUS_OK;
1228}
1229
1231 const uacpi_char *opcode, const uacpi_char *arg,
1233)
1234{
1235 uacpi_error("%s: invalid %s '%s'", opcode, arg, str->text);
1237}
1238
1240 const uacpi_char *opcode, struct uacpi_table_identifiers *id,
1242)
1243{
1245 "%s: unable to find table '%.4s' (OEM ID '%.6s', "
1246 "OEM Table ID '%.8s'): %s",
1247 opcode, id->signature.text, id->oemid, id->oem_table_id,
1249 );
1250}
1251
1253 const uacpi_char *opcode,
1254 struct uacpi_table_identifiers *out_id,
1256 uacpi_buffer *oem_table_id
1257)
1258{
1259 if (uacpi_unlikely(signature->size != (sizeof(uacpi_object_name) + 1)))
1260 return table_id_error(opcode, "SignatureString", signature);
1261
1262 uacpi_memcpy(out_id->signature.text, signature->text,
1263 sizeof(uacpi_object_name));
1264
1265 if (uacpi_unlikely(oem_id->size > (sizeof(out_id->oemid) + 1)))
1266 return table_id_error(opcode, "OemIDString", oem_id);
1267
1269 out_id->oemid, oem_id->text,
1270 sizeof(out_id->oemid), oem_id->size ? oem_id->size - 1 : 0
1271 );
1272
1273 if (uacpi_unlikely(oem_table_id->size > (sizeof(out_id->oem_table_id) + 1)))
1274 return table_id_error(opcode, "OemTableIDString", oem_table_id);
1275
1277 out_id->oem_table_id, oem_table_id->text,
1278 sizeof(out_id->oem_table_id),
1279 oem_table_id->size ? oem_table_id->size - 1 : 0
1280 );
1281
1282 return UACPI_STATUS_OK;
1283}
1284
1286{
1288 struct item_array *items = &ctx->cur_op_ctx->items;
1289 struct uacpi_table_identifiers table_id;
1293 uacpi_operation_region *op_region;
1294
1295 node = item_array_at(items, 0)->node;
1296
1298 "DataTableRegion", &table_id,
1299 item_array_at(items, 1)->obj->buffer,
1300 item_array_at(items, 2)->obj->buffer,
1301 item_array_at(items, 3)->obj->buffer
1302 );
1304 return ret;
1305
1306 ret = uacpi_table_find(&table_id, &table);
1308 report_table_id_find_error("DataTableRegion", &table_id, ret);
1309 return ret;
1310 }
1311
1312 obj = item_array_at(items, 4)->obj;
1313 op_region = obj->op_region;
1315 op_region->offset = table.virt_addr;
1316 op_region->length = table.hdr->length;
1317 op_region->table_idx = table.index;
1318
1321 );
1322 if (uacpi_unlikely(node->object == UACPI_NULL))
1324
1326 return UACPI_STATUS_OK;
1327}
1328
1330{
1331 return cause != UACPI_TABLE_LOAD_CAUSE_INIT;
1332}
1333
1335 void *ptr, enum uacpi_table_load_cause cause,
1336 uacpi_control_method *in_method
1337)
1338{
1339 struct acpi_dsdt *dsdt = ptr;
1340 uacpi_log_level log_level = UACPI_LOG_TRACE;
1341 const uacpi_char *log_prefix = "load of";
1342
1343 if (uacpi_unlikely(dsdt->hdr.length < sizeof(dsdt->hdr)))
1345
1346 if (is_dynamic_table_load(cause)) {
1347 log_prefix = cause == UACPI_TABLE_LOAD_CAUSE_HOST ?
1348 "host-invoked load of" : "dynamic load of";
1349 log_level = UACPI_LOG_INFO;
1350 }
1351
1353 log_level, "%s "UACPI_PRI_TBL_HDR,
1354 log_prefix, UACPI_FMT_TBL_HDR(&dsdt->hdr)
1355 );
1356
1357 in_method->code = dsdt->definition_block;
1358 in_method->size = dsdt->hdr.length - sizeof(dsdt->hdr);
1359 in_method->named_objects_persist = UACPI_TRUE;
1360
1361 return UACPI_STATUS_OK;
1362}
1363
1365 uacpi_namespace_node *parent, struct acpi_sdt_hdr *tbl,
1366 enum uacpi_table_load_cause cause
1367)
1368{
1369 struct uacpi_control_method method = { 0 };
1371
1372 ret = prepare_table_load(tbl, cause, &method);
1374 return ret;
1375
1378 return ret;
1379
1380 if (is_dynamic_table_load(cause))
1382
1383 return ret;
1384}
1385
1387{
1389 struct item_array *items = &ctx->cur_op_ctx->items;
1390 struct item *root_node_item;
1391 struct uacpi_table_identifiers table_id;
1393 uacpi_buffer *root_path, *param_path;
1395 uacpi_namespace_node *root_node, *param_node = UACPI_NULL;
1396
1397 /*
1398 * If we already have the last true/false object loaded, this is a second
1399 * invocation of this handler. For the second invocation we want to detect
1400 * new AML GPE handlers that might've been loaded, as well as potentially
1401 * remove the target.
1402 */
1403 if (item_array_size(items) == 12) {
1405 struct uacpi_table tmp_table = { 0 };
1406
1407 idx = item_array_at(items, 2)->immediate;
1408 tmp_table.index = idx;
1409 uacpi_table_unref(&tmp_table);
1410
1411 /*
1412 * If this load failed, remove the target that was provided via
1413 * ParameterPathString so that it doesn't get stored to.
1414 */
1415 if (uacpi_unlikely(item_array_at(items, 11)->obj->integer == 0)) {
1417
1418 target = item_array_at(items, 3)->obj;
1419 if (target != UACPI_NULL) {
1421 item_array_at(items, 3)->obj = UACPI_NULL;
1422 }
1423
1424 return UACPI_STATUS_OK;
1425 }
1426
1428 return UACPI_STATUS_OK;
1429 }
1430
1432 "LoadTable", &table_id,
1433 item_array_at(items, 5)->obj->buffer,
1434 item_array_at(items, 6)->obj->buffer,
1435 item_array_at(items, 7)->obj->buffer
1436 );
1438 return ret;
1439
1440 root_path = item_array_at(items, 8)->obj->buffer;
1441 param_path = item_array_at(items, 9)->obj->buffer;
1442 root_node_item = item_array_at(items, 0);
1443
1444 if (root_path->size > 1) {
1446 ctx->cur_frame->cur_scope, root_path->text, UACPI_SHOULD_LOCK_NO,
1448 &root_node
1449 );
1451 table_id_error("LoadTable", "RootPathString", root_path);
1454 return ret;
1455 }
1456 } else {
1457 root_node = uacpi_namespace_root();
1458 }
1459
1460 if (param_path->size > 1) {
1461 struct item *param_item;
1462
1464 root_node, param_path->text, UACPI_SHOULD_LOCK_NO,
1466 &param_node
1467 );
1469 table_id_error("LoadTable", "ParameterPathString", root_path);
1472 return ret;
1473 }
1474
1475 param_item = item_array_at(items, 3);
1476 param_item->obj = param_node->object;
1477 uacpi_object_ref(param_item->obj);
1478 param_item->type = ITEM_OBJECT;
1479 }
1480
1481 ret = uacpi_table_find(&table_id, &table);
1483 report_table_id_find_error("LoadTable", &table_id, ret);
1484 return ret;
1485 }
1486
1487 method = item_array_at(items, 1)->obj->method;
1490 );
1493 return ret;
1494 }
1495
1497 item_array_at(items, 2)->immediate = table.index;
1498
1499 root_node_item->node = root_node;
1500 root_node_item->type = ITEM_NAMESPACE_NODE;
1501 uacpi_shareable_ref(root_node);
1502
1503 return UACPI_STATUS_OK;
1504}
1505
1507{
1509 struct item_array *items = &ctx->cur_op_ctx->items;
1513 struct acpi_sdt_hdr *src_table = UACPI_NULL;
1514 void *table_buffer;
1515 uacpi_size declared_size;
1516 uacpi_bool unmap_src = UACPI_FALSE;
1517
1518 /*
1519 * If we already have the last true/false object loaded, this is a second
1520 * invocation of this handler. For the second invocation we simply want to
1521 * detect new AML GPE handlers that might've been loaded.
1522 * We do this only if table load was successful though.
1523 */
1524 if (item_array_size(items) == 6) {
1526 uacpi_table tmp_table = { 0 };
1527
1528 idx = item_array_at(items, 2)->immediate;
1529 tmp_table.index = idx;
1530 uacpi_table_unref(&tmp_table);
1531
1532 if (item_array_at(items, 5)->obj->integer != 0)
1534 return UACPI_STATUS_OK;
1535 }
1536
1537 src = item_array_at(items, 3)->obj;
1538
1539 switch (src->type) {
1541 uacpi_operation_region *op_region;
1542
1543 op_region = src->op_region;
1544 if (uacpi_unlikely(
1546 )) {
1547 uacpi_error("Load: operation region is not SystemMemory");
1549 goto error_out;
1550 }
1551
1552 if (uacpi_unlikely(op_region->length < sizeof(struct acpi_sdt_hdr))) {
1554 "Load: operation region is too small: %"UACPI_PRIu64,
1555 UACPI_FMT64(op_region->length)
1556 );
1558 goto error_out;
1559 }
1560
1561 src_table = uacpi_kernel_map(op_region->offset, op_region->length);
1562 if (uacpi_unlikely(src_table == UACPI_MAP_FAILED)) {
1564 "Load: failed to map operation region "
1565 "0x%016"UACPI_PRIX64" -> 0x%016"UACPI_PRIX64,
1566 UACPI_FMT64(op_region->offset),
1567 UACPI_FMT64(op_region->offset + op_region->length)
1568 );
1570 goto error_out;
1571 }
1572
1573 unmap_src = UACPI_TRUE;
1574 declared_size = op_region->length;
1575 break;
1576 }
1577
1578 case UACPI_OBJECT_BUFFER: {
1580
1581 buffer = src->buffer;
1582 if (buffer->size < sizeof(struct acpi_sdt_hdr)) {
1584 "Load: buffer is too small: %zu",
1585 buffer->size
1586 );
1587
1589 goto error_out;
1590 }
1591
1592 src_table = buffer->data;
1593 declared_size = buffer->size;
1594 break;
1595 }
1596
1597 default:
1599 "Load: invalid argument '%s', expected "
1600 "Buffer/Field/OperationRegion",
1602 );
1604 goto error_out;
1605 }
1606
1607 if (uacpi_unlikely(src_table->length > declared_size)) {
1609 "Load: table size %u is larger than the declared size %zu",
1610 src_table->length, declared_size
1611 );
1613 goto error_out;
1614 }
1615
1616 if (uacpi_unlikely(src_table->length < sizeof(struct acpi_sdt_hdr))) {
1617 uacpi_error("Load: table size %u is too small", src_table->length);
1619 goto error_out;
1620 }
1621
1622 table_buffer = uacpi_kernel_alloc(src_table->length);
1623 if (uacpi_unlikely(table_buffer == UACPI_NULL)) {
1625 goto error_out;
1626 }
1627
1628 uacpi_memcpy(table_buffer, src_table, src_table->length);
1629
1630 if (unmap_src) {
1631 uacpi_kernel_unmap(src_table, declared_size);
1632 unmap_src = UACPI_FALSE;
1633 }
1634
1637 );
1639 uacpi_free(table_buffer, src_table->length);
1640
1641 /*
1642 * Treat DENIED as a soft error, that is, fail the Load but don't abort
1643 * the currently running method. We simply return False to the caller
1644 * to signify an error in this case.
1645 */
1648
1650 goto error_out;
1651 }
1652
1653 method = item_array_at(items, 1)->obj->method;
1657 goto error_out;
1658 }
1659
1661 item_array_at(items, 2)->immediate = table.index;
1662
1663 item_array_at(items, 0)->node = uacpi_namespace_root();
1664 return UACPI_STATUS_OK;
1665
1666error_out:
1667 if (unmap_src && src_table)
1668 uacpi_kernel_unmap(src_table, declared_size);
1669 return ret;
1670}
1671
1673{
1675
1678 return ret;
1679
1680 ret = do_load_table(uacpi_namespace_root(), tbl, cause);
1681
1683 return ret;
1684}
1685
1687{
1688 struct package_length *pkg = &item->pkg;
1689 return pkg->end - pkg->begin;
1690}
1691
1697};
1698
1700 uacpi_field_unit **out_field)
1701{
1703
1705 if (obj->type != UACPI_OBJECT_FIELD_UNIT) {
1707 "invalid argument: '%.4s' is not a field unit (%s)",
1708 node->name.text, uacpi_object_type_to_string(obj->type)
1709 );
1711 }
1712
1713 *out_field = obj->field_unit;
1714 return UACPI_STATUS_OK;
1715}
1716
1718 uacpi_namespace_node **out_node)
1719{
1721
1723 if (obj->type != UACPI_OBJECT_OPERATION_REGION) {
1725 "invalid argument: '%.4s' is not an operation region (%s)",
1726 node->name.text, uacpi_object_type_to_string(obj->type)
1727 );
1729 }
1730
1731 *out_node = node;
1732 return UACPI_STATUS_OK;
1733}
1734
1736{
1738 struct op_context *op_ctx = ctx->cur_op_ctx;
1740 uacpi_object *obj, *connection_obj = UACPI_NULL;
1741 struct field_specific_data field_data = { 0 };
1742 uacpi_size i = 1, bit_offset = 0;
1743 uacpi_u32 length, pin_offset = 0;
1744
1745 uacpi_u8 raw_value, access_type, lock_rule, update_rule;
1746 uacpi_u8 access_attrib = 0, access_length = 0;
1747
1748 switch (op_ctx->op->code) {
1749 case UACPI_AML_OP_FieldOp:
1750 node = item_array_at(&op_ctx->items, i++)->node;
1751 ret = ensure_is_an_op_region(node, &field_data.region);
1753 return ret;
1754 break;
1755
1756 case UACPI_AML_OP_BankFieldOp:
1757 node = item_array_at(&op_ctx->items, i++)->node;
1758 ret = ensure_is_an_op_region(node, &field_data.region);
1760 return ret;
1761
1762 node = item_array_at(&op_ctx->items, i++)->node;
1763 ret = ensure_is_a_field_unit(node, &field_data.field0);
1765 return ret;
1766
1767 field_data.value = item_array_at(&op_ctx->items, i++)->obj->integer;
1768 break;
1769
1770 case UACPI_AML_OP_IndexFieldOp:
1771 node = item_array_at(&op_ctx->items, i++)->node;
1772 ret = ensure_is_a_field_unit(node, &field_data.field0);
1774 return ret;
1775
1776 node = item_array_at(&op_ctx->items, i++)->node;
1777 ret = ensure_is_a_field_unit(node, &field_data.field1);
1779 return ret;
1780 break;
1781
1782 default:
1784 }
1785
1786 /*
1787 * ByteData
1788 * bit 0-3: AccessType
1789 * 0 AnyAcc
1790 * 1 ByteAcc
1791 * 2 WordAcc
1792 * 3 DWordAcc
1793 * 4 QWordAcc
1794 * 5 BufferAcc
1795 * 6 Reserved
1796 * 7-15 Reserved
1797 * bit 4: LockRule
1798 * 0 NoLock
1799 * 1 Lock
1800 * bit 5-6: UpdateRule
1801 * 0 Preserve
1802 * 1 WriteAsOnes
1803 * 2 WriteAsZeros
1804 * bit 7: Reserved (must be 0)
1805 */
1806 raw_value = item_array_at(&op_ctx->items, i++)->immediate;
1807 access_type = (raw_value >> 0) & 0xF;
1808 lock_rule = (raw_value >> 4) & 0x1;
1809 update_rule = (raw_value >> 5) & 0x3;
1810
1811 while (i < item_array_size(&op_ctx->items)) {
1812 struct item *item;
1813 item = item_array_at(&op_ctx->items, i++);
1814
1815 // An actual field object
1816 if (item->type == ITEM_NAMESPACE_NODE) {
1818
1819 length = get_field_length(item_array_at(&op_ctx->items, i++));
1820 node = item->node;
1821
1822 obj = item_array_at(&op_ctx->items, i++)->obj;
1823
1824 // Duplicate field, skip
1826 goto next_field;
1827
1828 field = obj->field_unit;
1829
1830 field->update_rule = update_rule;
1831 field->lock_rule = lock_rule;
1832 field->attributes = access_attrib;
1833 field->access_length = access_length;
1834
1835 /*
1836 * 0 AnyAcc
1837 * 1 ByteAcc
1838 * 2 WordAcc
1839 * 3 DWordAcc
1840 * 4 QWordAcc
1841 * 5 BufferAcc
1842 * 6 Reserved
1843 * 7-15 Reserved
1844 */
1845 switch (access_type) {
1846 case 0:
1847 /*
1848 * NT always accesses AnyAcc fields one byte at a time, no
1849 * matter their size or alignment, so that's the only way
1850 * firmware has ever been tested. Don't try to pick a wider
1851 * access here, it could break hardware that works fine on NT.
1852 */
1854 case 1:
1855 case 5:
1856 field->access_width_bytes = 1;
1857 break;
1858 case 2:
1859 field->access_width_bytes = 2;
1860 break;
1861 case 3:
1862 field->access_width_bytes = 4;
1863 break;
1864 case 4:
1865 field->access_width_bytes = 8;
1866 break;
1867 default:
1868 uacpi_error("invalid field '%.4s' access type %d",
1869 node->name.text, access_type);
1871 }
1872
1873 field->bit_length = length;
1874 field->pin_offset = pin_offset;
1875
1876 // FIXME: overflow, OOB, etc checks
1877 field->byte_offset = UACPI_ALIGN_DOWN(
1878 bit_offset / 8,
1879 field->access_width_bytes,
1881 );
1882
1883 field->bit_offset_within_first_byte =
1884 bit_offset & ((field->access_width_bytes * 8) - 1);
1885
1886 switch (op_ctx->op->code) {
1887 case UACPI_AML_OP_FieldOp:
1888 field->region = field_data.region;
1889 uacpi_shareable_ref(field->region);
1890
1892 break;
1893
1894 case UACPI_AML_OP_BankFieldOp:
1895 field->bank_region = field_data.region;
1896 uacpi_shareable_ref(field->bank_region);
1897
1898 field->bank_selection = field_data.field0;
1899 uacpi_shareable_ref(field->bank_selection);
1900
1901 field->bank_value = field_data.value;
1903 break;
1904
1905 case UACPI_AML_OP_IndexFieldOp:
1906 field->index = field_data.field0;
1907 uacpi_shareable_ref(field->index);
1908
1909 field->data = field_data.field1;
1911
1913 break;
1914
1915 default:
1917 }
1918
1919 field->connection = connection_obj;
1920 if (field->connection)
1921 uacpi_object_ref(field->connection);
1922
1925 );
1926 if (uacpi_unlikely(node->object == UACPI_NULL))
1928
1929 ret = do_install_node_item(ctx->cur_frame, item);
1931 uacpi_object_unref(node->object);
1932 node->object = UACPI_NULL;
1933
1935 !ctx->cur_frame->method->named_objects_persist)
1936 return ret;
1937
1938 uacpi_warn("duplicate field '%.4s', skipping",
1939 node->name.text);
1940 }
1941
1942 next_field:
1943 bit_offset += length;
1944 pin_offset += length;
1945 continue;
1946 }
1947
1948 // All other stuff
1949 switch ((int)item->immediate) {
1950 // ReservedField := 0x00 PkgLength
1951 case 0x00:
1952 length = get_field_length(item_array_at(&op_ctx->items, i++));
1953 bit_offset += length;
1954 pin_offset += length;
1955 break;
1956
1957 // AccessField := 0x01 AccessType AccessAttrib
1958 // ExtendedAccessField := 0x03 AccessType ExtendedAccessAttrib AccessLength
1959 case 0x01:
1960 case 0x03:
1961 raw_value = item_array_at(&op_ctx->items, i++)->immediate;
1962
1963 access_type = raw_value & 0xF;
1964 access_attrib = (raw_value >> 6) & 0x3;
1965
1966 raw_value = item_array_at(&op_ctx->items, i++)->immediate;
1967
1968 /*
1969 * Bits 7:6
1970 * 0 = AccessAttrib = Normal Access Attributes
1971 * 1 = AccessAttrib = AttribBytes (x)
1972 * 2 = AccessAttrib = AttribRawBytes (x)
1973 * 3 = AccessAttrib = AttribRawProcessBytes (x)
1974 * x is encoded as bits 0:7 of the AccessAttrib byte.
1975 */
1976 if (access_attrib) {
1977 switch (access_attrib) {
1978 case 1:
1979 access_attrib = UACPI_ACCESS_ATTRIBUTE_BYTES;
1980 break;
1981 case 2:
1982 access_attrib = UACPI_ACCESS_ATTRIBUTE_RAW_BYTES;
1983 break;
1984 case 3:
1986 break;
1987 }
1988
1989 access_length = raw_value;
1990 } else { // Normal access attributes
1991 access_attrib = raw_value;
1992 }
1993
1994 if (item->immediate == 3)
1995 access_length = item_array_at(&op_ctx->items, i++)->immediate;
1996 break;
1997
1998 // ConnectField := <0x02 NameString> | <0x02 BufferData>
1999 case 0x02:
2000 connection_obj = item_array_at(&op_ctx->items, i++)->obj;
2001 pin_offset = 0;
2002 break;
2003
2004 default:
2006 }
2007 }
2008
2009 return UACPI_STATUS_OK;
2010}
2011
2013{
2014 if (!g_uacpi_rt_ctx.is_rev1)
2015 return;
2016
2017 obj->integer &= 0xFFFFFFFF;
2018}
2019
2020static uacpi_u64 ones(void)
2021{
2022 return g_uacpi_rt_ctx.is_rev1 ? 0xFFFFFFFF : 0xFFFFFFFFFFFFFFFF;
2023}
2024
2026 uacpi_object **out_operand)
2027{
2029
2030 // Check if we're targeting the previous call frame
2031 depth = call_frame_array_size(&ctx->call_stack);
2032 if (depth > 1) {
2033 struct op_context *op_ctx;
2034 struct call_frame *frame;
2035
2036 frame = call_frame_array_at(&ctx->call_stack, depth - 2);
2037 depth = op_context_array_size(&frame->pending_ops);
2038
2039 // Ok, no one wants the return value at call site. Discard it.
2040 if (!depth) {
2041 *out_operand = UACPI_NULL;
2042 return UACPI_STATUS_OK;
2043 }
2044
2045 op_ctx = op_context_array_at(&frame->pending_ops, depth - 1);
2046
2047 /*
2048 * Prevent the table being dynamically loaded from attempting to return
2049 * a value to the caller. This is unlikely to be ever encountered in the
2050 * wild, but we should still guard against the possibility.
2051 */
2052 if (uacpi_unlikely(op_ctx->op->code == UACPI_AML_OP_LoadOp ||
2053 op_ctx->op->code == UACPI_AML_OP_LoadTableOp)) {
2054 *out_operand = UACPI_NULL;
2055 return UACPI_STATUS_OK;
2056 }
2057
2058 *out_operand = item_array_last(&op_ctx->items)->obj;
2059 return UACPI_STATUS_OK;
2060 }
2061
2063}
2064
2066 uacpi_object **out_obj)
2067{
2069
2070 ret = method_get_ret_target(ctx, out_obj);
2071 if (ret == UACPI_STATUS_NOT_FOUND) {
2072 *out_obj = ctx->ret;
2073 return UACPI_STATUS_OK;
2074 }
2075 if (ret != UACPI_STATUS_OK || *out_obj == UACPI_NULL)
2076 return ret;
2077
2078 *out_obj = uacpi_unwrap_internal_reference(*out_obj);
2079 return UACPI_STATUS_OK;
2080}
2081
2083 struct code_block_array *blocks, enum code_block_type type,
2084 uacpi_size *out_idx_plus_one
2085)
2086{
2087 uacpi_size i;
2088
2089 i = code_block_array_size(blocks);
2090 while (i-- > 0) {
2091 struct code_block *block;
2092
2093 block = code_block_array_at(blocks, i);
2094 if (block->type == type) {
2095 if (out_idx_plus_one != UACPI_NULL)
2096 *out_idx_plus_one = i + 1;
2097 return block;
2098 }
2099 }
2100
2101 if (out_idx_plus_one != UACPI_NULL)
2102 *out_idx_plus_one = 0;
2103 return UACPI_NULL;
2104}
2105
2107{
2108 struct call_frame *cur_frame = ctx->cur_frame;
2109 struct op_context *op_ctx = ctx->cur_op_ctx;
2110 struct package_length *pkg;
2111 struct code_block *block;
2112
2113 block = code_block_array_alloc(&cur_frame->code_blocks);
2116
2117 pkg = &item_array_at(&op_ctx->items, 0)->pkg;
2118
2119 // Disarm the tracked package so that we don't skip the Scope
2120 op_ctx->tracked_pkg_idx = 0;
2121
2122 switch (op_ctx->op->code) {
2123 case UACPI_AML_OP_IfOp:
2124 block->type = CODE_BLOCK_IF;
2125 break;
2126 case UACPI_AML_OP_ElseOp:
2127 block->type = CODE_BLOCK_ELSE;
2128 break;
2129 case UACPI_AML_OP_WhileOp:
2130 block->type = CODE_BLOCK_WHILE;
2131
2132 if (pkg->begin == cur_frame->prev_while_code_offset) {
2133 uacpi_u64 cur_ticks;
2134
2136
2137 if (uacpi_unlikely(cur_ticks > block->expiration_point)) {
2138 uacpi_error("loop time out after running for %u seconds",
2139 g_uacpi_rt_ctx.loop_timeout_seconds);
2140 code_block_array_pop(&cur_frame->code_blocks);
2142 }
2143
2144 block->expiration_point = cur_frame->prev_while_expiration;
2145 } else {
2146 /*
2147 * Calculate the expiration point for this loop.
2148 * If a loop is executed past this point, it will get aborted.
2149 */
2150 block->expiration_point = uacpi_kernel_get_nanoseconds_since_boot();
2151 block->expiration_point +=
2152 g_uacpi_rt_ctx.loop_timeout_seconds * UACPI_NANOSECONDS_PER_SEC;
2153 }
2154
2155 cur_frame->last_while_idx_plus_one = code_block_array_size(
2156 &cur_frame->code_blocks
2157 );
2158 break;
2159 case UACPI_AML_OP_ScopeOp:
2160 case UACPI_AML_OP_DeviceOp:
2161 case UACPI_AML_OP_ProcessorOp:
2162 case UACPI_AML_OP_PowerResOp:
2163 case UACPI_AML_OP_ThermalZoneOp:
2164 block->type = CODE_BLOCK_SCOPE;
2165 block->node = item_array_at(&op_ctx->items, 1)->node;
2166 cur_frame->cur_scope = block->node;
2167 break;
2168 default:
2169 code_block_array_pop(&cur_frame->code_blocks);
2171 }
2172
2173 // -1 because we want to re-evaluate at the start of the op next time
2174 block->begin = pkg->begin - 1;
2175 block->end = pkg->end;
2176 ctx->cur_block = block;
2177
2178 return UACPI_STATUS_OK;
2179}
2180
2182 enum code_block_type type)
2183{
2184 struct call_frame *frame = ctx->cur_frame;
2185
2186 if (type == CODE_BLOCK_WHILE) {
2187 struct code_block *block = ctx->cur_block;
2188
2189 // + 1 here to skip the WhileOp and get to the PkgLength
2190 frame->prev_while_code_offset = block->begin + 1;
2191 frame->prev_while_expiration = block->expiration_point;
2192 }
2193
2194 code_block_array_pop(&frame->code_blocks);
2195 ctx->cur_block = code_block_array_last(&frame->code_blocks);
2196
2197 if (type == CODE_BLOCK_WHILE) {
2199 &frame->code_blocks, type, &frame->last_while_idx_plus_one
2200 );
2201 } else if (type == CODE_BLOCK_SCOPE) {
2202 struct code_block *block;
2203
2206 );
2207 if (block == UACPI_NULL) {
2209 return;
2210 }
2211
2212 frame->cur_scope = block->node;
2213 }
2214}
2215
2217{
2218 switch (src->type) {
2220 uacpi_trace("%s Uninitialized", prefix);
2221 break;
2223 uacpi_trace("%s String => \"%s\"", prefix, src->buffer->text);
2224 break;
2226 if (g_uacpi_rt_ctx.is_rev1) {
2228 "%s Integer => 0x%08X", prefix, (uacpi_u32)src->integer
2229 );
2230 } else {
2232 "%s Integer => 0x%016"UACPI_PRIX64, prefix,
2233 UACPI_FMT64(src->integer)
2234 );
2235 }
2236 break;
2238 uacpi_trace("%s Reference @%p => %p", prefix, src, src->inner_object);
2239 break;
2242 "%s Package @%p (%p) (%zu elements)",
2243 prefix, src, src->package, src->package->count
2244 );
2245 break;
2248 "%s Buffer @%p (%p) (%zu bytes)",
2249 prefix, src, src->buffer, src->buffer->size
2250 );
2251 break;
2254 "%s OperationRegion (ASID %d) 0x%016"UACPI_PRIX64
2255 " -> 0x%016"UACPI_PRIX64, prefix,
2256 src->op_region->space, UACPI_FMT64(src->op_region->offset),
2257 UACPI_FMT64(src->op_region->offset + src->op_region->length)
2258 );
2259 break;
2262 "%s Power Resource %d %d",
2263 prefix, src->power_resource.system_level,
2264 src->power_resource.resource_order
2265 );
2266 break;
2269 "%s Processor[%d] 0x%08X (%d)",
2270 prefix, src->processor->id, src->processor->block_address,
2271 src->processor->block_length
2272 );
2273 break;
2276 "%s Buffer Index %p[%zu] => 0x%02X",
2277 prefix, src->buffer_index.buffer->data, src->buffer_index.idx,
2278 *buffer_index_cursor(&src->buffer_index)
2279 );
2280 break;
2281 case UACPI_OBJECT_MUTEX:
2283 "%s Mutex @%p (%p => %p) sync level %d",
2284 prefix, src, src->mutex, src->mutex->handle,
2285 src->mutex->sync_level
2286 );
2287 break;
2289 uacpi_trace("%s Method @%p (%p)", prefix, src, src->method);
2290 break;
2291 default:
2293 "%s %s @%p",
2295 );
2296 }
2297}
2298
2300{
2301 /*
2302 * Don't bother running the body if current log level is not set to trace.
2303 * All DebugOp logging is done as TRACE exclusively.
2304 */
2306 return UACPI_STATUS_OK;
2307
2309
2310 debug_store_no_recurse("[AML DEBUG]", src);
2311
2312 if (src->type == UACPI_OBJECT_PACKAGE) {
2313 uacpi_package *pkg = src->package;
2314 uacpi_size i;
2315
2316 for (i = 0; i < pkg->count; ++i) {
2317 uacpi_object *obj = pkg->objects[i];
2318 if (obj->type == UACPI_OBJECT_REFERENCE &&
2320 obj = obj->inner_object;
2321
2322 debug_store_no_recurse("Element:", obj);
2323 }
2324 }
2325
2326 return UACPI_STATUS_OK;
2327}
2328
2329/*
2330 * NOTE: this function returns the parent object
2331 */
2333{
2335
2336 while (obj) {
2337 if (obj->type != UACPI_OBJECT_REFERENCE)
2338 return parent;
2339
2340 parent = obj;
2341 obj = parent->inner_object;
2342 }
2343
2344 // This should be unreachable
2345 return UACPI_NULL;
2346}
2347
2350
2351/*
2352 * Queues up an object to be looked at by check_no_reference_cycle, unless it
2353 * has nothing to lead to, or it was queued up already.
2354 *
2355 * An object might be reachable in more than one way, e.g. if it's referenced
2356 * by more than one element of a package. Going through it every single time
2357 * makes the amount of work that we have to do grow exponentially with the
2358 * depth of such a graph, so it's marked as soon as it's queued up.
2359 */
2361 struct object_queue *queue, uacpi_object *obj
2362)
2363{
2365
2366 if (obj == UACPI_NULL || obj->visited)
2367 return UACPI_STATUS_OK;
2368
2371 return UACPI_STATUS_OK;
2372
2373 entry = object_queue_alloc(queue);
2376
2377 *entry = obj;
2378 obj->visited = UACPI_TRUE;
2379 return UACPI_STATUS_OK;
2380}
2381
2382/*
2383 * Storing a reference, or a package containing one, can make the target
2384 * reachable from itself, which reference counting is unable to free. Walk
2385 * everything reachable through the new object and reject the store if it
2386 * leads back to the reference it's about to be stored through.
2387 */
2389 uacpi_object *dst, uacpi_object *new_obj
2390)
2391{
2392 struct object_queue queue = { 0 };
2395 uacpi_size i, j;
2396
2397 /*
2398 * Every object that was ever queued up stays in the queue, which is what
2399 * we use to take the marks back off once we're done.
2400 */
2401 ret = queue_object(&queue, new_obj);
2402
2403 for (i = 0; i < object_queue_size(&queue); ++i) {
2405 break;
2406
2407 obj = *object_queue_at(&queue, i);
2408
2409 if (obj == dst) {
2410 uacpi_error("store would create a reference cycle");
2412 break;
2413 }
2414
2416 ret = queue_object(&queue, obj->inner_object);
2417 continue;
2418 }
2419
2420 for (j = 0; j < obj->package->count; ++j) {
2421 ret = queue_object(&queue, obj->package->objects[j]);
2423 break;
2424 }
2425 }
2426
2427 for (i = 0; i < object_queue_size(&queue); ++i)
2428 (*object_queue_at(&queue, i))->visited = UACPI_FALSE;
2429
2430 object_queue_clear(&queue);
2431 return ret;
2432}
2433
2435 void *user, uacpi_namespace_node *node, uacpi_u32 node_depth
2436)
2437{
2438 uacpi_object *target_object = user;
2439 UACPI_UNUSED(node_depth);
2440
2441 if (node->object == target_object) {
2444 }
2445
2447}
2448
2450 uacpi_object *parent, uacpi_object *new_child
2451)
2452{
2454
2455 if (parent->flags == UACPI_REFERENCE_KIND_NAMED &&
2457
2458 /*
2459 * We're doing a CopyObject or similar to a namespace node that is an
2460 * operation region. Try to find the parent node and manually detach
2461 * the handler.
2462 */
2468 );
2469
2470 /*
2471 * Both the handler of the region and its _REG method were invoked by
2472 * the above, at times with the namespace unlocked, so any number of
2473 * other stores might've been done in the meantime. The one that we're
2474 * in the middle of was only checked against what was there before
2475 * that, and is free to be a reference cycle by now. Nothing else is
2476 * able to get in the way from this point on, so check it once more.
2477 */
2478 ret = check_no_reference_cycle(parent, new_child);
2480 return ret;
2481 }
2482
2485 return UACPI_STATUS_OK;
2486}
2487
2488/*
2489 * Objects that only ever come from a declaration in the namespace. Unlike
2490 * CopyObject, a store through an ArgX reference doesn't overwrite them on NT.
2491 */
2493{
2500 );
2501}
2502
2503/*
2504 * NT never overwrites these objects, no matter how they were reached, it
2505 * always stores to them _with_ implicit cast instead.
2506 */
2508{
2512 );
2513}
2514
2515/*
2516 * An Index() of a package refers to the slot that the element is stored in,
2517 * and keeps doing so after the element is replaced. A copy of it would only
2518 * refer to the element that's in there right now, so it's shared instead.
2519 */
2521{
2522 return obj->type == UACPI_OBJECT_REFERENCE &&
2524}
2525
2527 uacpi_object *src, uacpi_object **out_obj
2528)
2529{
2532
2535 *out_obj = src;
2536 return UACPI_STATUS_OK;
2537 }
2538
2542
2546 return ret;
2547 }
2548
2549 *out_obj = obj;
2550 return UACPI_STATUS_OK;
2551}
2552
2553/*
2554 * Breakdown of what happens here:
2555 *
2556 * CopyObject(..., Obj) where Obj is:
2557 * 1. LocalX -> Overwrite LocalX.
2558 * 2. NAME -> Overwrite NAME, or the object it refers to if it holds a
2559 * RefOf() of something.
2560 * 3. ArgX -> Overwrite ArgX unless ArgX is a reference, in that case
2561 * overwrite the referenced object.
2562 * 4. RefOf -> Not allowed here.
2563 * 5. Index -> Overwrite Object stored at the index.
2564 *
2565 * Unless the object that would get overwritten is one of the objects that NT
2566 * always stores to instead, e.g. a field.
2567 */
2570{
2572 uacpi_object *src_obj, *new_obj;
2573
2574 switch (dst->flags) {
2576 uacpi_object *referenced_obj;
2577
2578 referenced_obj = uacpi_unwrap_internal_reference(dst);
2579 if (referenced_obj->type == UACPI_OBJECT_REFERENCE)
2580 dst = reference_unwind(referenced_obj);
2581 break;
2582 }
2585 break;
2587 /*
2588 * A name that holds a reference is an alias of what it refers to, NT
2589 * only overwrites the name itself if it's an Index() of a package.
2590 */
2591 if (!object_is_package_index(dst->inner_object))
2593 break;
2594 default:
2596 }
2597
2599
2600 if (object_is_written_in_place(dst->inner_object))
2602 dst->inner_object, src_obj, UACPI_NULL
2603 );
2604
2605 ret = object_copy_for_overwrite(src_obj, &new_obj);
2607 return ret;
2608
2609 ret = check_no_reference_cycle(dst, new_obj);
2611 uacpi_object_unref(new_obj);
2612 return ret;
2613 }
2614
2615 ret = object_replace_child(dst, new_obj);
2616 uacpi_object_unref(new_obj);
2617
2618 return ret;
2619}
2620
2621/*
2622 * if Store(..., Obj) where Obj is:
2623 * 1. LocalX/Index -> OVERWRITE unless the object is a reference, in that
2624 * case store to the referenced object _with_ implicit
2625 * cast.
2626 * 2. ArgX -> OVERWRITE unless the object is a reference, in that
2627 * case OVERWRITE the referenced object.
2628 * 3. NAME -> Store with implicit cast.
2629 * 4. RefOf -> Not allowed here.
2630 *
2631 * Unless the object that would get overwritten is one of the objects that NT
2632 * always stores to instead, e.g. a field.
2633 */
2636)
2637{
2638 uacpi_object *src_obj;
2639 uacpi_bool overwrite = UACPI_FALSE;
2640
2641 switch (dst->flags) {
2645 uacpi_object *referenced_obj;
2646
2647 if (dst->flags == UACPI_REFERENCE_KIND_PKG_INDEX)
2648 referenced_obj = dst->inner_object;
2649 else
2650 referenced_obj = uacpi_unwrap_internal_reference(dst);
2651
2652 if (referenced_obj->type == UACPI_OBJECT_REFERENCE) {
2653 overwrite = dst->flags == UACPI_REFERENCE_KIND_ARG;
2654 dst = reference_unwind(referenced_obj);
2655
2656 if (overwrite && object_is_namespace_only(dst->inner_object)) {
2658 "attempted to overwrite %s object via an ArgX reference",
2659 uacpi_object_type_to_string(dst->inner_object->type)
2660 );
2662 }
2663 break;
2664 }
2665
2666 overwrite = UACPI_TRUE;
2667 break;
2668 }
2671 break;
2672 default:
2674 }
2675
2677 overwrite |= dst->inner_object->type == UACPI_OBJECT_UNINITIALIZED;
2678
2679 if (object_is_written_in_place(dst->inner_object))
2680 overwrite = UACPI_FALSE;
2681
2682 if (overwrite) {
2684 uacpi_object *new_obj;
2685
2686 ret = object_copy_for_overwrite(src_obj, &new_obj);
2688 return ret;
2689
2690 ret = check_no_reference_cycle(dst, new_obj);
2692 uacpi_object_unref(new_obj);
2693 return ret;
2694 }
2695
2696 ret = object_replace_child(dst, new_obj);
2697 uacpi_object_unref(new_obj);
2698 return ret;
2699 }
2700
2702 dst->inner_object, src_obj, wtr_response
2703 );
2704}
2705
2707{
2708 struct op_context *op_ctx = ctx->cur_op_ctx;
2709 uacpi_object *dst, *src;
2710
2711 src = item_array_at(&op_ctx->items, 0)->obj;
2712
2713 if (op_ctx->op->code == UACPI_AML_OP_CondRefOfOp)
2714 dst = item_array_at(&op_ctx->items, 2)->obj;
2715 else
2716 dst = item_array_at(&op_ctx->items, 1)->obj;
2717
2719 dst->inner_object = src;
2721 return UACPI_STATUS_OK;
2722}
2723
2726 uacpi_object *tgt0, uacpi_object *tgt1,
2728)
2729{
2730 uacpi_u64 lhs, rhs, res;
2731 uacpi_bool should_negate = UACPI_FALSE;
2732
2733 lhs = arg0->integer;
2734 rhs = arg1->integer;
2735
2736 switch (op)
2737 {
2738 case UACPI_AML_OP_AddOp:
2739 res = lhs + rhs;
2740 break;
2741 case UACPI_AML_OP_SubtractOp:
2742 res = lhs - rhs;
2743 break;
2744 case UACPI_AML_OP_MultiplyOp:
2745 res = lhs * rhs;
2746 break;
2747 case UACPI_AML_OP_ShiftLeftOp:
2748 case UACPI_AML_OP_ShiftRightOp:
2749 if (rhs <= (g_uacpi_rt_ctx.is_rev1 ? 31 : 63)) {
2750 if (op == UACPI_AML_OP_ShiftLeftOp)
2751 res = lhs << rhs;
2752 else
2753 res = lhs >> rhs;
2754 } else {
2755 res = 0;
2756 }
2757 break;
2758 case UACPI_AML_OP_NandOp:
2759 should_negate = UACPI_TRUE;
2761 case UACPI_AML_OP_AndOp:
2762 res = rhs & lhs;
2763 break;
2764 case UACPI_AML_OP_NorOp:
2765 should_negate = UACPI_TRUE;
2767 case UACPI_AML_OP_OrOp:
2768 res = rhs | lhs;
2769 break;
2770 case UACPI_AML_OP_XorOp:
2771 res = rhs ^ lhs;
2772 break;
2773 case UACPI_AML_OP_DivideOp:
2774 if (uacpi_unlikely(rhs == 0)) {
2775 uacpi_error("attempted to divide by zero");
2777 }
2778 tgt1->integer = lhs / rhs;
2779 res = lhs % rhs;
2780 break;
2781 case UACPI_AML_OP_ModOp:
2782 if (uacpi_unlikely(rhs == 0)) {
2783 uacpi_error("attempted to calculate modulo of zero");
2785 }
2786 res = lhs % rhs;
2787 break;
2788 default:
2790 }
2791
2792 if (should_negate)
2793 res = ~res;
2794
2795 tgt0->integer = res;
2796 return UACPI_STATUS_OK;
2797}
2798
2800{
2801 uacpi_object *arg0, *arg1, *tgt0, *tgt1;
2802 struct item_array *items = &ctx->cur_op_ctx->items;
2803 uacpi_aml_op op = ctx->cur_op_ctx->op->code;
2804
2805 arg0 = item_array_at(items, 0)->obj;
2806 arg1 = item_array_at(items, 1)->obj;
2807
2808 if (op == UACPI_AML_OP_DivideOp) {
2809 tgt0 = item_array_at(items, 4)->obj;
2810 tgt1 = item_array_at(items, 5)->obj;
2811 } else {
2812 tgt0 = item_array_at(items, 3)->obj;
2813 tgt1 = UACPI_NULL;
2814 }
2815
2816 return do_binary_math(arg0, arg1, tgt0, tgt1, op);
2817}
2818
2820{
2821 uacpi_object *arg, *tgt;
2822 struct item_array *items = &ctx->cur_op_ctx->items;
2823 uacpi_aml_op op = ctx->cur_op_ctx->op->code;
2824
2825 arg = item_array_at(items, 0)->obj;
2826 tgt = item_array_at(items, 2)->obj;
2827
2828 switch (op) {
2829 case UACPI_AML_OP_NotOp:
2830 tgt->integer = ~arg->integer;
2832 break;
2833 case UACPI_AML_OP_FindSetRightBitOp:
2834 tgt->integer = uacpi_bit_scan_forward(arg->integer);
2835 break;
2836 case UACPI_AML_OP_FindSetLeftBitOp:
2837 tgt->integer = uacpi_bit_scan_backward(arg->integer);
2838 break;
2839 default:
2841 }
2842
2843 return UACPI_STATUS_OK;
2844}
2845
2847 uacpi_size src_size)
2848{
2849 if (uacpi_likely(idx < src_size))
2850 return UACPI_STATUS_OK;
2851
2853 "invalid index %zu, %s@%p has %zu elements",
2854 idx, uacpi_object_type_to_string(obj->type), obj, src_size
2855 );
2857}
2858
2860{
2862 struct op_context *op_ctx = ctx->cur_op_ctx;
2864 struct item *dst;
2866
2867 src = item_array_at(&op_ctx->items, 0)->obj;
2868 idx = item_array_at(&op_ctx->items, 1)->obj->integer;
2869 dst = item_array_at(&op_ctx->items, 3);
2870
2871 switch (src->type) {
2873 case UACPI_OBJECT_STRING: {
2874 uacpi_buffer_index *buf_idx;
2877
2878 ret = ensure_valid_idx(src, idx, buf.length);
2880 return ret;
2881
2882 dst->type = ITEM_OBJECT;
2884 if (uacpi_unlikely(dst->obj == UACPI_NULL))
2886
2887 buf_idx = &dst->obj->buffer_index;
2888 buf_idx->idx = idx;
2889 buf_idx->buffer = src->buffer;
2890 uacpi_shareable_ref(buf_idx->buffer);
2891
2892 break;
2893 }
2894 case UACPI_OBJECT_PACKAGE: {
2895 uacpi_package *pkg = src->package;
2897
2898 ret = ensure_valid_idx(src, idx, pkg->count);
2900 return ret;
2901
2902 /*
2903 * Lazily transform the package element into an internal reference
2904 * to itself of type PKG_INDEX. This is needed to support stuff like
2905 * CopyObject(..., Index(pkg, X)) where the new object must be
2906 * propagated to anyone else with a currently alive index object.
2907 *
2908 * Sidenote: Yes, IndexOp is not a SimpleName, so technically it is
2909 * illegal to CopyObject to it. However, yet again we fall
2910 * victim to the NT ACPI driver implementation, which allows
2911 * it just fine.
2912 */
2913 obj = pkg->objects[idx];
2914 if (obj->type != UACPI_OBJECT_REFERENCE ||
2916
2919 );
2922
2923 pkg->objects[idx] = obj;
2924 uacpi_object_unref(obj->inner_object);
2925 }
2926
2927 dst->obj = obj;
2928 dst->type = ITEM_OBJECT;
2929 uacpi_object_ref(dst->obj);
2930 break;
2931 }
2932 default:
2934 "invalid argument for Index: %s, "
2935 "expected String/Buffer/Package",
2937 );
2939 }
2940
2941 return UACPI_STATUS_OK;
2942}
2943
2945 uacpi_size max_buffer_bytes)
2946{
2947 uacpi_u64 dst;
2948
2949 switch (obj->type) {
2951 dst = obj->integer;
2952 break;
2953 case UACPI_OBJECT_BUFFER: {
2955 bytes = UACPI_MIN(max_buffer_bytes, obj->buffer->size);
2956 uacpi_memcpy_zerout(&dst, obj->buffer->data, sizeof(dst), bytes);
2957 break;
2958 }
2961 obj->buffer->text, obj->buffer->size, UACPI_BASE_AUTO, &dst
2962 );
2963 break;
2964 default:
2965 dst = 0;
2966 break;
2967 }
2968
2969 return dst;
2970}
2971
2974)
2975{
2976 int repr_len;
2977 uacpi_char int_buf[21];
2978 uacpi_size final_size;
2979
2980 repr_len = uacpi_snprintf(
2981 int_buf, sizeof(int_buf),
2984 );
2985 if (uacpi_unlikely(repr_len < 0))
2987
2988 // 0x prefix + repr + \0
2989 final_size = (is_hex ? 2 : 0) + repr_len + 1;
2990
2991 str->data = uacpi_kernel_alloc(final_size);
2992 if (uacpi_unlikely(str->data == UACPI_NULL))
2994
2995 if (is_hex) {
2996 str->text[0] = '0';
2997 str->text[1] = 'x';
2998 }
2999 uacpi_memcpy(str->text + (is_hex ? 2 : 0), int_buf, repr_len + 1);
3000 str->size = final_size;
3001
3002 return UACPI_STATUS_OK;
3003}
3004
3007)
3008{
3009 int repr_len;
3010 uacpi_char int_buf[5];
3011 uacpi_size i, final_size;
3013
3014 if (is_hex) {
3015 final_size = 4 * buf->size;
3016 } else {
3017 final_size = 0;
3018
3019 for (i = 0; i < buf->size; ++i) {
3020 uacpi_u8 value = ((uacpi_u8*)buf->data)[i];
3021
3022 if (value < 10)
3023 final_size += 1;
3024 else if (value < 100)
3025 final_size += 2;
3026 else
3027 final_size += 3;
3028 }
3029 }
3030
3031 /*
3032 * Comma for every value but one and a null terminator, the latter being
3033 * all there is for an empty buffer.
3034 */
3035 final_size += UACPI_MAX(buf->size, 1);
3036
3037 str->data = uacpi_kernel_alloc(final_size);
3038 if (uacpi_unlikely(str->data == UACPI_NULL))
3040
3041 cursor = str->data;
3042
3043 for (i = 0; i < buf->size; ++i) {
3044 repr_len = uacpi_snprintf(
3045 int_buf, sizeof(int_buf),
3046 is_hex ? "0x%02X" : "%d",
3047 ((uacpi_u8*)buf->data)[i]
3048 );
3049 if (uacpi_unlikely(repr_len < 0)) {
3050 uacpi_free(str->data, final_size);
3051 str->data = UACPI_NULL;
3053 }
3054
3055 uacpi_memcpy(cursor, int_buf, repr_len + 1);
3056 cursor += repr_len;
3057
3058 if (i != buf->size - 1)
3059 *cursor++ = ',';
3060 }
3061 *cursor = '\0';
3062
3063 str->size = final_size;
3064 return UACPI_STATUS_OK;
3065}
3066
3069{
3070 buf->text = uacpi_kernel_alloc_zeroed(sizeof(uacpi_char));
3071 if (uacpi_unlikely(buf->text == UACPI_NULL))
3073
3074 if (is_string)
3075 buf->size = sizeof(uacpi_char);
3076
3077 return UACPI_STATUS_OK;
3078}
3079
3081{
3083}
3084
3086{
3087 /*
3088 * Allocate at least 1 byte just to be safe,
3089 * even for empty buffers. We still set the
3090 * size to 0 though.
3091 */
3093}
3094
3096{
3098 struct op_context *op_ctx = ctx->cur_op_ctx;
3099 uacpi_object *src, *dst;
3100
3101 src = item_array_at(&op_ctx->items, 0)->obj;
3102 dst = item_array_at(&op_ctx->items, 2)->obj;
3103
3104 switch (op_ctx->op->code) {
3105 case UACPI_AML_OP_ToIntegerOp:
3106 dst->integer = object_to_integer(src, sizeof_int());
3107 break;
3108
3109 case UACPI_AML_OP_ToHexStringOp:
3110 case UACPI_AML_OP_ToDecimalStringOp: {
3111 uacpi_bool is_hex = op_ctx->op->code == UACPI_AML_OP_ToHexStringOp;
3112
3113 if (src->type == UACPI_OBJECT_INTEGER) {
3114 ret = integer_to_string(src->integer, dst->buffer, is_hex);
3115 break;
3116 } else if (src->type == UACPI_OBJECT_BUFFER) {
3117 ret = buffer_to_string(src->buffer, dst->buffer, is_hex);
3118 break;
3119 }
3121 }
3122 case UACPI_AML_OP_ToBufferOp: {
3124 uacpi_u8 *dst_buf;
3125
3128 return ret;
3129
3130 if (uacpi_unlikely(buf.length == 0))
3131 return make_null_buffer(dst->buffer);
3132
3133 dst_buf = uacpi_kernel_alloc(buf.length);
3134 if (uacpi_unlikely(dst_buf == UACPI_NULL))
3136
3137 uacpi_memcpy(dst_buf, buf.bytes, buf.length);
3138 dst->buffer->data = dst_buf;
3139 dst->buffer->size = buf.length;
3140 break;
3141 }
3142
3143 default:
3145 }
3146
3147 return ret;
3148}
3149
3151{
3152 struct op_context *op_ctx = ctx->cur_op_ctx;
3153 uacpi_buffer *src_buf, *dst_buf;
3154 uacpi_size req_len, len;
3155
3156 src_buf = item_array_at(&op_ctx->items, 0)->obj->buffer;
3157 req_len = item_array_at(&op_ctx->items, 1)->obj->integer;
3158 dst_buf = item_array_at(&op_ctx->items, 3)->obj->buffer;
3159
3160 len = UACPI_MIN(req_len, src_buf->size);
3161 if (uacpi_unlikely(len == 0))
3162 return make_null_string(dst_buf);
3163
3164 len = uacpi_strnlen(src_buf->text, len);
3165
3166 dst_buf->text = uacpi_kernel_alloc(len + 1);
3167 if (uacpi_unlikely(dst_buf->text == UACPI_NULL))
3169
3170 uacpi_memcpy(dst_buf->text, src_buf->data, len);
3171 dst_buf->text[len] = '\0';
3172 dst_buf->size = len + 1;
3173
3174 return UACPI_STATUS_OK;
3175}
3176
3178{
3179 struct op_context *op_ctx = ctx->cur_op_ctx;
3180 uacpi_object *src, *dst;
3181 uacpi_data_view src_buf;
3182 uacpi_buffer *dst_buf;
3185
3186 src = item_array_at(&op_ctx->items, 0)->obj;
3187 if (uacpi_unlikely(src->type != UACPI_OBJECT_STRING &&
3188 src->type != UACPI_OBJECT_BUFFER)) {
3190 "invalid argument for Mid: %s, expected String/Buffer",
3192 );
3194 }
3195
3196 idx = item_array_at(&op_ctx->items, 1)->obj->integer;
3197 len = item_array_at(&op_ctx->items, 2)->obj->integer;
3198 dst = item_array_at(&op_ctx->items, 4)->obj;
3199 dst_buf = dst->buffer;
3200
3203
3204 if (uacpi_unlikely(src_buf.length == 0 || idx >= src_buf.length ||
3205 len == 0)) {
3206 if (src->type == UACPI_OBJECT_STRING) {
3207 dst->type = UACPI_OBJECT_STRING;
3208 return make_null_string(dst_buf);
3209 }
3210
3211 return make_null_buffer(dst_buf);
3212 }
3213
3214 // Guaranteed to be at least 1 here
3215 len = UACPI_MIN(len, src_buf.length - idx);
3216
3217 dst_buf->data = uacpi_kernel_alloc(len + is_string);
3218 if (uacpi_unlikely(dst_buf->data == UACPI_NULL))
3220
3221 uacpi_memcpy(dst_buf->data, (uacpi_u8*)src_buf.bytes + idx, len);
3222 dst_buf->size = len;
3223
3224 if (is_string) {
3225 dst_buf->text[dst_buf->size++] = '\0';
3226 dst->type = UACPI_OBJECT_STRING;
3227 }
3228
3229 return UACPI_STATUS_OK;
3230}
3231
3233{
3235 struct op_context *op_ctx = ctx->cur_op_ctx;
3236 uacpi_object *arg0, *arg1, *dst;
3237 uacpi_u8 *dst_buf;
3238 uacpi_size buf_size = 0;
3239
3240 arg0 = item_array_at(&op_ctx->items, 0)->obj;
3241 arg1 = item_array_at(&op_ctx->items, 1)->obj;
3242 dst = item_array_at(&op_ctx->items, 3)->obj;
3243
3244 switch (arg0->type) {
3245 case UACPI_OBJECT_INTEGER: {
3246 uacpi_u64 arg1_as_int;
3247 uacpi_size int_size;
3248
3249 int_size = sizeof_int();
3250 buf_size = int_size * 2;
3251
3252 dst_buf = uacpi_kernel_alloc(buf_size);
3253 if (uacpi_unlikely(dst_buf == UACPI_NULL))
3255
3256 arg1_as_int = object_to_integer(arg1, int_size);
3257
3258 uacpi_memcpy(dst_buf, &arg0->integer, int_size);
3259 uacpi_memcpy(dst_buf+ int_size, &arg1_as_int, int_size);
3260 break;
3261 }
3262 case UACPI_OBJECT_BUFFER: {
3263 uacpi_buffer *arg0_buf = arg0->buffer;
3264 uacpi_data_view arg1_buf = { 0 };
3265
3266 get_object_storage(arg1, &arg1_buf, UACPI_TRUE);
3267 buf_size = arg0_buf->size + arg1_buf.length;
3268
3269 // Two empty buffers make an empty buffer, see make_null_buffer()
3270 dst_buf = uacpi_kernel_alloc(UACPI_MAX(buf_size, 1));
3271 if (uacpi_unlikely(dst_buf == UACPI_NULL))
3273
3274 uacpi_memcpy(dst_buf, arg0_buf->data, arg0_buf->size);
3275 uacpi_memcpy(dst_buf + arg0_buf->size, arg1_buf.bytes, arg1_buf.length);
3276 break;
3277 }
3278 case UACPI_OBJECT_STRING: {
3279 uacpi_char int_buf[17];
3280 void *arg1_ptr;
3281 uacpi_size arg0_size, arg1_size;
3282 uacpi_buffer *arg0_buf = arg0->buffer;
3283
3284 switch (arg1->type) {
3285 case UACPI_OBJECT_INTEGER: {
3286 int size;
3287 size = uacpi_snprintf(int_buf, sizeof(int_buf), "%"UACPI_PRIx64,
3288 UACPI_FMT64(arg1->integer));
3289 if (size < 0)
3291
3292 arg1_ptr = int_buf;
3293 arg1_size = size + 1;
3294 break;
3295 }
3297 arg1_ptr = arg1->buffer->data;
3298 arg1_size = arg1->buffer->size;
3299 break;
3300 case UACPI_OBJECT_BUFFER: {
3301 uacpi_buffer tmp_buf;
3302
3303 ret = buffer_to_string(arg1->buffer, &tmp_buf, UACPI_TRUE);
3305 return ret;
3306
3307 arg1_ptr = tmp_buf.data;
3308 arg1_size = tmp_buf.size;
3309 break;
3310 }
3311 default:
3313 }
3314
3315 arg0_size = arg0_buf->size ? arg0_buf->size - 1 : arg0_buf->size;
3316 buf_size = arg0_size + arg1_size;
3317
3318 dst_buf = uacpi_kernel_alloc(buf_size);
3319 if (uacpi_unlikely(dst_buf == UACPI_NULL)) {
3321 goto cleanup;
3322 }
3323
3324 uacpi_memcpy(dst_buf, arg0_buf->data, arg0_size);
3325 uacpi_memcpy(dst_buf + arg0_size, arg1_ptr, arg1_size);
3326 dst->type = UACPI_OBJECT_STRING;
3327
3328 cleanup:
3329 if (arg1->type == UACPI_OBJECT_BUFFER)
3330 uacpi_free(arg1_ptr, arg1_size);
3331 break;
3332 }
3333 default:
3335 }
3336
3338 dst->buffer->data = dst_buf;
3339 dst->buffer->size = buf_size;
3340 }
3341 return ret;
3342}
3343
3345{
3347 struct op_context *op_ctx = ctx->cur_op_ctx;
3349 uacpi_object *arg0, *arg1, *dst;
3350 uacpi_u8 *dst_buf;
3351 uacpi_size dst_size, arg0_size, arg1_size;
3352
3353 arg0 = item_array_at(&op_ctx->items, 0)->obj;
3354 arg1 = item_array_at(&op_ctx->items, 1)->obj;
3355 dst = item_array_at(&op_ctx->items, 3)->obj;
3356
3360 return ret;
3361
3362 uacpi_buffer_to_view(arg1->buffer, &buffer);
3365 return ret;
3366
3367 dst_size = arg0_size + arg1_size + sizeof(struct acpi_resource_end_tag);
3368
3369 dst_buf = uacpi_kernel_alloc(dst_size);
3370 if (uacpi_unlikely(dst_buf == UACPI_NULL))
3372
3373 dst->buffer->data = dst_buf;
3374 dst->buffer->size = dst_size;
3375
3376 uacpi_memcpy(dst_buf, arg0->buffer->data, arg0_size);
3377 uacpi_memcpy(dst_buf + arg0_size, arg1->buffer->data, arg1_size);
3378
3379 /*
3380 * Small item (0), End Tag (0x0F), length 1
3381 * Leave the checksum as 0
3382 */
3383 dst_buf[dst_size - 2] =
3385 (sizeof(struct acpi_resource_end_tag) - 1);
3386 dst_buf[dst_size - 1] = 0;
3387
3388 return UACPI_STATUS_OK;
3389}
3390
3392{
3393 struct op_context *op_ctx = ctx->cur_op_ctx;
3394 uacpi_object *src, *dst;
3395
3396 src = item_array_at(&op_ctx->items, 0)->obj;
3397 dst = item_array_at(&op_ctx->items, 1)->obj;
3398
3401
3402 switch (src->type) {
3404 case UACPI_OBJECT_BUFFER: {
3407
3408 dst->integer = buf.length;
3409 break;
3410 }
3411
3413 dst->integer = src->package->count;
3414 break;
3415
3416 default:
3418 "invalid argument for Sizeof: %s, "
3419 "expected String/Buffer/Package",
3421 );
3423 }
3424
3425 return UACPI_STATUS_OK;
3426}
3427
3429{
3430 struct op_context *op_ctx = ctx->cur_op_ctx;
3431 uacpi_object *src, *dst;
3432
3433 src = item_array_at(&op_ctx->items, 0)->obj;
3434 dst = item_array_at(&op_ctx->items, 1)->obj;
3435
3438
3439 dst->integer = src->type;
3440 if (dst->integer == UACPI_OBJECT_BUFFER_INDEX)
3441 dst->integer = UACPI_OBJECT_BUFFER_FIELD;
3442
3443 return UACPI_STATUS_OK;
3444}
3445
3447{
3448 struct op_context *op_ctx = ctx->cur_op_ctx;
3450
3451 dst = item_array_at(&op_ctx->items, 0)->obj;
3453
3454 return UACPI_STATUS_OK;
3455}
3456
3458{
3459 struct op_context *op_ctx = ctx->cur_op_ctx;
3461
3462 time = item_array_at(&op_ctx->items, 0)->obj->integer;
3463
3464 if (op_ctx->op->code == UACPI_AML_OP_SleepOp) {
3465 /*
3466 * ACPICA doesn't allow sleeps longer than 2 seconds,
3467 * so we shouldn't either.
3468 */
3469 if (time > 2000)
3470 time = 2000;
3471
3475 } else {
3476 // Spec says this must evaluate to a ByteData
3477 if (time > 0xFF)
3478 time = 0xFF;
3480 }
3481
3482 return UACPI_STATUS_OK;
3483}
3484
3486{
3487 struct op_context *op_ctx = ctx->cur_op_ctx;
3488 uacpi_u64 src, dst = 0;
3489 uacpi_size i;
3490 uacpi_object *dst_obj;
3491
3492 src = item_array_at(&op_ctx->items, 0)->obj->integer;
3493 dst_obj = item_array_at(&op_ctx->items, 2)->obj;
3494 i = 64;
3495
3496 /*
3497 * NOTE: ACPICA just errors out for invalid BCD, but NT allows it just fine.
3498 * FromBCD matches NT behavior 1:1 even for invalid BCD, but ToBCD
3499 * produces different results when the input is too large.
3500 */
3501 if (op_ctx->op->code == UACPI_AML_OP_FromBCDOp) {
3502 do {
3503 i -= 4;
3504 dst *= 10;
3505 dst += (src >> i) & 0xF;
3506 } while (i);
3507 } else {
3508 while (src != 0) {
3509 dst >>= 4;
3510 i -= 4;
3511 dst |= (src % 10) << 60;
3512 src /= 10;
3513 }
3514
3515 dst >>= (i % 64);
3516 }
3517
3518 dst_obj->integer = dst;
3519 return UACPI_STATUS_OK;
3520}
3521
3523{
3525
3526 /*
3527 * Technically this doesn't exist in the wild, from the dumps that I have
3528 * the only user of the Unload opcode is the Surface Pro 3, which triggers
3529 * an unload of some I2C-related table as a response to some event.
3530 *
3531 * This op has been long deprecated by the specification exactly because
3532 * it hasn't really been used by anyone and the fact that it introduces
3533 * an enormous layer of complexity, which no driver is really prepared to
3534 * deal with (aka namespace nodes disappearing under its feet).
3535 *
3536 * Just pretend we have actually unloaded whatever the AML asked for, if it
3537 * ever tries to re-load this table that will just skip opcodes that create
3538 * already existing objects, which should be good enough and mostly
3539 * transparent to the AML.
3540 */
3541 uacpi_warn("refusing to unload a table from AML");
3542 return UACPI_STATUS_OK;
3543}
3544
3546{
3547 struct op_context *op_ctx = ctx->cur_op_ctx;
3548 uacpi_object *src, *dst;
3549
3550 src = item_array_at(&op_ctx->items, 0)->obj;
3551 dst = item_array_at(&op_ctx->items, 1)->obj;
3552
3553 dst->type = UACPI_OBJECT_INTEGER;
3554 dst->integer = src->integer ? 0 : ones();
3555
3556 return UACPI_STATUS_OK;
3557}
3558
3560{
3562
3563 if (lhs->type == UACPI_OBJECT_STRING || lhs->type == UACPI_OBJECT_BUFFER) {
3564 res = lhs->buffer->size == rhs->buffer->size;
3565
3566 if (res && lhs->buffer->size) {
3567 res = uacpi_memcmp(
3568 lhs->buffer->data,
3569 rhs->buffer->data,
3570 lhs->buffer->size
3571 ) == 0;
3572 }
3573 } else if (lhs->type == UACPI_OBJECT_INTEGER) {
3574 res = lhs->integer == rhs->integer;
3575 }
3576
3577 return res;
3578}
3579
3582)
3583{
3584 if (lhs->type == UACPI_OBJECT_STRING || lhs->type == UACPI_OBJECT_BUFFER) {
3585 int res;
3586 uacpi_buffer *lhs_buf, *rhs_buf;
3587
3588 lhs_buf = lhs->buffer;
3589 rhs_buf = rhs->buffer;
3590
3591 res = uacpi_memcmp(lhs_buf->data, rhs_buf->data,
3592 UACPI_MIN(lhs_buf->size, rhs_buf->size));
3593 if (res == 0) {
3594 if (lhs_buf->size < rhs_buf->size)
3595 res = -1;
3596 else if (lhs_buf->size > rhs_buf->size)
3597 res = 1;
3598 }
3599
3600 if (op == UACPI_AML_OP_LLessOp)
3601 return res < 0;
3602
3603 return res > 0;
3604 }
3605
3606 if (op == UACPI_AML_OP_LLessOp)
3607 return lhs->integer < rhs->integer;
3608
3609 return lhs->integer > rhs->integer;
3610}
3611
3613{
3614 struct op_context *op_ctx = ctx->cur_op_ctx;
3615 uacpi_aml_op op = op_ctx->op->code;
3616 uacpi_object *lhs, *rhs, *dst;
3618
3619 lhs = item_array_at(&op_ctx->items, 0)->obj;
3620 rhs = item_array_at(&op_ctx->items, 1)->obj;
3621 dst = item_array_at(&op_ctx->items, 2)->obj;
3622
3623 switch (op) {
3624 case UACPI_AML_OP_LEqualOp:
3625 case UACPI_AML_OP_LLessOp:
3626 case UACPI_AML_OP_LGreaterOp:
3627 // TODO: typecheck at parse time
3628 if (lhs->type != rhs->type) {
3630 "don't know how to do a logical comparison of '%s' and '%s'",
3633 );
3635 }
3636
3637 if (op == UACPI_AML_OP_LEqualOp)
3638 res = handle_logical_equality(lhs, rhs);
3639 else
3641 break;
3642 default: {
3643 uacpi_u64 lhs_int, rhs_int;
3644
3645 // NT only looks at the first 4 bytes of a buffer
3646 lhs_int = object_to_integer(lhs, 4);
3647 rhs_int = object_to_integer(rhs, 4);
3648
3649 if (op == UACPI_AML_OP_LandOp)
3650 res = lhs_int && rhs_int;
3651 else
3652 res = lhs_int || rhs_int;
3653 break;
3654 }
3655 }
3656
3657 dst->integer = res ? ones() : 0;
3658 return UACPI_STATUS_OK;
3659}
3660
3662 MTR = 0,
3663 MEQ = 1,
3664 MLE = 2,
3665 MLT = 3,
3666 MGE = 4,
3667 MGT = 5,
3668};
3669
3671{
3672 switch (op) {
3673 case MTR:
3674 return UACPI_TRUE;
3675 case MEQ:
3676 return lhs == rhs;
3677 case MLE:
3678 return lhs <= rhs;
3679 case MLT:
3680 return lhs < rhs;
3681 case MGE:
3682 return lhs >= rhs;
3683 case MGT:
3684 return lhs > rhs;
3685 default:
3686 return UACPI_FALSE;
3687 }
3688}
3689
3691{
3692 struct op_context *op_ctx = ctx->cur_op_ctx;
3693 uacpi_package *pkg;
3694 uacpi_u64 operand0, operand1, start_idx, i;
3695 enum match_op mop0, mop1;
3697
3698 pkg = item_array_at(&op_ctx->items, 0)->obj->package;
3699 mop0 = item_array_at(&op_ctx->items, 1)->immediate;
3700 operand0 = item_array_at(&op_ctx->items, 2)->obj->integer;
3701 mop1 = item_array_at(&op_ctx->items, 3)->immediate;
3702 operand1 = item_array_at(&op_ctx->items, 4)->obj->integer;
3703 start_idx = item_array_at(&op_ctx->items, 5)->obj->integer;
3704 dst = item_array_at(&op_ctx->items, 6)->obj;
3705
3706 for (i = start_idx; i < pkg->count; ++i) {
3707 uacpi_object *obj = pkg->objects[i];
3708
3709 if (obj->type != UACPI_OBJECT_INTEGER)
3710 continue;
3711
3712 if (match_one(mop0, obj->integer, operand0) &&
3713 match_one(mop1, obj->integer, operand1))
3714 break;
3715 }
3716
3717 if (i < pkg->count)
3718 dst->integer = i;
3719 else
3720 dst->integer = ones();
3721
3722 return UACPI_STATUS_OK;
3723}
3724
3725/*
3726 * PkgLength :=
3727 * PkgLeadByte |
3728 * <pkgleadbyte bytedata> |
3729 * <pkgleadbyte bytedata bytedata> | <pkgleadbyte bytedata bytedata bytedata>
3730 * PkgLeadByte :=
3731 * <bit 7-6: bytedata count that follows (0-3)>
3732 * <bit 5-4: only used if pkglength < 63>
3733 * <bit 3-0: least significant package length nybble>
3734 */
3736 struct package_length *out_pkg)
3737{
3739 uacpi_u8 *data, marker_length;
3740
3741 out_pkg->begin = frame->code_offset;
3742 marker_length = 1;
3743
3745 if (uacpi_unlikely(left < 1))
3747
3748 data = call_frame_cursor(frame);
3749 marker_length += *data >> 6;
3750
3751 if (uacpi_unlikely(left < marker_length))
3753
3754 switch (marker_length) {
3755 case 1:
3756 size = *data & 0x3F;
3757 break;
3758 case 2:
3759 case 3:
3760 case 4: {
3761 uacpi_u32 temp_byte = 0;
3762
3763 size = *data & 0xF;
3764 uacpi_memcpy(&temp_byte, data + 1, marker_length - 1);
3765
3766 // marker_length - 1 is at most 3, so this shift is safe
3767 size |= temp_byte << 4;
3768 break;
3769 }
3770 }
3771
3772 frame->code_offset += marker_length;
3773
3774 out_pkg->end = out_pkg->begin + size;
3775 if (uacpi_unlikely(out_pkg->end < out_pkg->begin)) {
3777 "PkgLength overflow: start=%u, size=%u", out_pkg->begin, size
3778 );
3780 }
3781
3782 return UACPI_STATUS_OK;
3783}
3784
3785/*
3786 * ByteData
3787 * // bit 0-2: ArgCount (0-7)
3788 * // bit 3: SerializeFlag
3789 * // 0 NotSerialized
3790 * // 1 Serialized
3791 * // bit 4-7: SyncLevel (0x00-0x0f)
3792 */
3794{
3795 method->args = flags_byte & 0x7;
3796 method->is_serialized = (flags_byte >> 3) & 1;
3797 method->sync_level = flags_byte >> 4;
3798}
3799
3801{
3802 struct op_context *op_ctx = ctx->cur_op_ctx;
3803 struct uacpi_control_method *this_method, *method;
3804 struct package_length *pkg;
3805 struct uacpi_namespace_node *node;
3806 struct uacpi_object *dst;
3807 uacpi_u32 method_begin_offset, method_size;
3808
3809 this_method = ctx->cur_frame->method;
3810 pkg = &item_array_at(&op_ctx->items, 0)->pkg;
3811 node = item_array_at(&op_ctx->items, 1)->node;
3812 method_begin_offset = item_array_at(&op_ctx->items, 3)->immediate;
3813
3814 if (uacpi_unlikely(pkg->end < pkg->begin ||
3815 pkg->end < method_begin_offset ||
3816 pkg->end > this_method->size)) {
3818 "invalid method %.4s bounds [%u..%u] (parent size is %u)",
3819 node->name.text, method_begin_offset, pkg->end, this_method->size
3820 );
3822 }
3823
3824 dst = item_array_at(&op_ctx->items, 4)->obj;
3825
3826 method = dst->method;
3827 method_size = pkg->end - method_begin_offset;
3828
3829 if (method_size) {
3830 method->code = uacpi_kernel_alloc(method_size);
3831 if (uacpi_unlikely(method->code == UACPI_NULL))
3833
3835 method->code,
3836 ctx->cur_frame->method->code + method_begin_offset,
3837 method_size
3838 );
3839 method->size = method_size;
3840 method->owns_code = 1;
3841 }
3842
3843 init_method_flags(method, item_array_at(&op_ctx->items, 2)->immediate);
3844
3846 dst);
3847 if (uacpi_unlikely(node->object == UACPI_NULL))
3849
3850 return UACPI_STATUS_OK;
3851}
3852
3854{
3855 struct op_context *op_ctx = ctx->cur_op_ctx;
3858
3859 node = item_array_at(&op_ctx->items, 0)->node;
3860
3861 if (op_ctx->op->code == UACPI_AML_OP_MutexOp) {
3862 dst = item_array_at(&op_ctx->items, 2)->obj;
3863
3864 // bits 0-3: SyncLevel (0x00-0x0f), bits 4-7: Reserved (must be 0)
3865 dst->mutex->sync_level = item_array_at(&op_ctx->items, 1)->immediate;
3866 dst->mutex->sync_level &= 0xF;
3867 } else {
3868 dst = item_array_at(&op_ctx->items, 1)->obj;
3869 }
3870
3873 dst
3874 );
3875 if (uacpi_unlikely(node->object == UACPI_NULL))
3877
3878 return UACPI_STATUS_OK;
3879}
3880
3882{
3883 struct op_context *op_ctx = ctx->cur_op_ctx;
3885
3887 item_array_at(&op_ctx->items, 0)->obj
3888 );
3889 if (uacpi_unlikely(obj->type != UACPI_OBJECT_EVENT)) {
3891 "%s: invalid argument '%s', expected an Event object",
3892 op_ctx->op->name, uacpi_object_type_to_string(obj->type)
3893 );
3895 }
3896
3897 switch (op_ctx->op->code)
3898 {
3899 case UACPI_AML_OP_SignalOp:
3900 uacpi_signal_native_event(obj->event->handle);
3901 break;
3902 case UACPI_AML_OP_ResetOp:
3903 uacpi_reset_native_event(obj->event->handle);
3904 break;
3905 case UACPI_AML_OP_WaitOp: {
3908
3909 timeout = item_array_at(&op_ctx->items, 1)->obj->integer;
3910 if (timeout > 0xFFFF)
3911 timeout = 0xFFFF;
3912
3913 /*
3914 * The namespace is unlocked while we wait, which makes it possible
3915 * for someone else to get rid of the object, e.g. by overwriting it
3916 * via CopyObject. All of the references that we have to it are gone
3917 * if that happens, so take one that is ours alone.
3918 */
3920
3922 ret = uacpi_wait_for_native_event(obj->event->handle, timeout);
3924
3926
3927 /*
3928 * The return value here is inverted, we return 0 for success and Ones
3929 * for timeout and everything else.
3930 */
3931 if (ret)
3932 item_array_at(&op_ctx->items, 2)->obj->integer = 0;
3933 break;
3934 }
3935 default:
3937 }
3938
3939 return UACPI_STATUS_OK;
3940}
3941
3943{
3944 struct op_context *op_ctx = ctx->cur_op_ctx;
3946
3948 item_array_at(&op_ctx->items, 0)->obj
3949 );
3950 if (uacpi_unlikely(obj->type != UACPI_OBJECT_MUTEX)) {
3952 "%s: invalid argument '%s', expected a Mutex object",
3953 op_ctx->op->name, uacpi_object_type_to_string(obj->type)
3954 );
3956 }
3957
3958 switch (op_ctx->op->code)
3959 {
3960 case UACPI_AML_OP_AcquireOp: {
3962 uacpi_u64 *return_value;
3964
3965 return_value = &item_array_at(&op_ctx->items, 2)->obj->integer;
3966
3967 if (uacpi_unlikely(ctx->sync_level > obj->mutex->sync_level)) {
3968 uacpi_warn(
3969 "ignoring attempt to acquire mutex @%p with a lower sync level "
3970 "(%d < %d)", obj->mutex, obj->mutex->sync_level,
3971 ctx->sync_level
3972 );
3973 break;
3974 }
3975
3976 timeout = item_array_at(&op_ctx->items, 1)->immediate;
3977 if (timeout > 0xFFFF)
3978 timeout = 0xFFFF;
3979
3983 *return_value = 0;
3984 break;
3985 }
3986
3987 /*
3988 * The namespace is unlocked while we wait for the mutex, which makes
3989 * it possible for someone else to get rid of the object, e.g. by
3990 * overwriting it via CopyObject. All of the references that we have
3991 * to it are gone if that happens, so take one that is ours alone.
3992 */
3994
3997 ret = held_mutexes_array_push(&ctx->held_mutexes, obj->mutex);
4001 return ret;
4002 }
4003
4004 ctx->sync_level = obj->mutex->sync_level;
4005 *return_value = 0;
4006 }
4007
4009 break;
4010 }
4011
4012 case UACPI_AML_OP_ReleaseOp: {
4014
4016 uacpi_warn(
4017 "attempted to release not-previously-acquired mutex object "
4018 "@%p (%p)", obj->mutex, obj->mutex->handle
4019 );
4020 break;
4021 }
4022
4024 &ctx->held_mutexes, obj->mutex,
4026 );
4028 uacpi_mutex **last_mutex;
4029
4030 last_mutex = held_mutexes_array_last(&ctx->held_mutexes);
4031 if (last_mutex == UACPI_NULL) {
4032 ctx->sync_level = 0;
4033 break;
4034 }
4035
4036 ctx->sync_level = (*last_mutex)->sync_level;
4037 }
4038 break;
4039 }
4040
4041 default:
4043 }
4044
4045 return UACPI_STATUS_OK;
4046}
4047
4049{
4051 struct op_context *op_ctx = ctx->cur_op_ctx;
4052 struct uacpi_namespace_node *node;
4054
4055 node = item_array_at(&op_ctx->items, 0)->node;
4056 value = item_array_at(&op_ctx->items, 1)->obj->integer;
4057
4060 return ret;
4061
4063 const uacpi_char *path;
4064
4066 uacpi_warn(
4067 "ignoring firmware Notify(%s, 0x%"UACPI_PRIX64") request, "
4068 "no listeners", path, UACPI_FMT64(value)
4069 );
4071
4072 return UACPI_STATUS_OK;
4073 }
4074
4076 uacpi_error("Notify() called on an invalid object %.4s",
4077 node->name.text);
4079 }
4080
4081 return ret;
4082}
4083
4085{
4086 struct op_context *op_ctx = ctx->cur_op_ctx;
4087 uacpi_firmware_request req = { 0 };
4088
4089 switch (op_ctx->op->code) {
4090 case UACPI_AML_OP_BreakPointOp:
4092 req.breakpoint.ctx = ctx;
4093 break;
4094 case UACPI_AML_OP_FatalOp:
4096 req.fatal.type = item_array_at(&op_ctx->items, 0)->immediate;
4097 req.fatal.code = item_array_at(&op_ctx->items, 1)->immediate;
4098 req.fatal.arg = item_array_at(&op_ctx->items, 2)->obj->integer;
4099 break;
4100 default:
4102 }
4103
4107
4108 return UACPI_STATUS_OK;
4109}
4110
4112{
4113 struct op_context *op_ctx = ctx->cur_op_ctx;
4114 struct uacpi_namespace_node *node;
4116
4117 node = item_array_at(&op_ctx->items, 0)->node;
4118 src = item_array_at(&op_ctx->items, 1)->obj;
4119
4121 src);
4122 if (uacpi_unlikely(node->object == UACPI_NULL))
4124
4125 return UACPI_STATUS_OK;
4126}
4127
4130)
4131{
4132 if (field->bit_length > (g_uacpi_rt_ctx.is_rev1 ? 32u : 64u) ||
4133 field->force_buffer)
4134 return UACPI_OBJECT_BUFFER;
4135
4136 return UACPI_OBJECT_INTEGER;
4137}
4138
4141)
4142{
4143 if (obj->type == UACPI_OBJECT_BUFFER_FIELD) {
4144 *out_type = buffer_field_get_read_type(&obj->buffer_field);
4145 return UACPI_STATUS_OK;
4146 }
4147
4148 return uacpi_field_unit_get_read_type(obj->field_unit, out_type);
4149}
4150
4153)
4154{
4155 uacpi_size bit_length;
4156
4157 if (obj->type == UACPI_OBJECT_BUFFER_FIELD) {
4158 bit_length = obj->buffer_field.bit_length;
4159 } else {
4161
4162 ret = uacpi_field_unit_get_bit_length(obj->field_unit, &bit_length);
4164 return ret;
4165 }
4166
4168 return UACPI_STATUS_OK;
4169}
4170
4172{
4173 uacpi_object *src, *unwound_src, *dst;
4174 uacpi_object_type read_type;
4175 bool is_field;
4177
4178 struct op_context *op_ctx = ctx->cur_op_ctx;
4179
4180 src = item_array_at(&op_ctx->items, 0)->obj;
4181 dst = item_array_at(&op_ctx->items, 1)->obj;
4182
4183 if (src->type == UACPI_OBJECT_BUFFER_INDEX) {
4184 uacpi_buffer_index *buf_idx = &src->buffer_index;
4185
4186 dst->type = UACPI_OBJECT_INTEGER;
4188 &dst->integer, buffer_index_cursor(buf_idx),
4189 sizeof(dst->integer), 1
4190 );
4191 return UACPI_STATUS_OK;
4192 }
4193
4194 /*
4195 * Explicit dereferencing [DerefOf] behavior:
4196 * Simply grabs the bottom-most object that is not a reference.
4197 * This mimics the behavior of NT Acpi.sys: any DerfOf fetches
4198 * the bottom-most reference. Note that this is different from
4199 * ACPICA where DerefOf dereferences one level.
4200 */
4201 unwound_src = reference_unwind(src)->inner_object;
4202 is_field = uacpi_object_is_one_of(
4203 unwound_src,
4205 );
4206
4207 /*
4208 * If the object is a field, find out how to read it and transform this
4209 * DerefOf into a field read op. Otherwise, simply assign this object to the
4210 * destination.
4211 */
4212 if (is_field) {
4213 uacpi_aml_op new_op;
4214
4215 ret = field_get_read_type(unwound_src, &read_type);
4218 "unable to perform a read from field %p: "
4219 "parent opregion gone", unwound_src
4220 );
4221 return ret;
4222 }
4223
4224 switch (read_type) {
4226 new_op = UACPI_AML_OP_InternalOpReadFieldAsBuffer;
4227 break;
4229 new_op = UACPI_AML_OP_InternalOpReadFieldAsInteger;
4230 break;
4231 default:
4233 }
4234
4235 op_ctx->op = uacpi_get_op_spec(new_op);
4236 op_ctx->pc = 0;
4237
4238 uacpi_object_ref(unwound_src);
4239 item_array_at(&op_ctx->items, 0)->obj = unwound_src;
4241
4242 /*
4243 * A proper destination object will be allocated by the op we have just
4244 * switched to. This one is not needed anymore.
4245 */
4247 item_array_pop(&op_ctx->items);
4248
4249 return UACPI_STATUS_OK;
4250 }
4251
4252 return uacpi_object_assign(
4253 dst, unwound_src,
4255 );
4256}
4257
4259{
4261 struct op_context *op_ctx = ctx->cur_op_ctx;
4262 struct item *src_item;
4263 uacpi_object *src_obj, *dst_obj;
4264 uacpi_size dst_size;
4265 void *dst = UACPI_NULL;
4266 uacpi_data_view wtr_response = { 0 };
4267
4268 src_item = item_array_at(&op_ctx->items, 0);
4269
4270 /*
4271 * Source may be a namespace node or an object depending on how we ended up
4272 * here, check explicitly.
4273 */
4274 if (src_item->type == ITEM_NAMESPACE_NODE) {
4276
4277 node = item_array_at(&op_ctx->items, 0)->node;
4279 } else {
4280 src_obj = src_item->obj;
4281 }
4282
4283 dst_obj = item_array_at(&op_ctx->items, 1)->obj;
4284
4285 if (op_ctx->op->code == UACPI_AML_OP_InternalOpReadFieldAsBuffer) {
4287
4288 ret = field_byte_size(src_obj, &dst_size);
4290 return ret;
4291
4292 if (dst_size != 0) {
4293 buf = dst_obj->buffer;
4294
4295 dst = uacpi_kernel_alloc_zeroed(dst_size);
4296 if (dst == UACPI_NULL)
4298
4299 buf->data = dst;
4300 buf->size = dst_size;
4301 }
4302 } else {
4303 dst = &dst_obj->integer;
4304 dst_size = sizeof(uacpi_u64);
4305 }
4306
4307 if (src_obj->type == UACPI_OBJECT_BUFFER_FIELD) {
4309 return UACPI_STATUS_OK;
4310 }
4311
4313 src_obj->field_unit, dst, dst_size, &wtr_response
4314 );
4316 return ret;
4317
4318 if (wtr_response.data != UACPI_NULL) {
4320
4321 buf = dst_obj->buffer;
4322 buf->data = wtr_response.data;
4323 buf->size = wtr_response.length;
4324 }
4325
4326 return ret;
4327}
4328
4330{
4331 struct op_context *op_ctx = ctx->cur_op_ctx;
4332 struct uacpi_namespace_node *node;
4333 uacpi_buffer *src_buf;
4334 uacpi_object *field_obj;
4336
4337 /*
4338 * Layout of items here:
4339 * [0] -> Type checked source buffer object
4340 * [1] -> Byte/bit index integer object
4341 * [2] ( if CreateField) -> bit length integer object
4342 * [3] (2 if not CreateField) -> the new namespace node
4343 * [4] (3 if not CreateField) -> the buffer field object we're creating here
4344 */
4345 src_buf = item_array_at(&op_ctx->items, 0)->obj->buffer;
4346
4347 if (op_ctx->op->code == UACPI_AML_OP_CreateFieldOp) {
4348 uacpi_object *idx_obj, *len_obj;
4349
4350 idx_obj = item_array_at(&op_ctx->items, 1)->obj;
4351 len_obj = item_array_at(&op_ctx->items, 2)->obj;
4352 node = item_array_at(&op_ctx->items, 3)->node;
4353 field_obj = item_array_at(&op_ctx->items, 4)->obj;
4354 field = &field_obj->buffer_field;
4355
4356 field->bit_index = idx_obj->integer;
4357
4358 /*
4359 * NT allows a length of 0, the result is a buffer field that's never
4360 * read from or written to.
4361 */
4362 if (uacpi_unlikely(len_obj->integer > 0xFFFFFFFF)) {
4364 "invalid bit field length (%"UACPI_PRIu64")",
4365 UACPI_FMT64(len_obj->integer)
4366 );
4368 }
4369
4370 field->bit_length = len_obj->integer;
4371 field->force_buffer = UACPI_TRUE;
4372 } else {
4373 uacpi_object *idx_obj;
4374
4375 idx_obj = item_array_at(&op_ctx->items, 1)->obj;
4376 node = item_array_at(&op_ctx->items, 2)->node;
4377 field_obj = item_array_at(&op_ctx->items, 3)->obj;
4378 field = &field_obj->buffer_field;
4379
4380 field->bit_index = idx_obj->integer;
4381 switch (op_ctx->op->code) {
4382 case UACPI_AML_OP_CreateBitFieldOp:
4383 field->bit_length = 1;
4384 break;
4385 case UACPI_AML_OP_CreateByteFieldOp:
4386 field->bit_length = 8;
4387 break;
4388 case UACPI_AML_OP_CreateWordFieldOp:
4389 field->bit_length = 16;
4390 break;
4391 case UACPI_AML_OP_CreateDWordFieldOp:
4392 field->bit_length = 32;
4393 break;
4394 case UACPI_AML_OP_CreateQWordFieldOp:
4395 field->bit_length = 64;
4396 break;
4397 default:
4399 }
4400
4401 if (op_ctx->op->code != UACPI_AML_OP_CreateBitFieldOp)
4402 field->bit_index *= 8;
4403 }
4404
4405 if (uacpi_unlikely((field->bit_index + field->bit_length) >
4406 src_buf->size * 8)) {
4408 "invalid buffer field: bits [%zu..%zu], buffer size is %zu bytes",
4409 field->bit_index, field->bit_index + field->bit_length,
4410 src_buf->size
4411 );
4413 }
4414
4415 field->backing = src_buf;
4416 uacpi_shareable_ref(field->backing);
4418 field_obj);
4419 if (uacpi_unlikely(node->object == UACPI_NULL))
4421
4422 return UACPI_STATUS_OK;
4423}
4424
4426{
4427 struct call_frame *frame = ctx->cur_frame;
4428 struct op_context *op_ctx = ctx->cur_op_ctx;
4429
4430 if (uacpi_unlikely(frame->last_while_idx_plus_one == 0)) {
4432 "attempting to %s outside of a While block",
4433 op_ctx->op->code == UACPI_AML_OP_BreakOp ? "Break" : "Continue"
4434 );
4436 }
4437
4438 for (;;) {
4439 if (code_block_array_size(&frame->code_blocks) >
4440 frame->last_while_idx_plus_one) {
4441 frame_reset_post_end_block(ctx, ctx->cur_block->type);
4442 continue;
4443 }
4444
4445 if (op_ctx->op->code == UACPI_AML_OP_BreakOp)
4446 frame->code_offset = ctx->cur_block->end;
4447 else
4448 frame->code_offset = ctx->cur_block->begin;
4449 frame_reset_post_end_block(ctx, ctx->cur_block->type);
4450 break;
4451 }
4452
4453 return UACPI_STATUS_OK;
4454}
4455
4457{
4460
4461 node = item_array_at(&op_ctx->items, 1)->node;
4462 obj = item_array_last(&op_ctx->items)->obj;
4463
4464 switch (op_ctx->op->code) {
4465 case UACPI_AML_OP_ProcessorOp: {
4466 uacpi_processor *proc = obj->processor;
4467 proc->id = item_array_at(&op_ctx->items, 2)->immediate;
4468 proc->block_address = item_array_at(&op_ctx->items, 3)->immediate;
4469 proc->block_length = item_array_at(&op_ctx->items, 4)->immediate;
4470 break;
4471 }
4472
4473 case UACPI_AML_OP_PowerResOp: {
4474 uacpi_power_resource *power_res = &obj->power_resource;
4475 power_res->system_level = item_array_at(&op_ctx->items, 2)->immediate;
4476 power_res->resource_order = item_array_at(&op_ctx->items, 3)->immediate;
4477 break;
4478 }
4479
4480 default:
4481 break;
4482 }
4483
4485 obj);
4486 if (uacpi_unlikely(node->object == UACPI_NULL))
4488
4489 return UACPI_STATUS_OK;
4490}
4491
4493{
4494 struct op_context *op_ctx = ctx->cur_op_ctx;
4495
4496 switch (op_ctx->op->code) {
4497 case UACPI_AML_OP_ProcessorOp:
4498 case UACPI_AML_OP_PowerResOp:
4499 case UACPI_AML_OP_ThermalZoneOp:
4500 case UACPI_AML_OP_DeviceOp: {
4502
4503 ret = create_named_scope(op_ctx);
4505 return ret;
4506
4508 }
4509 case UACPI_AML_OP_ScopeOp:
4510 case UACPI_AML_OP_IfOp:
4511 case UACPI_AML_OP_ElseOp:
4512 case UACPI_AML_OP_WhileOp: {
4513 break;
4514 }
4515 default:
4517 }
4518
4519 return begin_block_execution(ctx);
4520}
4521
4523{
4526
4527 ctx->cur_frame->code_offset = ctx->cur_frame->method->size;
4529
4531 return ret;
4532 if (dst == UACPI_NULL)
4533 return UACPI_STATUS_OK;
4534
4535 /*
4536 * Should be possible to move here if method returns a literal
4537 * like Return(Buffer { ... }), otherwise we have to copy just to
4538 * be safe.
4539 */
4540 return uacpi_object_assign(
4541 dst,
4542 item_array_at(&ctx->cur_op_ctx->items, 0)->obj,
4544 );
4545}
4546
4548{
4549 struct call_frame *frame = ctx->cur_frame;
4550
4551 if (frame == UACPI_NULL) {
4552 ctx->cur_op_ctx = UACPI_NULL;
4553 ctx->prev_op_ctx = UACPI_NULL;
4554 ctx->cur_block = UACPI_NULL;
4555 return;
4556 }
4557
4558 ctx->cur_op_ctx = op_context_array_last(&frame->pending_ops);
4559 ctx->prev_op_ctx = op_context_array_one_before_last(&frame->pending_ops);
4560 ctx->cur_block = code_block_array_last(&frame->code_blocks);
4561}
4562
4564{
4565 return ctx->cur_op_ctx && !ctx->cur_op_ctx->preempted;
4566}
4567
4572};
4573
4574static const uacpi_char *const op_trace_action_types[3] = {
4575 [OP_TRACE_ACTION_BEGIN] = "BEGIN",
4576 [OP_TRACE_ACTION_RESUME] = "RESUME",
4577 [OP_TRACE_ACTION_END] = "END",
4578};
4579
4580static inline void trace_op(
4581 const struct uacpi_op_spec *op, enum op_trace_action_type action
4582)
4583{
4585 "%s OP '%s' (0x%04X)",
4586 op_trace_action_types[action], op->name, op->code
4587 );
4588}
4589
4590static inline void trace_pop(uacpi_u8 pop)
4591{
4592 uacpi_debug(" pOP: %s (0x%02X)", uacpi_parse_op_to_string(pop), pop);
4593}
4594
4596 struct op_context *op_ctx)
4597{
4598 uacpi_size i;
4599
4600 /*
4601 * MethodCall items:
4602 * items[0] -> method namespace node
4603 * items[1] -> immediate that was used for parsing the arguments
4604 * items[2...nargs-1] -> method arguments
4605 * items[-1] -> return value object
4606 *
4607 * Here we only care about the arguments though.
4608 */
4609 for (i = 2; i < item_array_size(&op_ctx->items) - 1; i++) {
4610 uacpi_object *src, *dst;
4611
4612 src = item_array_at(&op_ctx->items, i)->obj;
4613
4617
4618 frame->args[i - 2] = dst;
4619 }
4620
4621 return UACPI_STATUS_OK;
4622}
4623
4625 uacpi_namespace_node *scope,
4627{
4628 struct code_block *block;
4629
4630 block = code_block_array_alloc(&frame->code_blocks);
4633
4634 block->type = CODE_BLOCK_SCOPE;
4635 block->node = scope;
4636 block->begin = 0;
4637 block->end = method->size;
4638 frame->cur_scope = scope;
4639 return UACPI_STATUS_OK;
4640}
4641
4643 struct call_frame **out_frame)
4644{
4645 struct call_frame_array *call_stack = &ctx->call_stack;
4646 struct call_frame *prev_frame;
4647
4648 *out_frame = call_frame_array_calloc(call_stack);
4649 if (uacpi_unlikely(*out_frame == UACPI_NULL))
4651
4652 /*
4653 * Allocating a new frame might have reallocated the dynamic buffer so our
4654 * execution_context members might now be pointing to freed memory.
4655 * Refresh them here.
4656 */
4657 prev_frame = call_frame_array_one_before_last(call_stack);
4658 ctx->cur_frame = prev_frame;
4660
4661 return UACPI_STATUS_OK;
4662}
4663
4665{
4666 struct code_block *block = ctx->cur_block;
4667 struct call_frame *cur_frame = ctx->cur_frame;
4668
4669 if (!block)
4670 return UACPI_FALSE;
4671 if (cur_frame->code_offset != block->end)
4672 return UACPI_FALSE;
4673
4674 if (block->type == CODE_BLOCK_WHILE)
4675 cur_frame->code_offset = block->begin;
4676
4678 return UACPI_TRUE;
4679}
4680
4683)
4684{
4686
4687 switch (dst->type) {
4688 case UACPI_OBJECT_DEBUG:
4689 ret = debug_store(src);
4690 break;
4692 ret = store_to_reference(dst, src, wtr_response);
4693 break;
4694
4697 ret = object_assign_with_implicit_cast(dst, src, wtr_response);
4698 break;
4699
4701 // NULL target
4702 if (dst->integer == 0) {
4704 break;
4705 }
4707 default:
4708 uacpi_error("attempted to store to an invalid target: %s",
4711 }
4712
4713 return ret;
4714}
4715
4717{
4718 uacpi_object *src, *dst;
4719 struct op_context *op_ctx = ctx->cur_op_ctx;
4720
4721 src = item_array_at(&op_ctx->items, 0)->obj;
4722 dst = item_array_at(&op_ctx->items, 1)->obj;
4723
4724 if (op_ctx->op->code == UACPI_AML_OP_StoreOp) {
4726 uacpi_data_view wtr_response = { 0 };
4727
4728 ret = store_to_target(dst, src, &wtr_response);
4730 return ret;
4731
4732 /*
4733 * This was a write-then-read field access since we got a response
4734 * buffer back from this store. Now we have to return this buffer
4735 * as a prvalue from the StoreOp so that it can be used by AML to
4736 * retrieve the response.
4737 */
4738 if (wtr_response.data != UACPI_NULL) {
4739 uacpi_object *wtr_response_obj;
4740
4741 wtr_response_obj = uacpi_create_object(UACPI_OBJECT_BUFFER);
4742 if (uacpi_unlikely(wtr_response_obj == UACPI_NULL)) {
4743 uacpi_free(wtr_response.data, wtr_response.length);
4745 }
4746
4747 wtr_response_obj->buffer->data = wtr_response.data;
4748 wtr_response_obj->buffer->size = wtr_response.length;
4749
4751 item_array_at(&op_ctx->items, 0)->obj = wtr_response_obj;
4752 }
4753
4754 return ret;
4755 }
4756
4757 if (dst->type != UACPI_OBJECT_REFERENCE)
4759
4761}
4762
4764{
4765 uacpi_object *src, *dst;
4766 struct op_context *op_ctx = ctx->cur_op_ctx;
4767 uacpi_object_type true_src_type;
4769
4770 src = item_array_at(&op_ctx->items, 0)->obj;
4771 dst = item_array_at(&op_ctx->items, 1)->obj;
4772
4773 if (src->type == UACPI_OBJECT_REFERENCE) {
4774 /*
4775 * Increment/Decrement are the only two operators that modify the value
4776 * in-place. Same as NT, fields are read no matter how many references
4777 * it takes to get to them, the result is written back the same way.
4778 */
4780 } // else buffer index
4781
4782 true_src_type = src->type;
4783
4784 switch (true_src_type) {
4786 dst->integer = src->integer;
4787 break;
4790 ret = field_get_read_type(src, &true_src_type);
4792 goto out_bad_type;
4793 if (true_src_type != UACPI_OBJECT_INTEGER)
4794 goto out_bad_type;
4795
4796 if (src->type == UACPI_OBJECT_FIELD_UNIT) {
4798 src->field_unit, &dst->integer, sizeof_int(),
4800 );
4802 return ret;
4803 } else {
4804 uacpi_read_buffer_field(&src->buffer_field, &dst->integer);
4805 }
4806 break;
4808 dst->integer = *buffer_index_cursor(&src->buffer_index);
4809 break;
4810 default:
4811 goto out_bad_type;
4812 }
4813
4814 if (op_ctx->op->code == UACPI_AML_OP_IncrementOp)
4815 dst->integer++;
4816 else
4817 dst->integer--;
4818
4819 return UACPI_STATUS_OK;
4820
4821out_bad_type:
4822 uacpi_error("Increment/Decrement: invalid object type '%s'",
4823 uacpi_object_type_to_string(true_src_type));
4825}
4826
4828 struct execution_context *ctx, struct call_frame *new_frame,
4830)
4831{
4833
4835 new_frame->method = method;
4836
4837 if (!method->is_serialized)
4838 return ret;
4839
4840 if (uacpi_unlikely(ctx->sync_level > method->sync_level)) {
4842 "cannot invoke method @%p, sync level %d is too low "
4843 "(current is %d)",
4844 method, method->sync_level, ctx->sync_level
4845 );
4847 }
4848
4849 if (method->mutex == UACPI_NULL) {
4850 method->mutex = uacpi_create_mutex();
4851 if (uacpi_unlikely(method->mutex == UACPI_NULL))
4853 method->mutex->sync_level = method->sync_level;
4854 }
4855
4857 ret = uacpi_acquire_aml_mutex(method->mutex, 0xFFFF);
4859 return ret;
4860
4861 ret = held_mutexes_array_push(&ctx->held_mutexes, method->mutex);
4864 return ret;
4865 }
4866 }
4867
4868 new_frame->prev_sync_level = ctx->sync_level;
4869 ctx->sync_level = method->sync_level;
4870 return UACPI_STATUS_OK;
4871}
4872
4874{
4875 struct call_frame *frame = ctx->cur_frame;
4876 struct op_context *op_ctx;
4877
4878 op_ctx = op_context_array_calloc(&frame->pending_ops);
4879 if (op_ctx == UACPI_NULL)
4881
4882 op_ctx->op = ctx->cur_op;
4884 return UACPI_STATUS_OK;
4885}
4886
4887static uacpi_bool pop_item(struct op_context *op_ctx)
4888{
4889 struct item *item;
4890
4891 if (item_array_size(&op_ctx->items) == 0)
4892 return UACPI_FALSE;
4893
4894 item = item_array_last(&op_ctx->items);
4895
4896 if (item->type == ITEM_OBJECT)
4898
4901
4902 item_array_pop(&op_ctx->items);
4903 return UACPI_TRUE;
4904}
4905
4906static void pop_op(struct execution_context *ctx)
4907{
4908 struct call_frame *frame = ctx->cur_frame;
4909 struct op_context *cur_op_ctx = ctx->cur_op_ctx;
4910
4911 while (pop_item(cur_op_ctx));
4912
4913 item_array_clear(&cur_op_ctx->items);
4914 op_context_array_pop(&frame->pending_ops);
4916}
4917
4918static void call_frame_clear(struct call_frame *frame)
4919{
4920 uacpi_size i;
4921 op_context_array_clear(&frame->pending_ops);
4922 code_block_array_clear(&frame->code_blocks);
4923
4924 while (temp_namespace_node_array_size(&frame->temp_nodes) != 0) {
4926
4927 node = *temp_namespace_node_array_last(&frame->temp_nodes);
4929 temp_namespace_node_array_pop(&frame->temp_nodes);
4930 }
4931 temp_namespace_node_array_clear(&frame->temp_nodes);
4932
4933 for (i = 0; i < 7; ++i)
4934 uacpi_object_unref(frame->args[i]);
4935 for (i = 0; i < 8; ++i)
4936 uacpi_object_unref(frame->locals[i]);
4937
4938 uacpi_method_unref(frame->method);
4939}
4940
4973};
4974
4975static const uacpi_u8 *op_decode_cursor(const struct op_context *ctx)
4976{
4977 const struct uacpi_op_spec *spec = ctx->op;
4978
4980 return &spec->indirect_decode_ops[ctx->pc];
4981
4982 return &spec->decode_ops[ctx->pc];
4983}
4984
4986{
4987 uacpi_u8 byte;
4988
4989 byte = *op_decode_cursor(ctx);
4990 ctx->pc++;
4991
4992 return byte;
4993}
4994
4996{
4997 uacpi_aml_op op = 0;
4998
4999 op |= op_decode_byte(op_ctx);
5000 op |= op_decode_byte(op_ctx) << 8;
5001
5002 return op;
5003}
5004
5005// MSVC doesn't support __VA_OPT__ so we do this weirdness
5006#define EXEC_OP_DO_LVL(lvl, reason, ...) \
5007 uacpi_##lvl("Op 0x%04X ('%s'): "reason, \
5008 op_ctx->op->code, op_ctx->op->name __VA_ARGS__)
5009
5010#define EXEC_OP_DO_ERR(reason, ...) EXEC_OP_DO_LVL(error, reason, __VA_ARGS__)
5011#define EXEC_OP_DO_WARN(reason, ...) EXEC_OP_DO_LVL(warn, reason, __VA_ARGS__)
5012
5013#define EXEC_OP_ERR_3(reason, arg0, arg1, arg2) \
5014 EXEC_OP_DO_ERR(reason, ,arg0, arg1, arg2)
5015#define EXEC_OP_ERR_2(reason, arg0, arg1) EXEC_OP_DO_ERR(reason, ,arg0, arg1)
5016#define EXEC_OP_ERR_1(reason, arg0) EXEC_OP_DO_ERR(reason, ,arg0)
5017#define EXEC_OP_ERR(reason) EXEC_OP_DO_ERR(reason)
5018
5019#define EXEC_OP_WARN(reason) EXEC_OP_DO_WARN(reason)
5020
5021#define SPEC_SIMPLE_NAME "SimpleName := NameString | ArgObj | LocalObj"
5022#define SPEC_SUPER_NAME \
5023 "SuperName := SimpleName | DebugObj | ReferenceTypeOpcode"
5024#define SPEC_TERM_ARG \
5025 "TermArg := ExpressionOpcode | DataObject | ArgObj | LocalObj"
5026#define SPEC_OPERAND "Operand := TermArg => Integer"
5027#define SPEC_STRING "String := TermArg => String"
5028#define SPEC_TARGET "Target := SuperName | NullName"
5029
5030#define SPEC_COMPUTATIONAL_DATA \
5031 "ComputationalData := ByteConst | WordConst | DWordConst | QWordConst " \
5032 "| String | ConstObj | RevisionOp | DefBuffer"
5033
5035{
5036 switch (op) {
5041 return UACPI_TRUE;
5042 default:
5043 return UACPI_FALSE;
5044 }
5045}
5046
5048{
5049 switch (op) {
5055 return UACPI_TRUE;
5056 default:
5057 return UACPI_FALSE;
5058 }
5059}
5060
5062{
5063 switch (op) {
5067 return UACPI_TRUE;
5068 default:
5069 return UACPI_FALSE;
5070 }
5071}
5072
5074{
5075 switch (op) {
5078 return UACPI_TRUE;
5079 default:
5080 return UACPI_FALSE;
5081 }
5082}
5083
5084static uacpi_status op_typecheck(const struct op_context *op_ctx,
5085 const struct op_context *cur_op_ctx)
5086{
5087 const uacpi_char *expected_type_str;
5088 uacpi_u8 ok_mask = 0;
5089 uacpi_u8 props = cur_op_ctx->op->properties;
5090
5091 switch (*op_decode_cursor(op_ctx)) {
5092 // SimpleName := NameString | ArgObj | LocalObj
5094 expected_type_str = SPEC_SIMPLE_NAME;
5096 break;
5097
5098 // Target := SuperName | NullName
5100 expected_type_str = SPEC_TARGET;
5102 break;
5103
5104 // SuperName := SimpleName | DebugObj | ReferenceTypeOpcode
5107 expected_type_str = SPEC_SUPER_NAME;
5108 ok_mask |= UACPI_OP_PROPERTY_SUPERNAME;
5109 break;
5110
5111 // TermArg := ExpressionOpcode | DataObject | ArgObj | LocalObj
5119 expected_type_str = SPEC_TERM_ARG;
5120 ok_mask |= UACPI_OP_PROPERTY_TERM_ARG;
5121 break;
5122 default:
5124 }
5125
5126 if (!(props & ok_mask)) {
5127 EXEC_OP_ERR_2("invalid argument: '%s', expected a %s",
5128 cur_op_ctx->op->name, expected_type_str);
5130 }
5131
5132 return UACPI_STATUS_OK;
5133}
5134
5136 const struct op_context *op_ctx,
5137 const uacpi_object *obj,
5138 enum uacpi_object_type expected_type,
5139 const uacpi_char *spec_desc
5140)
5141{
5142 if (uacpi_likely(obj->type == expected_type))
5143 return UACPI_STATUS_OK;
5144
5145 EXEC_OP_ERR_2("invalid argument type: %s, expected a %s",
5146 uacpi_object_type_to_string(obj->type), spec_desc);
5148}
5149
5151 const struct op_context *op_ctx,
5152 const uacpi_object *obj
5153)
5154{
5156}
5157
5159 const struct op_context *op_ctx,
5160 const uacpi_object *obj
5161)
5162{
5164}
5165
5167 const struct op_context *op_ctx,
5168 const uacpi_object *obj
5169)
5170{
5171 switch (obj->type) {
5175 return UACPI_STATUS_OK;
5176 default:
5178 "invalid argument type: %s, expected a %s",
5181 );
5183 }
5184}
5185
5186static void emit_op_skip_warn(const struct op_context *op_ctx)
5187{
5188 EXEC_OP_WARN("skipping due to previous errors");
5189}
5190
5192 struct call_frame *frame, uacpi_size offset, enum uacpi_parse_op op,
5194)
5195{
5196 static const uacpi_char *oom_prefix = "<...>";
5197 static const uacpi_char *empty_string = "";
5198 static const uacpi_char *unknown_path = "<unknown-path>";
5199 static const uacpi_char *invalid_path = "<invalid-path>";
5200
5201 uacpi_status conv_ret;
5202 const uacpi_char *action;
5203 const uacpi_char *requested_path_to_print;
5204 const uacpi_char *middle_part = UACPI_NULL;
5205 const uacpi_char *prefix_path = UACPI_NULL;
5206 uacpi_char *requested_path = UACPI_NULL;
5207 uacpi_size length = 0;
5208 uacpi_bool is_create;
5209
5210 is_create = op == UACPI_PARSE_OP_CREATE_NAMESTRING ||
5212
5213 if (is_create)
5214 action = "create";
5215 else
5216 action = "lookup";
5217
5218 conv_ret = name_string_to_path(
5219 frame, offset, &requested_path, &length
5220 );
5221 if (uacpi_unlikely_error(conv_ret)) {
5222 if (conv_ret == UACPI_STATUS_OUT_OF_MEMORY)
5223 requested_path_to_print = unknown_path;
5224 else
5225 requested_path_to_print = invalid_path;
5226 } else {
5227 requested_path_to_print = requested_path;
5228 }
5229
5230 if (requested_path && requested_path[0] != '\\') {
5232 frame->cur_scope
5233 );
5234 if (uacpi_unlikely(prefix_path == UACPI_NULL))
5235 prefix_path = oom_prefix;
5236
5237 if (prefix_path[1] != '\0')
5238 middle_part = ".";
5239 } else {
5240 prefix_path = empty_string;
5241 }
5242
5243 if (middle_part == UACPI_NULL)
5244 middle_part = empty_string;
5245
5246 if (length == 5 && !is_create) {
5248 level,
5249 "unable to %s named object '%s' within (or above) "
5250 "scope '%s': %s", action, requested_path_to_print,
5251 prefix_path, uacpi_status_to_string(ret)
5252 );
5253 } else {
5255 level,
5256 "unable to %s named object '%s%s%s': %s",
5257 action, prefix_path, middle_part,
5258 requested_path_to_print, uacpi_status_to_string(ret)
5259 );
5260 }
5261
5262 uacpi_free(requested_path, length);
5263 if (prefix_path != oom_prefix && prefix_path != empty_string)
5264 uacpi_free_dynamic_string(prefix_path);
5265}
5266
5268{
5269 struct op_context *op_ctx = ctx->cur_op_ctx;
5270
5271 EXEC_OP_ERR("no dedicated handler installed");
5273}
5274
5322};
5323
5325 /*
5326 * All OPs that don't have a handler dispatch to here if
5327 * UACPI_PARSE_OP_INVOKE_HANDLER is reached.
5328 */
5375};
5376
5378 [UACPI_AML_OP_Local0Op] = OP_HANDLER_LOCAL,
5379 [UACPI_AML_OP_Local1Op] = OP_HANDLER_LOCAL,
5380 [UACPI_AML_OP_Local2Op] = OP_HANDLER_LOCAL,
5381 [UACPI_AML_OP_Local3Op] = OP_HANDLER_LOCAL,
5382 [UACPI_AML_OP_Local4Op] = OP_HANDLER_LOCAL,
5383 [UACPI_AML_OP_Local5Op] = OP_HANDLER_LOCAL,
5384 [UACPI_AML_OP_Local6Op] = OP_HANDLER_LOCAL,
5385 [UACPI_AML_OP_Local7Op] = OP_HANDLER_LOCAL,
5386
5387 [UACPI_AML_OP_Arg0Op] = OP_HANDLER_ARG,
5388 [UACPI_AML_OP_Arg1Op] = OP_HANDLER_ARG,
5389 [UACPI_AML_OP_Arg2Op] = OP_HANDLER_ARG,
5390 [UACPI_AML_OP_Arg3Op] = OP_HANDLER_ARG,
5391 [UACPI_AML_OP_Arg4Op] = OP_HANDLER_ARG,
5392 [UACPI_AML_OP_Arg5Op] = OP_HANDLER_ARG,
5393 [UACPI_AML_OP_Arg6Op] = OP_HANDLER_ARG,
5394
5395 [UACPI_AML_OP_StringPrefix] = OP_HANDLER_STRING,
5396
5397 [UACPI_AML_OP_AddOp] = OP_HANDLER_BINARY_MATH,
5398 [UACPI_AML_OP_SubtractOp] = OP_HANDLER_BINARY_MATH,
5399 [UACPI_AML_OP_MultiplyOp] = OP_HANDLER_BINARY_MATH,
5400 [UACPI_AML_OP_DivideOp] = OP_HANDLER_BINARY_MATH,
5401 [UACPI_AML_OP_ShiftLeftOp] = OP_HANDLER_BINARY_MATH,
5402 [UACPI_AML_OP_ShiftRightOp] = OP_HANDLER_BINARY_MATH,
5403 [UACPI_AML_OP_AndOp] = OP_HANDLER_BINARY_MATH,
5404 [UACPI_AML_OP_NandOp] = OP_HANDLER_BINARY_MATH,
5405 [UACPI_AML_OP_OrOp] = OP_HANDLER_BINARY_MATH,
5406 [UACPI_AML_OP_NorOp] = OP_HANDLER_BINARY_MATH,
5407 [UACPI_AML_OP_XorOp] = OP_HANDLER_BINARY_MATH,
5408 [UACPI_AML_OP_ModOp] = OP_HANDLER_BINARY_MATH,
5409
5410 [UACPI_AML_OP_IfOp] = OP_HANDLER_CODE_BLOCK,
5411 [UACPI_AML_OP_ElseOp] = OP_HANDLER_CODE_BLOCK,
5412 [UACPI_AML_OP_WhileOp] = OP_HANDLER_CODE_BLOCK,
5413 [UACPI_AML_OP_ScopeOp] = OP_HANDLER_CODE_BLOCK,
5414
5415 [UACPI_AML_OP_ContinueOp] = OP_HANDLER_CONTROL_FLOW,
5416 [UACPI_AML_OP_BreakOp] = OP_HANDLER_CONTROL_FLOW,
5417
5418 [UACPI_AML_OP_ReturnOp] = OP_HANDLER_RETURN,
5419
5420 [UACPI_AML_OP_MethodOp] = OP_HANDLER_CREATE_METHOD,
5421
5422 [UACPI_AML_OP_StoreOp] = OP_HANDLER_COPY_OBJECT_OR_STORE,
5423 [UACPI_AML_OP_CopyObjectOp] = OP_HANDLER_COPY_OBJECT_OR_STORE,
5424
5425 [UACPI_AML_OP_IncrementOp] = OP_HANDLER_INC_DEC,
5426 [UACPI_AML_OP_DecrementOp] = OP_HANDLER_INC_DEC,
5427
5428 [UACPI_AML_OP_RefOfOp] = OP_HANDLER_REF_OF,
5429 [UACPI_AML_OP_DerefOfOp] = OP_HANDLER_DEREF_OF,
5430
5431 [UACPI_AML_OP_LnotOp] = OP_HANDLER_LOGICAL_NOT,
5432
5433 [UACPI_AML_OP_LEqualOp] = OP_HANDLER_BINARY_LOGIC,
5434 [UACPI_AML_OP_LandOp] = OP_HANDLER_BINARY_LOGIC,
5435 [UACPI_AML_OP_LorOp] = OP_HANDLER_BINARY_LOGIC,
5436 [UACPI_AML_OP_LGreaterOp] = OP_HANDLER_BINARY_LOGIC,
5437 [UACPI_AML_OP_LLessOp] = OP_HANDLER_BINARY_LOGIC,
5438
5439 [UACPI_AML_OP_InternalOpNamedObject] = OP_HANDLER_NAMED_OBJECT,
5440 [UACPI_AML_OP_InternalOpDerefNamedObject] = OP_HANDLER_DEREF_OF,
5441
5442 [UACPI_AML_OP_BufferOp] = OP_HANDLER_BUFFER,
5443
5444 [UACPI_AML_OP_PackageOp] = OP_HANDLER_PACKAGE,
5445 [UACPI_AML_OP_VarPackageOp] = OP_HANDLER_PACKAGE,
5446
5447 [UACPI_AML_OP_NameOp] = OP_HANDLER_CREATE_NAMED,
5448
5449 [UACPI_AML_OP_CreateBitFieldOp] = OP_HANDLER_CREATE_BUFFER_FIELD,
5450 [UACPI_AML_OP_CreateByteFieldOp] = OP_HANDLER_CREATE_BUFFER_FIELD,
5451 [UACPI_AML_OP_CreateWordFieldOp] = OP_HANDLER_CREATE_BUFFER_FIELD,
5452 [UACPI_AML_OP_CreateDWordFieldOp] = OP_HANDLER_CREATE_BUFFER_FIELD,
5453 [UACPI_AML_OP_CreateQWordFieldOp] = OP_HANDLER_CREATE_BUFFER_FIELD,
5454
5455 [UACPI_AML_OP_InternalOpReadFieldAsBuffer] = OP_HANDLER_READ_FIELD,
5456 [UACPI_AML_OP_InternalOpReadFieldAsInteger] = OP_HANDLER_READ_FIELD,
5457
5458 [UACPI_AML_OP_ToIntegerOp] = OP_HANDLER_TO,
5459 [UACPI_AML_OP_ToBufferOp] = OP_HANDLER_TO,
5460 [UACPI_AML_OP_ToDecimalStringOp] = OP_HANDLER_TO,
5461 [UACPI_AML_OP_ToHexStringOp] = OP_HANDLER_TO,
5462 [UACPI_AML_OP_ToStringOp] = OP_HANDLER_TO_STRING,
5463
5464 [UACPI_AML_OP_AliasOp] = OP_HANDLER_ALIAS,
5465
5466 [UACPI_AML_OP_ConcatOp] = OP_HANDLER_CONCATENATE,
5467 [UACPI_AML_OP_ConcatResOp] = OP_HANDLER_CONCATENATE_RES,
5468
5469 [UACPI_AML_OP_SizeOfOp] = OP_HANDLER_SIZEOF,
5470
5471 [UACPI_AML_OP_NotOp] = OP_HANDLER_UNARY_MATH,
5472 [UACPI_AML_OP_FindSetLeftBitOp] = OP_HANDLER_UNARY_MATH,
5473 [UACPI_AML_OP_FindSetRightBitOp] = OP_HANDLER_UNARY_MATH,
5474
5475 [UACPI_AML_OP_IndexOp] = OP_HANDLER_INDEX,
5476
5477 [UACPI_AML_OP_ObjectTypeOp] = OP_HANDLER_OBJECT_TYPE,
5478
5479 [UACPI_AML_OP_MidOp] = OP_HANDLER_MID,
5480
5481 [UACPI_AML_OP_MatchOp] = OP_HANDLER_MATCH,
5482
5483 [UACPI_AML_OP_NotifyOp] = OP_HANDLER_NOTIFY,
5484
5485 [UACPI_AML_OP_BreakPointOp] = OP_HANDLER_FIRMWARE_REQUEST,
5486};
5487
5488#define EXT_OP_IDX(op) (op & 0xFF)
5489
5491 [EXT_OP_IDX(UACPI_AML_OP_CreateFieldOp)] = OP_HANDLER_CREATE_BUFFER_FIELD,
5492 [EXT_OP_IDX(UACPI_AML_OP_CondRefOfOp)] = OP_HANDLER_REF_OF,
5493 [EXT_OP_IDX(UACPI_AML_OP_OpRegionOp)] = OP_HANDLER_CREATE_OP_REGION,
5494 [EXT_OP_IDX(UACPI_AML_OP_DeviceOp)] = OP_HANDLER_CODE_BLOCK,
5495 [EXT_OP_IDX(UACPI_AML_OP_ProcessorOp)] = OP_HANDLER_CODE_BLOCK,
5496 [EXT_OP_IDX(UACPI_AML_OP_PowerResOp)] = OP_HANDLER_CODE_BLOCK,
5497 [EXT_OP_IDX(UACPI_AML_OP_ThermalZoneOp)] = OP_HANDLER_CODE_BLOCK,
5498 [EXT_OP_IDX(UACPI_AML_OP_TimerOp)] = OP_HANDLER_TIMER,
5499 [EXT_OP_IDX(UACPI_AML_OP_MutexOp)] = OP_HANDLER_CREATE_MUTEX_OR_EVENT,
5500 [EXT_OP_IDX(UACPI_AML_OP_EventOp)] = OP_HANDLER_CREATE_MUTEX_OR_EVENT,
5501
5502 [EXT_OP_IDX(UACPI_AML_OP_FieldOp)] = OP_HANDLER_CREATE_FIELD,
5503 [EXT_OP_IDX(UACPI_AML_OP_IndexFieldOp)] = OP_HANDLER_CREATE_FIELD,
5504 [EXT_OP_IDX(UACPI_AML_OP_BankFieldOp)] = OP_HANDLER_CREATE_FIELD,
5505
5506 [EXT_OP_IDX(UACPI_AML_OP_FromBCDOp)] = OP_HANDLER_BCD,
5507 [EXT_OP_IDX(UACPI_AML_OP_ToBCDOp)] = OP_HANDLER_BCD,
5508
5509 [EXT_OP_IDX(UACPI_AML_OP_DataRegionOp)] = OP_HANDLER_CREATE_DATA_REGION,
5510
5511 [EXT_OP_IDX(UACPI_AML_OP_LoadTableOp)] = OP_HANDLER_LOAD_TABLE,
5512 [EXT_OP_IDX(UACPI_AML_OP_LoadOp)] = OP_HANDLER_LOAD,
5513 [EXT_OP_IDX(UACPI_AML_OP_UnloadOp)] = OP_HANDLER_UNLOAD,
5514
5515 [EXT_OP_IDX(UACPI_AML_OP_StallOp)] = OP_HANDLER_STALL_OR_SLEEP,
5516 [EXT_OP_IDX(UACPI_AML_OP_SleepOp)] = OP_HANDLER_STALL_OR_SLEEP,
5517
5518 [EXT_OP_IDX(UACPI_AML_OP_SignalOp)] = OP_HANDLER_EVENT_CTL,
5519 [EXT_OP_IDX(UACPI_AML_OP_ResetOp)] = OP_HANDLER_EVENT_CTL,
5520 [EXT_OP_IDX(UACPI_AML_OP_WaitOp)] = OP_HANDLER_EVENT_CTL,
5521
5522 [EXT_OP_IDX(UACPI_AML_OP_AcquireOp)] = OP_HANDLER_MUTEX_CTL,
5523 [EXT_OP_IDX(UACPI_AML_OP_ReleaseOp)] = OP_HANDLER_MUTEX_CTL,
5524
5525 [EXT_OP_IDX(UACPI_AML_OP_FatalOp)] = OP_HANDLER_FIRMWARE_REQUEST,
5526};
5527
5532};
5533
5538)
5539{
5541 struct call_frame *frame;
5542
5543 if (uacpi_unlikely(call_frame_array_size(&ctx->call_stack) >=
5544 g_uacpi_rt_ctx.max_call_stack_depth))
5546
5547 ret = push_new_frame(ctx, &frame);
5549 return ret;
5550
5551 ret = enter_method(ctx, frame, method);
5553 goto method_dispatch_error;
5554
5555 if (type == METHOD_CALL_NATIVE) {
5556 uacpi_u8 arg_count;
5557
5558 arg_count = args ? args->count : 0;
5559 if (uacpi_unlikely(arg_count != method->args)) {
5561 "invalid number of arguments %zu to call %.4s, expected %d",
5562 args ? args->count : 0, node->name.text, method->args
5563 );
5564
5566 goto method_dispatch_error;
5567 }
5568
5569 if (args != UACPI_NULL) {
5570 uacpi_u8 i;
5571
5572 for (i = 0; i < method->args; ++i) {
5573 frame->args[i] = args->objects[i];
5574 uacpi_object_ref(args->objects[i]);
5575 }
5576 }
5577 } else if (type == METHOD_CALL_AML) {
5578 ret = frame_push_args(frame, ctx->cur_op_ctx);
5580 goto method_dispatch_error;
5581 }
5582
5585 goto method_dispatch_error;
5586
5587 ctx->cur_frame = frame;
5588 ctx->cur_op_ctx = UACPI_NULL;
5589 ctx->prev_op_ctx = UACPI_NULL;
5590 ctx->cur_block = code_block_array_last(&ctx->cur_frame->code_blocks);
5591
5592 if (method->native_call) {
5594
5597 goto method_dispatch_error;
5598
5599 return method->handler(ctx, retval);
5600 }
5601
5602 return UACPI_STATUS_OK;
5603
5604method_dispatch_error:
5605 call_frame_clear(frame);
5606 call_frame_array_pop(&ctx->call_stack);
5607 return ret;
5608}
5609
5611 struct call_frame *frame, struct op_context *op_ctx
5612)
5613{
5614 struct item *item;
5615
5616 if (op_ctx->tracked_pkg_idx == 0)
5617 return;
5618
5619 item = item_array_at(&op_ctx->items, op_ctx->tracked_pkg_idx - 1);
5620 frame->code_offset = item->pkg.end;
5621}
5622
5624{
5626 struct call_frame *frame = ctx->cur_frame;
5627 struct op_context *op_ctx;
5628 struct item *item = UACPI_NULL;
5629 enum uacpi_parse_op prev_op = 0, op;
5630
5631 /*
5632 * Allocate a new op context if previous is preempted (looking for a
5633 * dynamic argument), or doesn't exist at all.
5634 */
5636 ret = push_op(ctx);
5638 return ret;
5639 } else {
5640 trace_op(ctx->cur_op_ctx->op, OP_TRACE_ACTION_RESUME);
5641 }
5642
5643 if (ctx->prev_op_ctx)
5644 prev_op = *op_decode_cursor(ctx->prev_op_ctx);
5645
5646 for (;;) {
5648 return ret;
5649
5650 op_ctx = ctx->cur_op_ctx;
5651 frame = ctx->cur_frame;
5652
5653 if (op_ctx->pc == 0 && ctx->prev_op_ctx) {
5654 /*
5655 * Type check the current arg type against what is expected by the
5656 * preempted op. This check is able to catch most type violations
5657 * with the only exception being Operand as we only know whether
5658 * that evaluates to an integer after the fact.
5659 */
5660 ret = op_typecheck(ctx->prev_op_ctx, ctx->cur_op_ctx);
5662 return ret;
5663 }
5664
5665 op = op_decode_byte(op_ctx);
5666 trace_pop(op);
5667
5669 item = item_array_alloc(&op_ctx->items);
5672
5674 if (item->type == ITEM_OBJECT) {
5676
5678 type = op_decode_byte(op_ctx);
5679
5683 } else {
5685 }
5686 } else if (item == UACPI_NULL) {
5687 item = item_array_last(&op_ctx->items);
5688 }
5689
5690 switch (op) {
5691 case UACPI_PARSE_OP_END:
5693 trace_op(ctx->cur_op_ctx->op, OP_TRACE_ACTION_END);
5694
5696 uacpi_u8 idx;
5697
5698 idx = op_decode_byte(op_ctx);
5699 if (item_array_at(&op_ctx->items, idx)->handle != UACPI_NULL)
5700 break;
5701
5702 emit_op_skip_warn(op_ctx);
5703 }
5704
5705 apply_tracked_pkg(frame, op_ctx);
5706
5707 pop_op(ctx);
5708 if (ctx->cur_op_ctx) {
5709 ctx->cur_op_ctx->preempted = UACPI_FALSE;
5710 ctx->cur_op_ctx->pc++;
5711 }
5712
5713 return UACPI_STATUS_OK;
5714 }
5715
5717 emit_op_skip_warn(op_ctx);
5718 break;
5719
5720 case UACPI_PARSE_OP_TARGET: {
5721 uacpi_aml_op next_op;
5722
5723 /*
5724 * Target := SuperName | NullName, and a null target has no use
5725 * for an object, so don't bother executing it as ZeroOp.
5726 */
5727 if (peek_next_op(frame, &next_op) == 1 &&
5728 next_op == UACPI_AML_OP_ZeroOp) {
5729 frame->code_offset++;
5730 break;
5731 }
5733 }
5744 /*
5745 * Preempt this op parsing for now as we wait for the dynamic arg
5746 * to be parsed.
5747 */
5748 op_ctx->preempted = UACPI_TRUE;
5749 op_ctx->pc--;
5750 return UACPI_STATUS_OK;
5751
5753 op_ctx->tracked_pkg_idx = item_array_size(&op_ctx->items);
5756 ret = parse_package_length(frame, &item->pkg);
5757 break;
5758
5761 void *dst;
5762 uacpi_u8 src_width;
5763
5766 dst = &item->obj->integer;
5767 src_width = 8;
5768 } else {
5769 dst = &item->immediate;
5770 src_width = op_decode_byte(op_ctx);
5771 }
5772
5774 dst, op_decode_cursor(op_ctx),
5775 sizeof(uacpi_u64), src_width
5776 );
5777 op_ctx->pc += src_width;
5778 break;
5779 }
5780
5782 break;
5783
5787 void *dst;
5788
5789 width = op_decode_byte(op_ctx);
5792
5795 item->obj->integer = 0;
5796 dst = &item->obj->integer;
5797 } else {
5799 }
5800
5802 frame->code_offset += width;
5803 break;
5804 }
5805
5809 obj->type = UACPI_OBJECT_INTEGER;
5810 obj->integer = op == UACPI_PARSE_OP_LOAD_FALSE_OBJECT ? 0 : ones();
5811 break;
5812 }
5813
5815 item->immediate = frame->code_offset;
5816 break;
5817
5820 break;
5821
5823 uacpi_object_type expected_type;
5824
5825 expected_type = op_decode_byte(op_ctx);
5826
5827 if (uacpi_unlikely(item->obj->type != expected_type)) {
5828 EXEC_OP_ERR_2("bad object type: expected %s, got %s!",
5829 uacpi_object_type_to_string(expected_type),
5832 }
5833
5834 break;
5835 }
5836
5838 uacpi_object_type_bits expected_mask = 0;
5839 uacpi_bool one_of;
5841 uacpi_u8 num_types, i;
5842
5843 num_types = op_decode_byte(op_ctx);
5844 for (i = 0; i < num_types; i++) {
5845 type = op_decode_byte(op_ctx);
5846 if (i < UACPI_ARRAY_SIZE(types))
5847 types[i] = type;
5848
5849 expected_mask |= 1u << type;
5850 }
5851
5852 one_of = uacpi_object_is_one_of(item->obj, expected_mask);
5853 if (uacpi_likely(one_of))
5854 break;
5855
5857
5858 if (i == 2) {
5860 "bad object type: expected one of %s/%s, got %s!",
5864 );
5865 break;
5866 }
5867
5869 "bad object type: expected one of 0x%08X, got %s!",
5870 expected_mask, uacpi_object_type_to_string(item->obj->type)
5871 );
5872 break;
5873 }
5874
5876 frame->code_offset--;
5877 break;
5878
5880 item_array_at(&op_ctx->items, op_decode_byte(op_ctx))->immediate--;
5881 break;
5882
5884 pop_item(op_ctx);
5885 item = item_array_last(&op_ctx->items);
5886 break;
5887
5889 uacpi_size pkg_idx = op_ctx->tracked_pkg_idx - 1;
5890 struct package_length *pkg;
5891 uacpi_u8 bytes_skip;
5892
5893 bytes_skip = op_decode_byte(op_ctx);
5894 pkg = &item_array_at(&op_ctx->items, pkg_idx)->pkg;
5895
5896 if (frame->code_offset >= pkg->end)
5897 op_ctx->pc += bytes_skip;
5898
5899 break;
5900 }
5901
5906 uacpi_u8 idx, bytes_skip;
5907 uacpi_bool is_null, skip_if_null;
5908
5912 } else {
5913 idx = op_decode_byte(op_ctx);
5914 is_null = item_array_at(&op_ctx->items, idx)->handle == UACPI_NULL;
5915 }
5916
5917 bytes_skip = op_decode_byte(op_ctx);
5918 skip_if_null = op == UACPI_PARSE_OP_IF_NOT_NULL ||
5920
5921 if (is_null == skip_if_null)
5922 op_ctx->pc += bytes_skip;
5923
5924 break;
5925 }
5926
5928 uacpi_u8 value, bytes_skip;
5929
5930 value = op_decode_byte(op_ctx);
5931 bytes_skip = op_decode_byte(op_ctx);
5932
5933 if (item->immediate != value)
5934 op_ctx->pc += bytes_skip;
5935
5936 break;
5937 }
5938
5941 uacpi_u8 bytes_skip;
5942 uacpi_bool is_false, skip_if_false;
5943
5944 bytes_skip = op_decode_byte(op_ctx);
5945 is_false = item->obj->integer == 0;
5946 skip_if_false = op == UACPI_PARSE_OP_IF_LAST_TRUE;
5947
5948 if (is_false == skip_if_false)
5949 op_ctx->pc += bytes_skip;
5950
5951 break;
5952 }
5953
5954 case UACPI_PARSE_OP_JMP: {
5955 op_ctx->pc = op_decode_byte(op_ctx);
5956 break;
5957 }
5958
5964 uacpi_size offset = frame->code_offset;
5965 enum resolve_behavior behavior;
5966
5970 else
5972
5973 ret = resolve_name_string(frame, behavior, &item->node);
5974
5975 if (ret == UACPI_STATUS_NOT_FOUND) {
5976 uacpi_bool is_ok;
5977
5978 if (prev_op) {
5979 is_ok = op_allows_unresolved(prev_op);
5980 is_ok &= op_allows_unresolved(op);
5981 } else {
5982 // This is the only standalone op where we allow unresolved
5983 is_ok = op_ctx->op->code == UACPI_AML_OP_ExternalOp;
5984 }
5985
5986 if (is_ok)
5988 }
5989
5992 uacpi_status trace_ret = ret;
5993 uacpi_bool abort_whileif = UACPI_FALSE;
5994
5995 if (frame->method->named_objects_persist &&
5998 struct op_context *first_ctx;
5999
6000 first_ctx = op_context_array_at(&frame->pending_ops, 0);
6001 abort_whileif = first_ctx->op->code == UACPI_AML_OP_WhileOp ||
6002 first_ctx->op->code == UACPI_AML_OP_IfOp;
6003
6004 if (op_allows_unresolved_if_load(op) || abort_whileif) {
6005 lvl = UACPI_LOG_WARN;
6007 }
6008 }
6009
6011 frame, offset, op, trace_ret, lvl
6012 );
6013
6014 if (abort_whileif) {
6015 while (op_context_array_size(&frame->pending_ops) != 1)
6016 pop_op(ctx);
6017
6018 op_ctx = op_context_array_at(&frame->pending_ops, 0);
6019 op_ctx->pc++;
6020 op_ctx->preempted = UACPI_FALSE;
6021 break;
6022 }
6023
6026 }
6027
6030 !frame->method->named_objects_persist)
6032
6033 break;
6034 }
6035
6037 uacpi_aml_op code = op_ctx->op->code;
6038 uacpi_u8 idx;
6039
6040 if (code <= 0xFF)
6042 else
6044
6045 ret = op_handlers[idx](ctx);
6046 break;
6047 }
6048
6050 item = item_array_at(&op_ctx->items, op_decode_byte(op_ctx));
6051 ret = do_install_node_item(frame, item);
6053 uacpi_object_unref(item->node->object);
6054 item->node->object = UACPI_NULL;
6055 }
6056 break;
6057
6061 struct item *dst;
6062
6063 if (!ctx->prev_op_ctx)
6064 break;
6065
6066 switch (prev_op) {
6072
6073 if (prev_op == UACPI_PARSE_OP_OPERAND)
6074 ret = typecheck_operand(ctx->prev_op_ctx, src);
6075 else if (prev_op == UACPI_PARSE_OP_STRING)
6076 ret = typecheck_string(ctx->prev_op_ctx, src);
6077 else if (prev_op == UACPI_PARSE_OP_COMPUTATIONAL_DATA)
6078 ret = typecheck_computational_data(ctx->prev_op_ctx, src);
6079
6080 break;
6083 src = item->obj;
6084 break;
6085
6091 src = item->obj;
6092 break;
6093
6094 default:
6095 EXEC_OP_ERR_1("don't know how to copy/transfer object to %u",
6096 prev_op);
6098 break;
6099 }
6100
6102 dst = item_array_last(&ctx->prev_op_ctx->items);
6103 dst->type = ITEM_OBJECT;
6104
6106 dst->obj = src;
6107 uacpi_object_ref(dst->obj);
6108 } else {
6110 if (uacpi_unlikely(dst->obj == UACPI_NULL)) {
6112 break;
6113 }
6114
6117 }
6118 }
6119 break;
6120 }
6121
6124 uacpi_object *dst, *src;
6125
6126 dst = item_array_at(&op_ctx->items, op_decode_byte(op_ctx))->obj;
6127
6129 src = item_array_at(&op_ctx->items,
6130 op_decode_byte(op_ctx))->obj;
6131 } else {
6132 src = item->obj;
6133 }
6134
6135 // Null target
6136 if (dst == UACPI_NULL)
6137 break;
6138
6140 break;
6141 }
6142
6143 // Nothing to do here, object is allocated automatically
6147 break;
6148
6152 enum uacpi_assign_behavior behavior;
6153
6154 item_array_pop(&op_ctx->items);
6155 item = item_array_last(&op_ctx->items);
6156
6157 // An Index() of a package must keep referring to the same slot
6160 break;
6161 }
6162
6165 else
6167
6168 ret = uacpi_object_assign(temp, item->obj, behavior);
6170 break;
6171
6173 item->obj = temp;
6174 break;
6175 }
6176
6178 struct uacpi_namespace_node *node;
6180
6181 node = item_array_at(&op_ctx->items, 0)->node;
6183
6186 );
6187 return ret;
6188 }
6189
6191 struct uacpi_namespace_node *node;
6193
6194 node = item_array_at(&op_ctx->items, 0)->node;
6195 method = item_array_at(&op_ctx->items, 1)->obj->method;
6196
6199 );
6200 return ret;
6201 }
6202
6204 uacpi_aml_op new_op = UACPI_AML_OP_InternalOpNamedObject;
6206
6207 if (item->node == UACPI_NULL) {
6208 if (!op_allows_unresolved(prev_op))
6210 break;
6211 }
6212
6214
6215 switch (obj->type) {
6216 case UACPI_OBJECT_METHOD: {
6217 uacpi_bool should_invoke;
6218
6219 switch (prev_op) {
6222 should_invoke = UACPI_FALSE;
6223 break;
6224 default:
6225 should_invoke = !op_wants_supername(prev_op);
6226 }
6227
6228 if (!should_invoke)
6229 break;
6230
6231 new_op = UACPI_AML_OP_InternalOpMethodCall0Args;
6232 new_op += obj->method->args;
6233 break;
6234 }
6235
6236 /*
6237 * A named object that holds a reference is an alias of whatever
6238 * it refers to on NT, so reading it reads that instead.
6239 */
6242 if (!op_wants_term_arg_or_operand(prev_op))
6243 break;
6244
6247 item->obj = obj;
6249
6250 new_op = UACPI_AML_OP_InternalOpDerefNamedObject;
6251 break;
6252
6256
6257 if (!op_wants_term_arg_or_operand(prev_op))
6258 break;
6259
6262 const uacpi_char *field_path;
6263
6265 item->node
6266 );
6267
6269 "unable to perform a read from field %s: "
6270 "parent opregion gone", field_path
6271 );
6272 uacpi_free_absolute_path(field_path);
6273 }
6274
6275 switch (type) {
6277 new_op = UACPI_AML_OP_InternalOpReadFieldAsBuffer;
6278 break;
6280 new_op = UACPI_AML_OP_InternalOpReadFieldAsInteger;
6281 break;
6282 default:
6284 continue;
6285 }
6286 break;
6287 }
6288 default:
6289 break;
6290 }
6291
6292 op_ctx->pc = 0;
6293 op_ctx->op = uacpi_get_op_spec(new_op);
6294 break;
6295 }
6296
6298 uacpi_aml_op next_op, target_op;
6299 uacpi_u32 cur_offset;
6300 uacpi_u8 op_length;
6301
6302 cur_offset = frame->code_offset;
6303 apply_tracked_pkg(frame, op_ctx);
6304 op_length = peek_next_op(frame, &next_op);
6305
6306 target_op = op_decode_aml_op(op_ctx);
6307 if (op_length == 0 || next_op != target_op) {
6308 // Revert tracked package
6309 frame->code_offset = cur_offset;
6310 break;
6311 }
6312
6313 frame->code_offset += op_length;
6314 op_ctx->switched_from = op_ctx->op->code;
6315 op_ctx->op = uacpi_get_op_spec(target_op);
6316 op_ctx->pc = 0;
6317 break;
6318 }
6319
6321 uacpi_aml_op target_op;
6322 uacpi_u8 skip_bytes;
6323
6324 target_op = op_decode_aml_op(op_ctx);
6325 skip_bytes = op_decode_byte(op_ctx);
6326
6327 if (op_ctx->switched_from != target_op)
6328 op_ctx->pc += skip_bytes;
6329 break;
6330 }
6331
6332 default:
6333 EXEC_OP_ERR_1("unhandled parser op '%u'", op);
6335 break;
6336 }
6337 }
6338}
6339
6341{
6342 uacpi_control_method *method = ctx->cur_frame->method;
6343
6344 if (method->is_serialized) {
6346 &ctx->held_mutexes, method->mutex, FORCE_RELEASE_YES
6347 );
6348 ctx->sync_level = ctx->cur_frame->prev_sync_level;
6349 }
6350
6351 call_frame_clear(ctx->cur_frame);
6352 call_frame_array_pop(&ctx->call_stack);
6353
6354 ctx->cur_frame = call_frame_array_last(&ctx->call_stack);
6356}
6357
6360 uacpi_u32 aml_offset, uacpi_u32 method_size, const uacpi_char *op
6361)
6362{
6363 static const uacpi_char *unknown_path = "<unknown>";
6364 uacpi_char oom_absolute_path[9] = "<?>.";
6365
6366 const uacpi_char *absolute_path;
6367
6368 if (block != UACPI_NULL && block->type == CODE_BLOCK_SCOPE) {
6370 if (uacpi_unlikely(absolute_path == UACPI_NULL))
6371 uacpi_memcpy(oom_absolute_path + 4, block->node->name.text, 4);
6372 } else {
6373 absolute_path = unknown_path;
6374 }
6375
6377 " #%zu in %s()+%u/%u at %s",
6378 depth, absolute_path, aml_offset, method_size, op
6379 );
6380
6381 if (absolute_path != oom_absolute_path && absolute_path != unknown_path)
6382 uacpi_free_dynamic_string(absolute_path);
6383}
6384
6386{
6388 uacpi_bool should_stop;
6389
6390 /*
6391 * Non-empty call stack here means the execution was aborted at some point,
6392 * probably due to a bytecode error.
6393 */
6394 depth = call_frame_array_size(&ctx->call_stack);
6395
6396 if (depth != 0) {
6397 uacpi_size idx = 0;
6398 uacpi_bool table_level_code;
6399 const struct uacpi_op_spec *op;
6400 const uacpi_char *op_name;
6401
6402 do {
6403 op = UACPI_NULL;
6404 table_level_code = ctx->cur_frame->method->named_objects_persist;
6405
6406 if (table_level_code && idx != 0)
6407 /*
6408 * This isn't the first frame that we are aborting.
6409 * If this is table-level code, we have just unwound a call
6410 * chain that had triggered an abort. Stop here, no need to
6411 * abort table load because of it.
6412 */
6413 break;
6414
6415 while (op_context_array_size(&ctx->cur_frame->pending_ops) != 0) {
6416 if (op == UACPI_NULL)
6417 op = op_context_array_last(
6418 &ctx->cur_frame->pending_ops
6419 )->op;
6420
6421 pop_op(ctx);
6422 }
6423
6424 /*
6425 * For the very first frame, fetch the opcode from the execution
6426 * context directly if we got nothing from the pending_ops array.
6427 * The reason we do this is because in case this was an invalid
6428 * opcode it won't actually end up in the pending_ops array at all.
6429 * This is only possible for the first frame, since all the frames
6430 * below are guaranteed to be either in MethodCallOp or
6431 * Load{Table}Op.
6432 */
6433 if (op == UACPI_NULL && idx == 0)
6434 op = ctx->cur_op;
6435
6436 if (uacpi_likely(op != UACPI_NULL)) {
6437 op_name = op->name;
6438
6439 if (op_is_internal(op))
6440 /*
6441 * All internal OPs are prefixed with this, strip to
6442 * make them look nicer in the backtrace.
6443 */
6444 op_name += sizeof("InternalOp") - 1;
6445 } else {
6446 op_name = "<unknown>";
6447 }
6448
6450 code_block_array_at(&ctx->cur_frame->code_blocks, 0), idx,
6451 ctx->cur_frame->code_offset, ctx->cur_frame->method->size,
6452 op_name
6453 );
6454
6455 should_stop = idx++ == 0 && table_level_code;
6457 } while (--depth && !should_stop);
6458 }
6459}
6460
6462{
6463 if (ctx->ret)
6464 uacpi_object_unref(ctx->ret);
6465
6466 while (held_mutexes_array_size(&ctx->held_mutexes) != 0) {
6468 &ctx->held_mutexes,
6469 *held_mutexes_array_last(&ctx->held_mutexes),
6471 );
6472 }
6473
6474 call_frame_array_clear(&ctx->call_stack);
6475 held_mutexes_array_clear(&ctx->held_mutexes);
6476 uacpi_free(ctx, sizeof(*ctx));
6477}
6478
6481 const uacpi_object_array *args, uacpi_object **out_obj
6482)
6483{
6485 struct execution_context *ctx;
6486
6487 ctx = uacpi_kernel_alloc_zeroed(sizeof(*ctx));
6490
6491 if (out_obj != UACPI_NULL) {
6493 if (uacpi_unlikely(ctx->ret == UACPI_NULL)) {
6495 goto out;
6496 }
6497 }
6498
6501 goto out;
6502
6503 for (;;) {
6505 if (ctx->cur_frame == UACPI_NULL)
6506 break;
6507
6508 if (maybe_end_block(ctx))
6509 continue;
6510
6511 if (!call_frame_has_code(ctx->cur_frame)) {
6513 continue;
6514 }
6515
6516 ret = get_op(ctx);
6518 goto handle_method_abort;
6519
6521 }
6522
6523 ret = exec_op(ctx);
6525 goto handle_method_abort;
6526
6527 continue;
6528
6529 handle_method_abort:
6530 uacpi_error("aborting %s due to previous error: %s",
6531 ctx->cur_frame->method->named_objects_persist ?
6532 "table load" : "method invocation",
6535
6536 /*
6537 * Having a frame here implies that we just aborted a dynamic table
6538 * load. Signal to the caller that it failed by setting the return
6539 * value to false.
6540 */
6541 if (ctx->cur_frame) {
6542 struct item *it;
6543
6544 it = item_array_last(&ctx->cur_op_ctx->items);
6545 if (it != UACPI_NULL && it->obj != UACPI_NULL)
6546 it->obj->integer = 0;
6547 }
6548 }
6549
6550out:
6551 if (ctx->ret != UACPI_NULL) {
6552 uacpi_object *ret_obj = UACPI_NULL;
6553
6554 if (ctx->ret->type != UACPI_OBJECT_UNINITIALIZED) {
6555 ret_obj = ctx->ret;
6556 uacpi_object_ref(ret_obj);
6557 }
6558
6559 *out_obj = ret_obj;
6560 }
6561
6563 return ret;
6564}
6565
6567{
6568 struct execution_context *ctx = handle;
6569 uacpi_bool is_supported;
6572
6573 arg = uacpi_unwrap_internal_reference(ctx->cur_frame->args[0]);
6574 if (arg->type != UACPI_OBJECT_STRING) {
6575 uacpi_error("_OSI: invalid argument type %s, expected a String",
6578 }
6579
6580 if (retval == UACPI_NULL)
6581 return UACPI_STATUS_OK;
6582
6584
6585 ret = uacpi_handle_osi(arg->buffer->text, &is_supported);
6587 return ret;
6588
6589 retval->integer = is_supported ? ones() : 0;
6590
6591 uacpi_trace("_OSI(%s) => reporting as %ssupported",
6592 arg->buffer->text, is_supported ? "" : "un");
6593 return UACPI_STATUS_OK;
6594}
6595
6596#endif // !UACPI_BAREBONES_MODE
static unsigned char bytes[4]
Definition: adnsresfilter.c:74
void user(int argc, const char *argv[])
Definition: cmds.c:1350
uacpi_status uacpi_acquire_aml_mutex(uacpi_mutex *, uacpi_u16 timeout)
Definition: mutex.c:199
static void uacpi_signal_native_event(uacpi_handle evt)
Definition: mutex.h:95
static void uacpi_reset_native_event(uacpi_handle evt)
Definition: mutex.h:106
uacpi_status uacpi_release_aml_mutex(uacpi_mutex *)
Definition: mutex.c:239
uacpi_bool uacpi_this_thread_owns_aml_mutex(uacpi_mutex *)
Definition: mutex.c:191
static uacpi_bool uacpi_wait_for_native_event(uacpi_handle evt, uacpi_u16 timeout)
Definition: mutex.h:88
UINT op
Definition: effect.c:235
unsigned int idx
Definition: utils.c:40
static void cleanup(void)
Definition: main.c:1335
BOOL force
Definition: metahost.c:100
method
Definition: dragdrop.c:54
#define ACPI_SMALL_ITEM_NAME_IDX
Definition: acpi.h:1225
struct uacpi_runtime_context g_uacpi_rt_ctx
Definition: uacpi.c:18
static uacpi_bool uacpi_should_log(enum uacpi_log_level lvl)
Definition: context.h:95
#define UACPI_ARRAY_SIZE(arr)
Definition: helpers.h:5
#define UACPI_UNUSED(x)
Definition: helpers.h:7
uacpi_size uacpi_round_up_bits_to_bytes(uacpi_size bit_length)
Definition: io.c:11
void uacpi_write_buffer_field(uacpi_buffer_field *field, const void *src, uacpi_size size)
Definition: io.c:152
uacpi_status uacpi_field_unit_get_bit_length(struct uacpi_field_unit *field, uacpi_size *out_length)
Definition: io.c:786
uacpi_status uacpi_write_field_unit_in_chunks(uacpi_field_unit *field, const void *src, uacpi_size size, uacpi_data_view *wtr_response)
Definition: io.c:746
void uacpi_read_buffer_field(const uacpi_buffer_field *field, void *dst)
Definition: io.c:113
uacpi_status uacpi_field_unit_get_read_type(struct uacpi_field_unit *field, uacpi_object_type *out_type)
Definition: io.c:757
uacpi_status uacpi_read_field_unit(uacpi_field_unit *field, void *dst, uacpi_size size, uacpi_data_view *wtr_response)
Definition: io.c:558
uacpi_status uacpi_write_field_unit(uacpi_field_unit *field, const void *src, uacpi_size size, uacpi_data_view *wtr_response)
Definition: io.c:738
#define uacpi_trace(...)
Definition: log.h:33
#define uacpi_error(...)
Definition: log.h:36
#define uacpi_warn(...)
Definition: log.h:35
#define uacpi_log_lvl(lvl, fmt,...)
Definition: log.h:22
#define uacpi_debug(...)
Definition: log.h:32
void uacpi_namespace_node_unref(uacpi_namespace_node *node)
Definition: namespace.c:294
uacpi_status uacpi_namespace_do_for_each_child(uacpi_namespace_node *parent, uacpi_iteration_callback descending_callback, uacpi_iteration_callback ascending_callback, uacpi_object_type_bits, uacpi_u32 max_depth, enum uacpi_should_lock, enum uacpi_permanent_only, void *user)
Definition: namespace.c:841
uacpi_status uacpi_namespace_write_unlock(void)
Definition: namespace.c:51
#define UACPI_NAMESPACE_NODE_FLAG_TEMPORARY
Definition: namespace.h:25
@ UACPI_PERMANENT_ONLY_NO
Definition: namespace.h:93
uacpi_namespace_node * uacpi_namespace_node_find_sub_node(uacpi_namespace_node *parent, uacpi_object_name name)
Definition: namespace.c:453
#define UACPI_NAMESPACE_NODE_FLAG_ALIAS
Definition: namespace.h:10
uacpi_object * uacpi_namespace_node_get_object(const uacpi_namespace_node *node)
Definition: namespace.c:653
uacpi_namespace_node * uacpi_namespace_node_alloc(uacpi_object_name name)
Definition: namespace.c:281
uacpi_status uacpi_namespace_node_install(uacpi_namespace_node *parent, uacpi_namespace_node *node)
Definition: namespace.c:299
uacpi_status uacpi_namespace_node_uninstall(uacpi_namespace_node *node)
Definition: namespace.c:356
@ UACPI_SHOULD_LOCK_NO
Definition: namespace.h:98
uacpi_status uacpi_namespace_write_lock(void)
Definition: namespace.c:46
@ UACPI_MAY_SEARCH_ABOVE_PARENT_YES
Definition: namespace.h:89
uacpi_status uacpi_namespace_node_resolve(uacpi_namespace_node *scope, const uacpi_char *path, enum uacpi_should_lock, enum uacpi_may_search_above_parent, enum uacpi_permanent_only, uacpi_namespace_node **out_node)
Definition: namespace.c:498
#define UACPI_DUAL_NAME_PREFIX
Definition: opcodes.h:10
#define UACPI_MULTI_NAME_PREFIX
Definition: opcodes.h:11
const uacpi_char * uacpi_parse_op_to_string(enum uacpi_parse_op op)
Definition: opcodes.c:252
uacpi_parse_op
Definition: opcodes.h:18
@ UACPI_PARSE_OP_OPERAND
Definition: opcodes.h:55
@ UACPI_PARSE_OP_COMPUTATIONAL_DATA
Definition: opcodes.h:64
@ UACPI_PARSE_OP_OBJECT_CONVERT_TO_DEEP_COPY
Definition: opcodes.h:119
@ UACPI_PARSE_OP_EXISTING_NAMESTRING_OR_NULL_IF_LOAD
Definition: opcodes.h:107
@ UACPI_PARSE_OP_END
Definition: opcodes.h:19
@ UACPI_PARSE_OP_TYPECHECK_ONE_OF
Definition: opcodes.h:159
@ UACPI_PARSE_OP_STORE_TO_TARGET_INDIRECT
Definition: opcodes.h:182
@ UACPI_PARSE_OP_TERM_ARG
Definition: opcodes.h:39
@ UACPI_PARSE_OP_CREATE_NAMESTRING
Definition: opcodes.h:83
@ UACPI_PARSE_OP_TRACKED_PKGLEN
Definition: opcodes.h:77
@ UACPI_PARSE_OP_CONVERT_NAMESTRING
Definition: opcodes.h:207
@ UACPI_PARSE_OP_INSTALL_NAMESPACE_NODE
Definition: opcodes.h:162
@ UACPI_PARSE_OP_IF_LAST_NULL
Definition: opcodes.h:226
@ UACPI_PARSE_OP_AML_PC_DECREMENT
Definition: opcodes.h:185
@ UACPI_PARSE_OP_OBJECT_COPY_TO_PREV
Definition: opcodes.h:173
@ UACPI_PARSE_OP_EXISTING_NAMESTRING_OR_NULL
Definition: opcodes.h:101
@ UACPI_PARSE_OP_LOAD_TRUE_OBJECT
Definition: opcodes.h:147
@ UACPI_PARSE_OP_PKGLEN
Definition: opcodes.h:70
@ UACPI_PARSE_OP_EXISTING_NAMESTRING
Definition: opcodes.h:95
@ UACPI_PARSE_OP_TERM_ARG_OR_NAMED_OBJECT
Definition: opcodes.h:46
@ UACPI_PARSE_OP_IF_LAST_NOT_NULL
Definition: opcodes.h:232
@ UACPI_PARSE_OP_INVOKE_HANDLER
Definition: opcodes.h:110
@ UACPI_PARSE_OP_IF_HAS_DATA
Definition: opcodes.h:213
@ UACPI_PARSE_OP_DISPATCH_TABLE_LOAD
Definition: opcodes.h:201
@ UACPI_PARSE_OP_TERM_ARG_UNWRAP_INTERNAL
Definition: opcodes.h:40
@ UACPI_PARSE_OP_TYPECHECK
Definition: opcodes.h:153
@ UACPI_PARSE_OP_SIMPLE_NAME
Definition: opcodes.h:31
@ UACPI_PARSE_OP_IF_LAST_FALSE
Definition: opcodes.h:244
@ UACPI_PARSE_OP_JMP
Definition: opcodes.h:267
@ UACPI_PARSE_OP_ITEM_POP
Definition: opcodes.h:191
@ UACPI_PARSE_OP_SWITCH_TO_NEXT_IF_EQUALS
Definition: opcodes.h:255
@ UACPI_PARSE_OP_SUPERNAME_OR_UNRESOLVED
Definition: opcodes.h:36
@ UACPI_PARSE_OP_RECORD_AML_PC
Definition: opcodes.h:128
@ UACPI_PARSE_OP_DISPATCH_METHOD_CALL
Definition: opcodes.h:194
@ UACPI_PARSE_OP_SUPERNAME
Definition: opcodes.h:34
@ UACPI_PARSE_OP_OBJECT_ALLOC
Definition: opcodes.h:113
@ UACPI_PARSE_OP_OBJECT_TRANSFER_TO_PREV
Definition: opcodes.h:165
@ UACPI_PARSE_OP_IF_LAST_TRUE
Definition: opcodes.h:247
@ UACPI_PARSE_OP_IF_NULL
Definition: opcodes.h:220
@ UACPI_PARSE_OP_LOAD_INLINE_IMM_AS_OBJECT
Definition: opcodes.h:131
@ UACPI_PARSE_OP_STRING
Definition: opcodes.h:58
@ UACPI_PARSE_OP_LOAD_IMM
Definition: opcodes.h:140
@ UACPI_PARSE_OP_STORE_TO_TARGET
Definition: opcodes.h:176
@ UACPI_PARSE_OP_SKIP_WITH_WARN_IF_NULL
Definition: opcodes.h:25
@ UACPI_PARSE_OP_CREATE_NAMESTRING_OR_NULL_IF_LOAD
Definition: opcodes.h:89
@ UACPI_PARSE_OP_EMPTY_OBJECT_ALLOC
Definition: opcodes.h:115
@ UACPI_PARSE_OP_LOAD_IMM_AS_OBJECT
Definition: opcodes.h:143
@ UACPI_PARSE_OP_OBJECT_CONVERT_TO_SHALLOW_COPY
Definition: opcodes.h:118
@ UACPI_PARSE_OP_TARGET
Definition: opcodes.h:67
@ UACPI_PARSE_OP_TERM_ARG_OR_NAMED_OBJECT_OR_UNRESOLVED
Definition: opcodes.h:52
@ UACPI_PARSE_OP_IF_LAST_EQUALS
Definition: opcodes.h:238
@ UACPI_PARSE_OP_IF_NOT_NULL
Definition: opcodes.h:229
@ UACPI_PARSE_OP_LOAD_FALSE_OBJECT
Definition: opcodes.h:146
@ UACPI_PARSE_OP_OBJECT_ALLOC_TYPED
Definition: opcodes.h:125
@ UACPI_PARSE_OP_EMIT_SKIP_WARN
Definition: opcodes.h:28
@ UACPI_PARSE_OP_LOAD_ZERO_IMM
Definition: opcodes.h:137
@ UACPI_PARSE_OP_IF_SWITCHED_FROM
Definition: opcodes.h:262
@ UACPI_PARSE_OP_TRUNCATE_NUMBER
Definition: opcodes.h:150
@ UACPI_PARSE_OP_IMM_DECREMENT
Definition: opcodes.h:188
@ UACPI_PARSE_OP_LOAD_INLINE_IMM
Definition: opcodes.h:134
#define UACPI_NULL_NAME
Definition: opcodes.h:12
const struct uacpi_op_spec * uacpi_get_op_spec(uacpi_aml_op)
Definition: opcodes.c:44
@ UACPI_OP_PROPERTY_SIMPLE_NAME
Definition: opcodes.h:275
@ UACPI_OP_PROPERTY_TERM_ARG
Definition: opcodes.h:273
@ UACPI_OP_PROPERTY_INVALID
Definition: opcodes.h:282
@ UACPI_OP_PROPERTY_INTERNAL
Definition: opcodes.h:289
@ UACPI_OP_PROPERTY_SUPERNAME
Definition: opcodes.h:274
@ UACPI_OP_PROPERTY_OUT_OF_LINE
Definition: opcodes.h:279
@ UACPI_OP_PROPERTY_TARGET
Definition: opcodes.h:276
#define UACPI_EXT_PREFIX
Definition: opcodes.h:7
uacpi_aml_op
Definition: opcodes.h:1388
uacpi_status uacpi_find_aml_resource_end_tag(uacpi_data_view, uacpi_size *out_offset)
Definition: resources.c:1528
uacpi_u8 uacpi_bit_scan_forward(uacpi_u64)
Definition: stdlib.c:124
#define UACPI_MAX(x, y)
Definition: stdlib.h:103
uacpi_i32 uacpi_snprintf(uacpi_char *buffer, uacpi_size capacity, const uacpi_char *fmt,...)
Definition: stdlib.c:690
#define uacpi_memzero(ptr, size)
Definition: stdlib.h:99
#define uacpi_kernel_alloc_zeroed
Definition: stdlib.h:127
#define uacpi_memcmp
Definition: stdlib.h:61
#define uacpi_memcpy
Definition: stdlib.h:34
uacpi_size uacpi_strnlen(const uacpi_char *str, uacpi_size max)
Definition: stdlib.c:85
#define UACPI_ALIGN_DOWN(x, val, type)
Definition: stdlib.h:109
#define uacpi_free(mem, _)
Definition: stdlib.h:96
uacpi_u8 uacpi_bit_scan_backward(uacpi_u64)
Definition: stdlib.c:166
void uacpi_memcpy_zerout(void *dst, const void *src, uacpi_size dst_size, uacpi_size src_size)
Definition: stdlib.c:112
#define uacpi_memmove
Definition: stdlib.h:43
#define UACPI_MIN(x, y)
Definition: stdlib.h:102
struct uacpi_object * uacpi_create_internal_reference(enum uacpi_reference_kind kind, uacpi_object *child)
Definition: types.c:1456
@ UACPI_PREALLOC_OBJECTS_YES
Definition: types.h:303
uacpi_object * uacpi_create_object(uacpi_object_type type)
Definition: types.c:328
void uacpi_object_detach_child(uacpi_object *parent)
Definition: types.c:965
uacpi_bool uacpi_package_fill(uacpi_package *pkg, uacpi_size num_elements, enum uacpi_prealloc_objects prealloc_objects)
Definition: types.c:125
void uacpi_buffer_to_view(uacpi_buffer *, uacpi_data_view *)
Definition: types.c:1042
uacpi_reference_kind
Definition: types.h:10
@ UACPI_REFERENCE_KIND_LOCAL
Definition: types.h:12
@ UACPI_REFERENCE_KIND_ARG
Definition: types.h:13
@ UACPI_REFERENCE_KIND_PKG_INDEX
Definition: types.h:15
@ UACPI_REFERENCE_KIND_NAMED
Definition: types.h:14
@ UACPI_FIELD_UNIT_KIND_NORMAL
Definition: types.h:207
@ UACPI_FIELD_UNIT_KIND_BANK
Definition: types.h:209
@ UACPI_FIELD_UNIT_KIND_INDEX
Definition: types.h:208
uacpi_mutex * uacpi_create_mutex(void)
Definition: types.c:182
void uacpi_object_attach_child(uacpi_object *parent, uacpi_object *child)
Definition: types.c:949
uacpi_status uacpi_object_assign(uacpi_object *dst, uacpi_object *src, enum uacpi_assign_behavior)
Definition: types.c:1371
void uacpi_method_unref(uacpi_control_method *)
Definition: types.c:650
uacpi_assign_behavior
Definition: types.h:285
@ UACPI_ASSIGN_BEHAVIOR_DEEP_COPY
Definition: types.h:286
@ UACPI_ASSIGN_BEHAVIOR_SHALLOW_COPY
Definition: types.h:287
void uacpi_mutex_unref(uacpi_mutex *)
Definition: types.c:496
@ UACPI_STRING_KIND_PATH
Definition: types.h:21
uacpi_object * uacpi_unwrap_internal_reference(uacpi_object *object)
Definition: types.c:1471
uacpi_log_level
Definition: log.h:7
@ UACPI_LOG_INFO
Definition: log.h:24
@ UACPI_LOG_TRACE
Definition: log.h:18
@ UACPI_LOG_ERROR
Definition: log.h:35
@ UACPI_LOG_WARN
Definition: log.h:29
void uacpi_free_absolute_path(const uacpi_char *path)
Definition: namespace.c:1093
#define UACPI_MAX_DEPTH_ANY
Definition: namespace.h:102
const uacpi_char * uacpi_namespace_node_generate_absolute_path(const uacpi_namespace_node *node)
Definition: namespace.c:1053
uacpi_namespace_node * uacpi_namespace_root(void)
Definition: namespace.c:264
#define UACPI_FALLTHROUGH
Definition: compiler.h:100
#define uacpi_likely(expr)
Definition: compiler.h:89
#define uacpi_unlikely(expr)
Definition: compiler.h:88
#define UACPI_PRIX64
Definition: types.h:61
size_t uacpi_size
Definition: types.h:37
uint32_t uacpi_u32
Definition: types.h:21
bool uacpi_bool
Definition: types.h:31
#define UACPI_FALSE
Definition: types.h:30
uint64_t uacpi_u64
Definition: types.h:22
char uacpi_char
Definition: types.h:44
#define UACPI_NULL
Definition: types.h:33
uint8_t uacpi_u8
Definition: types.h:19
#define UACPI_FMT64(val)
Definition: types.h:62
#define UACPI_PRIx64
Definition: types.h:60
#define UACPI_TRUE
Definition: types.h:29
#define UACPI_PRIu64
Definition: types.h:59
#define uacpi_likely_success(expr)
Definition: status.h:54
#define uacpi_unlikely_error(expr)
Definition: status.h:50
uacpi_status
Definition: status.h:10
@ UACPI_STATUS_INVALID_ARGUMENT
Definition: status.h:18
@ UACPI_STATUS_AML_OBJECT_ALREADY_EXISTS
Definition: status.h:36
@ UACPI_STATUS_AML_OUT_OF_BOUNDS_INDEX
Definition: status.h:40
@ UACPI_STATUS_NOT_FOUND
Definition: status.h:17
@ UACPI_STATUS_UNIMPLEMENTED
Definition: status.h:19
@ UACPI_STATUS_AML_REFERENCE_CYCLE
Definition: status.h:45
@ UACPI_STATUS_OUT_OF_MEMORY
Definition: status.h:13
@ UACPI_STATUS_OVERRIDDEN
Definition: status.h:30
@ UACPI_STATUS_INVALID_TABLE_LENGTH
Definition: status.h:16
@ UACPI_STATUS_AML_INCOMPATIBLE_OBJECT_TYPE
Definition: status.h:38
@ UACPI_STATUS_AML_UNDEFINED_REFERENCE
Definition: status.h:34
@ UACPI_STATUS_AML_LOOP_TIMEOUT
Definition: status.h:43
@ UACPI_STATUS_AML_BAD_ENCODING
Definition: status.h:39
@ UACPI_STATUS_AML_INVALID_OPCODE
Definition: status.h:37
@ UACPI_STATUS_MAPPING_FAILED
Definition: status.h:12
@ UACPI_STATUS_OK
Definition: status.h:11
@ UACPI_STATUS_AML_INVALID_NAMESTRING
Definition: status.h:35
@ UACPI_STATUS_AML_CALL_STACK_DEPTH_LIMIT
Definition: status.h:44
@ UACPI_STATUS_DENIED
Definition: status.h:31
@ UACPI_STATUS_AML_SYNC_LEVEL_TOO_HIGH
Definition: status.h:41
@ UACPI_STATUS_NO_HANDLER
Definition: status.h:25
const uacpi_char * uacpi_status_to_string(uacpi_status)
Definition: uacpi.c:61
void uacpi_object_ref(uacpi_object *obj)
Definition: types.c:733
uacpi_bool uacpi_object_is_one_of(uacpi_object *, uacpi_object_type_bits type_mask)
Definition: types.c:996
uacpi_iteration_decision
Definition: types.h:28
@ UACPI_ITERATION_DECISION_BREAK
Definition: types.h:30
@ UACPI_ITERATION_DECISION_CONTINUE
Definition: types.h:29
uacpi_object_type_bits
Definition: types.h:134
@ UACPI_OBJECT_MUTEX_BIT
Definition: types.h:143
@ UACPI_OBJECT_REFERENCE_BIT
Definition: types.h:150
@ UACPI_OBJECT_METHOD_BIT
Definition: types.h:142
@ UACPI_OBJECT_BUFFER_INDEX_BIT
Definition: types.h:151
@ UACPI_OBJECT_FIELD_UNIT_BIT
Definition: types.h:139
@ UACPI_OBJECT_PROCESSOR_BIT
Definition: types.h:146
@ UACPI_OBJECT_POWER_RESOURCE_BIT
Definition: types.h:145
@ UACPI_OBJECT_BUFFER_FIELD_BIT
Definition: types.h:148
@ UACPI_OBJECT_OPERATION_REGION_BIT
Definition: types.h:144
@ UACPI_OBJECT_PACKAGE_BIT
Definition: types.h:138
@ UACPI_OBJECT_EVENT_BIT
Definition: types.h:141
@ UACPI_OBJECT_THERMAL_ZONE_BIT
Definition: types.h:147
@ UACPI_OBJECT_DEVICE_BIT
Definition: types.h:140
@ UACPI_ACCESS_ATTRIBUTE_RAW_BYTES
Definition: types.h:493
@ UACPI_ACCESS_ATTRIBUTE_RAW_PROCESS_BYTES
Definition: types.h:494
@ UACPI_ACCESS_ATTRIBUTE_BYTES
Definition: types.h:490
const uacpi_char * uacpi_object_type_to_string(uacpi_object_type)
Definition: types.c:52
uacpi_object_type
Definition: types.h:110
@ UACPI_OBJECT_EVENT
Definition: types.h:118
@ UACPI_OBJECT_METHOD
Definition: types.h:119
@ UACPI_OBJECT_BUFFER
Definition: types.h:114
@ UACPI_OBJECT_STRING
Definition: types.h:113
@ UACPI_OBJECT_PROCESSOR
Definition: types.h:123
@ UACPI_OBJECT_PACKAGE
Definition: types.h:115
@ UACPI_OBJECT_POWER_RESOURCE
Definition: types.h:122
@ UACPI_OBJECT_UNINITIALIZED
Definition: types.h:111
@ UACPI_OBJECT_REFERENCE
Definition: types.h:128
@ UACPI_OBJECT_MUTEX
Definition: types.h:120
@ UACPI_OBJECT_DEBUG
Definition: types.h:126
@ UACPI_OBJECT_INTEGER
Definition: types.h:112
@ UACPI_OBJECT_BUFFER_FIELD
Definition: types.h:125
@ UACPI_OBJECT_OPERATION_REGION
Definition: types.h:121
@ UACPI_OBJECT_FIELD_UNIT
Definition: types.h:116
@ UACPI_OBJECT_BUFFER_INDEX
Definition: types.h:129
@ UACPI_FIRMWARE_REQUEST_TYPE_FATAL
Definition: types.h:528
@ UACPI_FIRMWARE_REQUEST_TYPE_BREAKPOINT
Definition: types.h:527
uacpi_bool uacpi_object_is(uacpi_object *, uacpi_object_type)
Definition: types.c:991
@ UACPI_ADDRESS_SPACE_SYSTEM_MEMORY
Definition: types.h:43
@ UACPI_ADDRESS_SPACE_TABLE_DATA
Definition: types.h:58
@ UACPI_ADDRESS_SPACE_PCC
Definition: types.h:53
void uacpi_object_unref(uacpi_object *obj)
Definition: types.c:761
void uacpi_events_match_post_dynamic_table_load(void)
Definition: event.c:1567
static uacpi_status field_byte_size(uacpi_object *obj, uacpi_size *out_size)
Definition: interpreter.c:4151
static uacpi_status handle_arg(struct execution_context *ctx)
Definition: interpreter.c:1147
static uacpi_status handle_control_flow(struct execution_context *ctx)
Definition: interpreter.c:4425
static uacpi_status handle_create_field(struct execution_context *ctx)
Definition: interpreter.c:1735
static uacpi_status table_id_error(const uacpi_char *opcode, const uacpi_char *arg, uacpi_buffer *str)
Definition: interpreter.c:1230
static uacpi_status handle_concatenate(struct execution_context *ctx)
Definition: interpreter.c:3232
static uacpi_status handle_unload(struct execution_context *ctx)
Definition: interpreter.c:3522
#define AML_READ(ptr, offset)
Definition: interpreter.c:340
static const uacpi_char *const op_trace_action_types[3]
Definition: interpreter.c:4574
static uacpi_status handle_deref_of(struct execution_context *ctx)
Definition: interpreter.c:4171
static uacpi_status handle_field_read(struct execution_context *ctx)
Definition: interpreter.c:4258
match_op
Definition: interpreter.c:3661
@ MGE
Definition: interpreter.c:3666
@ MLT
Definition: interpreter.c:3665
@ MGT
Definition: interpreter.c:3667
@ MLE
Definition: interpreter.c:3664
@ MEQ
Definition: interpreter.c:3663
@ MTR
Definition: interpreter.c:3662
static uacpi_status frame_setup_base_scope(struct call_frame *frame, uacpi_namespace_node *scope, uacpi_control_method *method)
Definition: interpreter.c:4624
static uacpi_status typecheck_operand(const struct op_context *op_ctx, const uacpi_object *obj)
Definition: interpreter.c:5150
#define EXEC_OP_ERR_3(reason, arg0, arg1, arg2)
Definition: interpreter.c:5013
static uacpi_status prepare_table_load(void *ptr, enum uacpi_table_load_cause cause, uacpi_control_method *in_method)
Definition: interpreter.c:1334
static uacpi_status do_load_table(uacpi_namespace_node *parent, struct acpi_sdt_hdr *tbl, enum uacpi_table_load_cause cause)
Definition: interpreter.c:1364
static uacpi_status method_get_ret_target(struct execution_context *ctx, uacpi_object **out_operand)
Definition: interpreter.c:2025
static uacpi_status object_copy_for_overwrite(uacpi_object *src, uacpi_object **out_obj)
Definition: interpreter.c:2526
static uacpi_status store_to_target(uacpi_object *dst, uacpi_object *src, uacpi_data_view *wtr_response)
Definition: interpreter.c:4681
static void apply_tracked_pkg(struct call_frame *frame, struct op_context *op_ctx)
Definition: interpreter.c:5610
static uacpi_status prepare_method_call(struct execution_context *ctx, uacpi_namespace_node *node, uacpi_control_method *method, enum method_call_type type, const uacpi_object_array *args)
Definition: interpreter.c:5534
static uacpi_bool op_allows_unresolved_if_load(enum uacpi_parse_op op)
Definition: interpreter.c:5073
item_type
Definition: interpreter.c:23
@ ITEM_OBJECT
Definition: interpreter.c:26
@ ITEM_EMPTY_OBJECT
Definition: interpreter.c:27
@ ITEM_IMMEDIATE
Definition: interpreter.c:29
@ ITEM_NONE
Definition: interpreter.c:24
@ ITEM_PACKAGE_LENGTH
Definition: interpreter.c:28
@ ITEM_NAMESPACE_NODE
Definition: interpreter.c:25
#define SPEC_TERM_ARG
Definition: interpreter.c:5024
static uacpi_status handle_code_block(struct execution_context *ctx)
Definition: interpreter.c:4492
resolve_behavior
Definition: interpreter.c:475
@ RESOLVE_FAIL_IF_DOESNT_EXIST
Definition: interpreter.c:477
@ RESOLVE_CREATE_LAST_NAMESEG_FAIL_IF_EXISTS
Definition: interpreter.c:476
static void trace_method_abort(struct code_block *block, uacpi_size depth, uacpi_u32 aml_offset, uacpi_u32 method_size, const uacpi_char *op)
Definition: interpreter.c:6358
static void truncate_number_if_needed(uacpi_object *obj)
Definition: interpreter.c:2012
static uacpi_status handle_event_ctl(struct execution_context *ctx)
Definition: interpreter.c:3881
op_handler
Definition: interpreter.c:5275
@ OP_HANDLER_LOGICAL_NOT
Definition: interpreter.c:5289
@ OP_HANDLER_INDEX
Definition: interpreter.c:5302
@ OP_HANDLER_CREATE_METHOD
Definition: interpreter.c:5284
@ OP_HANDLER_MUTEX_CTL
Definition: interpreter.c:5319
@ OP_HANDLER_STALL_OR_SLEEP
Definition: interpreter.c:5317
@ OP_HANDLER_BINARY_MATH
Definition: interpreter.c:5280
@ OP_HANDLER_INC_DEC
Definition: interpreter.c:5286
@ OP_HANDLER_CREATE_DATA_REGION
Definition: interpreter.c:5305
@ OP_HANDLER_BINARY_LOGIC
Definition: interpreter.c:5290
@ OP_HANDLER_NOTIFY
Definition: interpreter.c:5320
@ OP_HANDLER_LOCAL
Definition: interpreter.c:5277
@ OP_HANDLER_LOAD_TABLE
Definition: interpreter.c:5315
@ OP_HANDLER_ALIAS
Definition: interpreter.c:5297
@ OP_HANDLER_REF_OF
Definition: interpreter.c:5287
@ OP_HANDLER_OBJECT_TYPE
Definition: interpreter.c:5303
@ OP_HANDLER_UNLOAD
Definition: interpreter.c:5314
@ OP_HANDLER_STRING
Definition: interpreter.c:5279
@ OP_HANDLER_BUFFER
Definition: interpreter.c:5292
@ OP_HANDLER_UNARY_MATH
Definition: interpreter.c:5301
@ OP_HANDLER_CREATE_MUTEX_OR_EVENT
Definition: interpreter.c:5312
@ OP_HANDLER_PACKAGE
Definition: interpreter.c:5293
@ OP_HANDLER_MID
Definition: interpreter.c:5310
@ OP_HANDLER_CREATE_FIELD
Definition: interpreter.c:5306
@ OP_HANDLER_COPY_OBJECT_OR_STORE
Definition: interpreter.c:5285
@ OP_HANDLER_BCD
Definition: interpreter.c:5313
@ OP_HANDLER_CODE_BLOCK
Definition: interpreter.c:5282
@ OP_HANDLER_TO_STRING
Definition: interpreter.c:5308
@ OP_HANDLER_SIZEOF
Definition: interpreter.c:5300
@ OP_HANDLER_NAMED_OBJECT
Definition: interpreter.c:5291
@ OP_HANDLER_LOAD
Definition: interpreter.c:5316
@ OP_HANDLER_CONCATENATE_RES
Definition: interpreter.c:5299
@ OP_HANDLER_READ_FIELD
Definition: interpreter.c:5296
@ OP_HANDLER_CONCATENATE
Definition: interpreter.c:5298
@ OP_HANDLER_EVENT_CTL
Definition: interpreter.c:5318
@ OP_HANDLER_CONTROL_FLOW
Definition: interpreter.c:5281
@ OP_HANDLER_MATCH
Definition: interpreter.c:5311
@ OP_HANDLER_RETURN
Definition: interpreter.c:5283
@ OP_HANDLER_FIRMWARE_REQUEST
Definition: interpreter.c:5321
@ OP_HANDLER_CREATE_BUFFER_FIELD
Definition: interpreter.c:5295
@ OP_HANDLER_TIMER
Definition: interpreter.c:5309
@ OP_HANDLER_ARG
Definition: interpreter.c:5278
@ OP_HANDLER_CREATE_NAMED
Definition: interpreter.c:5294
@ OP_HANDLER_UNINSTALLED
Definition: interpreter.c:5276
@ OP_HANDLER_CREATE_OP_REGION
Definition: interpreter.c:5304
@ OP_HANDLER_DEREF_OF
Definition: interpreter.c:5288
@ OP_HANDLER_TO
Definition: interpreter.c:5307
static uacpi_status debug_store(uacpi_object *src)
Definition: interpreter.c:2299
static uacpi_status field_get_read_type(uacpi_object *obj, uacpi_object_type *out_type)
Definition: interpreter.c:4139
static uacpi_status handle_create_named(struct execution_context *ctx)
Definition: interpreter.c:4111
static uacpi_status object_assign_with_implicit_cast(uacpi_object *dst, uacpi_object *src, uacpi_data_view *wtr_response)
Definition: interpreter.c:1014
static uacpi_status ensure_valid_idx(uacpi_object *obj, uacpi_size idx, uacpi_size src_size)
Definition: interpreter.c:2846
#define SPEC_SUPER_NAME
Definition: interpreter.c:5022
static uacpi_status method_get_ret_object(struct execution_context *ctx, uacpi_object **out_obj)
Definition: interpreter.c:2065
static uacpi_status handle_to(struct execution_context *ctx)
Definition: interpreter.c:3095
static uacpi_u8 parse_op_generates_item[0x100]
Definition: interpreter.c:4941
static uacpi_status handle_return(struct execution_context *ctx)
Definition: interpreter.c:4522
static uacpi_bool maybe_end_block(struct execution_context *ctx)
Definition: interpreter.c:4664
static void init_method_flags(uacpi_control_method *method, uacpi_u8 flags_byte)
Definition: interpreter.c:3793
static uacpi_status handle_create_method(struct execution_context *ctx)
Definition: interpreter.c:3800
static uacpi_status handle_buffer(struct execution_context *ctx)
Definition: interpreter.c:721
static uacpi_status handle_mid(struct execution_context *ctx)
Definition: interpreter.c:3177
static uacpi_u64 ones(void)
Definition: interpreter.c:2020
static uacpi_object_type buffer_field_get_read_type(struct uacpi_buffer_field *field)
Definition: interpreter.c:4128
static void trace_pop(uacpi_u8 pop)
Definition: interpreter.c:4590
static uacpi_status do_binary_math(uacpi_object *arg0, uacpi_object *arg1, uacpi_object *tgt0, uacpi_object *tgt1, uacpi_aml_op op)
Definition: interpreter.c:2724
static uacpi_status name_string_to_path(struct call_frame *frame, uacpi_size offset, uacpi_char **out_string, uacpi_size *out_size)
Definition: interpreter.c:367
static uacpi_status handle_create_mutex_or_event(struct execution_context *ctx)
Definition: interpreter.c:3853
static uacpi_status handle_inc_dec(struct execution_context *ctx)
Definition: interpreter.c:4763
static uacpi_status handle_unary_math(struct execution_context *ctx)
Definition: interpreter.c:2819
static uacpi_status handle_object_type(struct execution_context *ctx)
Definition: interpreter.c:3428
static void report_table_id_find_error(const uacpi_char *opcode, struct uacpi_table_identifiers *id, uacpi_status ret)
Definition: interpreter.c:1239
static uacpi_status handle_bcd(struct execution_context *ctx)
Definition: interpreter.c:3485
static void pop_op(struct execution_context *ctx)
Definition: interpreter.c:4906
static uacpi_status queue_object(struct object_queue *queue, uacpi_object *obj)
Definition: interpreter.c:2360
static uacpi_bool object_is_package_index(uacpi_object *obj)
Definition: interpreter.c:2520
static void trace_named_object_lookup_or_creation_failure(struct call_frame *frame, uacpi_size offset, enum uacpi_parse_op op, uacpi_status ret, enum uacpi_log_level level)
Definition: interpreter.c:5191
static uacpi_bool pop_item(struct op_context *op_ctx)
Definition: interpreter.c:4887
static uacpi_status held_mutexes_array_remove_and_release(struct held_mutexes_array *arr, uacpi_mutex *mutex, enum force_release force)
Definition: interpreter.c:185
static uacpi_status handle_create_buffer_field(struct execution_context *ctx)
Definition: interpreter.c:4329
#define SPEC_STRING
Definition: interpreter.c:5027
static uacpi_status build_table_id(const uacpi_char *opcode, struct uacpi_table_identifiers *out_id, uacpi_buffer *signature, uacpi_buffer *oem_id, uacpi_buffer *oem_table_id)
Definition: interpreter.c:1252
static uacpi_u8 handler_idx_of_ext_op[0x100]
Definition: interpreter.c:5490
static uacpi_status handle_match(struct execution_context *ctx)
Definition: interpreter.c:3690
static void emit_op_skip_warn(const struct op_context *op_ctx)
Definition: interpreter.c:5186
static uacpi_status handle_stall_or_sleep(struct execution_context *ctx)
Definition: interpreter.c:3457
static uacpi_status handle_notify(struct execution_context *ctx)
Definition: interpreter.c:4048
argx_or_localx
Definition: interpreter.c:1094
@ LOCALX
Definition: interpreter.c:1096
@ ARGX
Definition: interpreter.c:1095
static uacpi_bool op_wants_supername(enum uacpi_parse_op op)
Definition: interpreter.c:5034
static uacpi_status do_make_empty_object(uacpi_buffer *buf, uacpi_bool is_string)
Definition: interpreter.c:3067
static uacpi_status handle_ref_of(struct execution_context *ctx)
Definition: interpreter.c:2706
static void write_buffer_index(uacpi_buffer_index *buf_idx, uacpi_data_view *src_buf)
Definition: interpreter.c:962
static uacpi_status push_op(struct execution_context *ctx)
Definition: interpreter.c:4873
static uacpi_status parse_package_length(struct call_frame *frame, struct package_length *out_pkg)
Definition: interpreter.c:3735
static uacpi_status handle_to_string(struct execution_context *ctx)
Definition: interpreter.c:3150
static void * call_frame_cursor(struct call_frame *frame)
Definition: interpreter.c:291
static uacpi_u8 peek_next_op(struct call_frame *frame, uacpi_aml_op *out_op)
Definition: interpreter.c:658
static uacpi_status handle_copy_object_or_store(struct execution_context *ctx)
Definition: interpreter.c:4716
static uacpi_status handle_string(struct execution_context *ctx)
Definition: interpreter.c:773
static uacpi_status handle_arg_or_local(struct execution_context *ctx, uacpi_size idx, enum argx_or_localx type)
Definition: interpreter.c:1099
static uacpi_status handle_timer(struct execution_context *ctx)
Definition: interpreter.c:3446
static uacpi_u8 op_decode_byte(struct op_context *ctx)
Definition: interpreter.c:4985
static void stack_unwind(struct execution_context *ctx)
Definition: interpreter.c:6385
static uacpi_bool op_wants_term_arg_or_operand(enum uacpi_parse_op op)
Definition: interpreter.c:5047
#define SPEC_TARGET
Definition: interpreter.c:5028
static uacpi_status create_named_scope(struct op_context *op_ctx)
Definition: interpreter.c:4456
static uacpi_status check_no_reference_cycle(uacpi_object *dst, uacpi_object *new_obj)
Definition: interpreter.c:2388
static void debug_store_no_recurse(const uacpi_char *prefix, uacpi_object *src)
Definition: interpreter.c:2216
static uacpi_status exec_op(struct execution_context *ctx)
Definition: interpreter.c:5623
static uacpi_status begin_block_execution(struct execution_context *ctx)
Definition: interpreter.c:2106
static uacpi_u8 handler_idx_of_op[0x100]
Definition: interpreter.c:5377
static uacpi_object * reference_unwind(uacpi_object *obj)
Definition: interpreter.c:2332
uacpi_status uacpi_execute_table(void *tbl, enum uacpi_table_load_cause cause)
Definition: interpreter.c:1672
static uacpi_status object_replace_child(uacpi_object *parent, uacpi_object *new_child)
Definition: interpreter.c:2449
static bool op_is_invalid(const struct uacpi_op_spec *op)
Definition: interpreter.c:691
static uacpi_status get_op(struct execution_context *ctx)
Definition: interpreter.c:696
static uacpi_iteration_decision opregion_try_detach_from_parent(void *user, uacpi_namespace_node *node, uacpi_u32 node_depth)
Definition: interpreter.c:2434
static void execution_context_release(struct execution_context *ctx)
Definition: interpreter.c:6461
static uacpi_status make_null_string(uacpi_buffer *buf)
Definition: interpreter.c:3080
static uacpi_bool op_allows_unresolved(enum uacpi_parse_op op)
Definition: interpreter.c:5061
static uacpi_status copy_object_to_reference(uacpi_object *dst, uacpi_object *src)
Definition: interpreter.c:2568
static uacpi_status handle_create_alias(struct execution_context *ctx)
Definition: interpreter.c:1171
static void trace_op(const struct uacpi_op_spec *op, enum op_trace_action_type action)
Definition: interpreter.c:4580
static uacpi_status typecheck_string(const struct op_context *op_ctx, const uacpi_object *obj)
Definition: interpreter.c:5158
#define EXEC_OP_ERR(reason)
Definition: interpreter.c:5017
static uacpi_status handle_load_table(struct execution_context *ctx)
Definition: interpreter.c:1386
force_release
Definition: interpreter.c:180
@ FORCE_RELEASE_NO
Definition: interpreter.c:181
@ FORCE_RELEASE_YES
Definition: interpreter.c:182
static void frame_reset_post_end_block(struct execution_context *ctx, enum code_block_type type)
Definition: interpreter.c:2181
static uacpi_size sizeof_int(void)
Definition: interpreter.c:912
static uacpi_status handle_local(struct execution_context *ctx)
Definition: interpreter.c:1138
static struct code_block * find_last_block(struct code_block_array *blocks, enum code_block_type type, uacpi_size *out_idx_plus_one)
Definition: interpreter.c:2082
static uacpi_status(* op_handlers[])(struct execution_context *ctx)
Definition: interpreter.c:5324
static uacpi_bool object_is_written_in_place(uacpi_object *obj)
Definition: interpreter.c:2507
static uacpi_size call_frame_code_bytes_left(struct call_frame *frame)
Definition: interpreter.c:296
op_trace_action_type
Definition: interpreter.c:4568
@ OP_TRACE_ACTION_RESUME
Definition: interpreter.c:4570
@ OP_TRACE_ACTION_BEGIN
Definition: interpreter.c:4569
@ OP_TRACE_ACTION_END
Definition: interpreter.c:4571
static uacpi_aml_op op_decode_aml_op(struct op_context *op_ctx)
Definition: interpreter.c:4995
static uacpi_status handle_create_op_region(struct execution_context *ctx)
Definition: interpreter.c:1185
#define SPEC_SIMPLE_NAME
Definition: interpreter.c:5021
static void call_frame_clear(struct call_frame *frame)
Definition: interpreter.c:4918
method_call_type
Definition: interpreter.c:5528
@ METHOD_CALL_AML
Definition: interpreter.c:5530
@ METHOD_CALL_TABLE_LOAD
Definition: interpreter.c:5531
@ METHOD_CALL_NATIVE
Definition: interpreter.c:5529
static uacpi_status do_install_node_item(struct call_frame *frame, struct item *item)
Definition: interpreter.c:640
static uacpi_status handle_sizeof(struct execution_context *ctx)
Definition: interpreter.c:3391
static uacpi_status handle_load(struct execution_context *ctx)
Definition: interpreter.c:1506
static uacpi_bool trim_to_last_chunk(uacpi_object *src, uacpi_data_view *buf, uacpi_size chunk_size)
Definition: interpreter.c:975
#define SPEC_COMPUTATIONAL_DATA
Definition: interpreter.c:5030
static uacpi_status resolve_name_string(struct call_frame *frame, enum resolve_behavior behavior, struct uacpi_namespace_node **out_node)
Definition: interpreter.c:480
static uacpi_status handle_firmware_request(struct execution_context *ctx)
Definition: interpreter.c:4084
static void held_mutexes_array_remove_idx(struct held_mutexes_array *arr, uacpi_size i)
Definition: interpreter.c:128
uacpi_status uacpi_execute_control_method(uacpi_namespace_node *scope, uacpi_control_method *method, const uacpi_object_array *args, uacpi_object **out_obj)
Definition: interpreter.c:6479
static uacpi_status handle_package(struct execution_context *ctx)
Definition: interpreter.c:801
#define EXEC_OP_ERR_1(reason, arg0)
Definition: interpreter.c:5016
static void refresh_ctx_pointers(struct execution_context *ctx)
Definition: interpreter.c:4547
static uacpi_bool is_dynamic_table_load(enum uacpi_table_load_cause cause)
Definition: interpreter.c:1329
static uacpi_status store_to_field_unit(uacpi_field_unit *field, uacpi_object *src, uacpi_data_view *buf, uacpi_data_view *wtr_response)
Definition: interpreter.c:993
#define EXEC_OP_ERR_2(reason, arg0, arg1)
Definition: interpreter.c:5015
static uacpi_u64 object_to_integer(const uacpi_object *obj, uacpi_size max_buffer_bytes)
Definition: interpreter.c:2944
static uacpi_status handle_logical_not(struct execution_context *ctx)
Definition: interpreter.c:3545
static uacpi_status make_null_buffer(uacpi_buffer *buf)
Definition: interpreter.c:3085
static uacpi_bool call_frame_has_code(struct call_frame *frame)
Definition: interpreter.c:301
static uacpi_u8 * buffer_index_cursor(uacpi_buffer_index *buf_idx)
Definition: interpreter.c:952
static uacpi_bool match_one(enum match_op op, uacpi_u64 lhs, uacpi_u64 rhs)
Definition: interpreter.c:3670
static uacpi_status get_object_storage(uacpi_object *obj, uacpi_data_view *out_buf, uacpi_bool include_null)
Definition: interpreter.c:917
static uacpi_status enter_method(struct execution_context *ctx, struct call_frame *new_frame, uacpi_control_method *method)
Definition: interpreter.c:4827
static void ctx_reload_post_ret(struct execution_context *ctx)
Definition: interpreter.c:6340
#define EXT_OP_IDX(op)
Definition: interpreter.c:5488
static bool op_is_internal(const struct uacpi_op_spec *op)
Definition: interpreter.c:686
static uacpi_status ensure_is_a_field_unit(uacpi_namespace_node *node, uacpi_field_unit **out_field)
Definition: interpreter.c:1699
static uacpi_status handle_mutex_ctl(struct execution_context *ctx)
Definition: interpreter.c:3942
code_block_type
Definition: interpreter.c:87
@ CODE_BLOCK_ELSE
Definition: interpreter.c:89
@ CODE_BLOCK_IF
Definition: interpreter.c:88
@ CODE_BLOCK_WHILE
Definition: interpreter.c:90
@ CODE_BLOCK_SCOPE
Definition: interpreter.c:91
static uacpi_bool ctx_has_non_preempted_op(struct execution_context *ctx)
Definition: interpreter.c:4563
static uacpi_status typecheck_computational_data(const struct op_context *op_ctx, const uacpi_object *obj)
Definition: interpreter.c:5166
static uacpi_u32 get_field_length(struct item *item)
Definition: interpreter.c:1686
static uacpi_status store_to_reference(uacpi_object *dst, uacpi_object *src, uacpi_data_view *wtr_response)
Definition: interpreter.c:2634
static uacpi_status push_new_frame(struct execution_context *ctx, struct call_frame **out_frame)
Definition: interpreter.c:4642
static uacpi_status handle_concatenate_res(struct execution_context *ctx)
Definition: interpreter.c:3344
static uacpi_bool handle_logical_equality(uacpi_object *lhs, uacpi_object *rhs)
Definition: interpreter.c:3559
static uacpi_status ensure_is_an_op_region(uacpi_namespace_node *node, uacpi_namespace_node **out_node)
Definition: interpreter.c:1717
static uacpi_status handle_binary_math(struct execution_context *ctx)
Definition: interpreter.c:2799
static uacpi_status buffer_to_string(uacpi_buffer *buf, uacpi_buffer *str, uacpi_bool is_hex)
Definition: interpreter.c:3005
static uacpi_status handle_binary_logic(struct execution_context *ctx)
Definition: interpreter.c:3612
static uacpi_status handle_named_object(struct execution_context *ctx)
Definition: interpreter.c:1156
#define SPEC_OPERAND
Definition: interpreter.c:5026
static uacpi_status integer_to_string(uacpi_u64 integer, uacpi_buffer *str, uacpi_bool is_hex)
Definition: interpreter.c:2972
static uacpi_status frame_push_args(struct call_frame *frame, struct op_context *op_ctx)
Definition: interpreter.c:4595
static uacpi_status uninstalled_op_handler(struct execution_context *ctx)
Definition: interpreter.c:5267
static uacpi_status parse_nameseg(uacpi_u8 *cursor, uacpi_object_name *out_name)
Definition: interpreter.c:342
static uacpi_status typecheck_obj(const struct op_context *op_ctx, const uacpi_object *obj, enum uacpi_object_type expected_type, const uacpi_char *spec_desc)
Definition: interpreter.c:5135
static uacpi_bool handle_logical_less_or_greater(uacpi_aml_op op, uacpi_object *lhs, uacpi_object *rhs)
Definition: interpreter.c:3580
static uacpi_status handle_create_data_region(struct execution_context *ctx)
Definition: interpreter.c:1285
static uacpi_status op_typecheck(const struct op_context *op_ctx, const struct op_context *cur_op_ctx)
Definition: interpreter.c:5084
#define EXEC_OP_WARN(reason)
Definition: interpreter.c:5019
static uacpi_bool object_is_namespace_only(uacpi_object *obj)
Definition: interpreter.c:2492
uacpi_status uacpi_osi(uacpi_handle handle, uacpi_object *retval)
Definition: interpreter.c:6566
static const uacpi_u8 * op_decode_cursor(const struct op_context *ctx)
Definition: interpreter.c:4975
static uacpi_status handle_index(struct execution_context *ctx)
Definition: interpreter.c:2859
return ret
Definition: mutex.c:147
action
Definition: namespace.c:714
r parent
Definition: btrfs.c:3010
#define is_hex(c)
Definition: registry.c:430
#define DYNAMIC_ARRAY_WITH_INLINE_STORAGE_IMPL(name, type, prefix)
#define DYNAMIC_ARRAY_WITH_INLINE_STORAGE(name, type, inline_capacity)
Definition: dynamic_array.h:7
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
GLint level
Definition: gl.h:1546
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei width
Definition: gl.h:1546
GLuint buffer
Definition: glext.h:5915
GLuint res
Definition: glext.h:9613
GLenum src
Definition: glext.h:6340
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
GLuint GLuint GLuint GLuint arg1
Definition: glext.h:9513
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLint left
Definition: glext.h:7726
GLenum GLenum dst
Definition: glext.h:6340
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
const char cursor[]
Definition: icontest.c:13
uacpi_status uacpi_notify_all(uacpi_namespace_node *node, uacpi_u64 value)
Definition: notify.c:96
void uacpi_opregion_uninstall_handler(uacpi_namespace_node *node)
Definition: opregion.c:492
uacpi_status uacpi_initialize_opregion_node(uacpi_namespace_node *node)
Definition: opregion.c:1065
uacpi_status uacpi_handle_osi(const uacpi_char *string, uacpi_bool *out_value)
Definition: osi.c:362
#define UACPI_PRI_TBL_HDR
Definition: tables.h:58
uacpi_status uacpi_table_install_with_origin(void *virt, enum uacpi_table_origin origin, uacpi_table *out_table)
Definition: tables.c:935
void uacpi_table_mark_as_loaded(uacpi_size idx)
Definition: tables.c:1308
#define UACPI_FMT_TBL_HDR(hdr)
Definition: tables.h:59
#define UACPI_NANOSECONDS_PER_SEC
Definition: utilities.h:45
uacpi_status uacpi_string_to_integer(const uacpi_char *str, uacpi_size max_chars, enum uacpi_base base, uacpi_u64 *out_value)
Definition: utilities.c:233
uacpi_bool uacpi_is_valid_nameseg(uacpi_u8 *nameseg)
Definition: utilities.c:315
@ UACPI_BASE_AUTO
Definition: utilities.h:31
void uacpi_free_dynamic_string(const uacpi_char *str)
Definition: utilities.c:1148
uacpi_table_load_cause
Definition: interpreter.h:9
@ UACPI_TABLE_LOAD_CAUSE_HOST
Definition: interpreter.h:13
@ UACPI_TABLE_LOAD_CAUSE_INIT
Definition: interpreter.h:12
@ UACPI_TABLE_LOAD_CAUSE_LOAD_OP
Definition: interpreter.h:10
@ UACPI_TABLE_LOAD_CAUSE_LOAD_TABLE_OP
Definition: interpreter.h:11
uint32_t entry
Definition: isohybrid.c:63
static BOOL is_null(jsval_t v)
Definition: jsval.h:185
void * uacpi_kernel_alloc(uacpi_size size)
Definition: uacpiosl.c:111
void uacpi_kernel_stall(uacpi_u8 usec)
Definition: uacpiosl.c:42
void uacpi_kernel_sleep(uacpi_u64 msec)
Definition: uacpiosl.c:47
#define UACPI_MAP_FAILED
Definition: kernel_api.h:13
uacpi_u64 uacpi_kernel_get_nanoseconds_since_boot(void)
Definition: uacpiosl.c:35
uacpi_status uacpi_kernel_handle_firmware_request(uacpi_firmware_request *)
Definition: uacpiosl.c:177
void uacpi_kernel_unmap(void *addr, uacpi_size len)
Definition: uacpiosl.c:198
void * uacpi_kernel_map(uacpi_phys_addr addr, uacpi_size len)
Definition: uacpiosl.c:191
__u16 time
Definition: mkdosfs.c:8
static int blocks
Definition: mkdosfs.c:527
char string[160]
Definition: util.h:11
static PVOID ptr
Definition: dispmode.c:27
static HANDLE PIO_APC_ROUTINE PVOID PIO_STATUS_BLOCK ULONG PVOID ULONG PVOID ULONG out_size
Definition: file.c:72
static TCHAR * items[]
Definition: page1.c:45
static BOOL is_string(parse_buffer *buf)
Definition: parsing.c:581
static HANDLE proc()
Definition: pdb.c:32
for(i=0;i< sizeof(testsuite)/sizeof(testsuite[0]);++i) ok(call_test(testsuite[i].func)
const WCHAR * str
static calc_node_t * pop(void)
Definition: rpn_ieee.c:90
static calc_node_t temp
Definition: rpn_ieee.c:38
static uacpi_u32 uacpi_shareable_ref(uacpi_handle handle)
Definition: shareable.h:40
wchar_t const *const size_t const buffer_size
Definition: stat.cpp:95
Definition: vfat.h:185
Definition: match.c:390
uacpi_u32 prev_while_code_offset
Definition: interpreter.c:281
struct uacpi_namespace_node * cur_scope
Definition: interpreter.c:285
uacpi_object * locals[8]
Definition: interpreter.c:271
struct temp_namespace_node_array temp_nodes
Definition: interpreter.c:275
struct op_context_array pending_ops
Definition: interpreter.c:273
uacpi_u32 code_offset
Definition: interpreter.c:283
uacpi_size last_while_idx_plus_one
Definition: interpreter.c:278
uacpi_object * args[7]
Definition: interpreter.c:270
struct uacpi_control_method * method
Definition: interpreter.c:268
struct code_block_array code_blocks
Definition: interpreter.c:274
uacpi_u64 prev_while_expiration
Definition: interpreter.c:280
uacpi_u8 prev_sync_level
Definition: interpreter.c:288
uacpi_u32 end
Definition: interpreter.c:96
enum code_block_type type
Definition: interpreter.c:95
uacpi_u32 begin
Definition: interpreter.c:96
struct uacpi_namespace_node * node
Definition: interpreter.c:98
uacpi_u64 expiration_point
Definition: interpreter.c:99
Definition: inflate.c:139
uacpi_u8 sync_level
Definition: interpreter.c:337
struct op_context * prev_op_ctx
Definition: interpreter.c:334
struct code_block * cur_block
Definition: interpreter.c:332
struct held_mutexes_array held_mutexes
Definition: interpreter.c:329
struct call_frame * cur_frame
Definition: interpreter.c:331
struct call_frame_array call_stack
Definition: interpreter.c:328
struct op_context * cur_op_ctx
Definition: interpreter.c:335
uacpi_object * ret
Definition: interpreter.c:327
const struct uacpi_op_spec * cur_op
Definition: interpreter.c:333
struct uacpi_field_unit * field1
Definition: interpreter.c:1695
struct uacpi_field_unit * field0
Definition: interpreter.c:1694
uacpi_namespace_node * region
Definition: interpreter.c:1693
Definition: parser.c:44
uacpi_u64 immediate
Definition: interpreter.c:44
uacpi_u8 type
Definition: interpreter.c:38
struct uacpi_namespace_node * node
Definition: interpreter.c:42
uacpi_object * obj
Definition: interpreter.c:41
uacpi_handle handle
Definition: interpreter.c:40
struct package_length pkg
Definition: interpreter.c:43
uacpi_u8 immediate_bytes[8]
Definition: interpreter.c:45
Definition: module.h:456
Definition: name.c:39
uacpi_u8 tracked_pkg_idx
Definition: interpreter.c:60
uacpi_bool preempted
Definition: interpreter.c:54
const struct uacpi_op_spec * op
Definition: interpreter.c:64
struct item_array items
Definition: interpreter.c:65
uacpi_u8 pc
Definition: interpreter.c:53
uacpi_aml_op switched_from
Definition: interpreter.c:62
uacpi_u32 begin
Definition: interpreter.c:33
uacpi_u32 end
Definition: interpreter.c:34
Definition: queue.c:179
Definition: tools.h:99
Definition: dhcpd.h:248
Definition: cmds.c:130
uacpi_buffer * buffer
Definition: types.h:49
uacpi_size idx
Definition: types.h:48
uacpi_size size
Definition: types.h:31
uacpi_char * text
Definition: types.h:29
void * data
Definition: types.h:27
uacpi_u8 named_objects_persist
Definition: types.h:181
uacpi_u8 * code
Definition: types.h:173
uacpi_u32 size
Definition: types.h:177
uacpi_char * text
Definition: types.h:99
uacpi_size length
Definition: types.h:105
void * data
Definition: types.h:102
uacpi_u8 * bytes
Definition: types.h:96
struct uacpi_firmware_request::@810::@813 fatal
struct uacpi_firmware_request::@810::@812 breakpoint
uacpi_object_name name
Definition: namespace.h:29
uacpi_object * object
Definition: namespace.h:31
struct uacpi_namespace_node * parent
Definition: namespace.h:32
uacpi_control_method * method
Definition: types.h:267
uacpi_u8 type
Definition: types.h:252
uacpi_field_unit * field_unit
Definition: types.h:279
uacpi_buffer_field buffer_field
Definition: types.h:265
uacpi_u64 integer
Definition: types.h:263
uacpi_object * inner_object
Definition: types.h:266
uacpi_buffer * buffer
Definition: types.h:268
uacpi_u8 * indirect_decode_ops
Definition: opcodes.h:296
uacpi_u8 properties
Definition: opcodes.h:298
uacpi_u8 decode_ops[16]
Definition: opcodes.h:295
uacpi_u64 offset
Definition: types.h:125
uacpi_u64 table_idx
Definition: types.h:130
uacpi_u16 space
Definition: types.h:123
uacpi_u64 length
Definition: types.h:126
uacpi_object ** objects
Definition: types.h:36
uacpi_size count
Definition: types.h:37
uacpi_u8 system_level
Definition: types.h:162
uacpi_u16 resource_order
Definition: types.h:163
uacpi_object_name signature
Definition: tables.h:16
char oem_table_id[8]
Definition: tables.h:22
uacpi_size index
Definition: tables.h:33
uacpi_status uacpi_table_find(const uacpi_table_identifiers *id, uacpi_table *out_table)
Definition: tables.c:1178
uacpi_status uacpi_table_unref(uacpi_table *)
Definition: tables.c:1357
@ UACPI_TABLE_ORIGIN_FIRMWARE_VIRTUAL
Definition: tables.h:188
Character const *const prefix
Definition: tempnam.cpp:195
#define byte(x, n)
Definition: tomcrypt.h:118
Definition: dlist.c:348
uacpi_u32 id
Definition: types.h:25
uacpi_char text[4]
Definition: types.h:24
Definition: pdh_main.c:64
struct _slot slot
Definition: vfat.h:196
static const WCHAR props[]
Definition: wbemdisp.c:288
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
int retval
Definition: wcstombs.cpp:91
void * arg
Definition: msvc.h:10
static unsigned int block
Definition: xmlmemory.c:101