ReactOS 0.4.17-dev-683-g0dafdc5
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 if (uacpi_unlikely(declared_size->integer == 0)) {
751 uacpi_error("attempted to create an empty buffer");
753 }
754
755 buffer_size = declared_size->integer;
756 if (uacpi_unlikely(init_size > buffer_size)) {
758 "too many buffer initializers: %u (size is %u)",
759 init_size, buffer_size
760 );
762 }
763
764 dst = item_array_at(&op_ctx->items, 3)->obj;
765 dst->buffer->data = uacpi_kernel_alloc(buffer_size);
766 if (uacpi_unlikely(dst->buffer->data == UACPI_NULL))
768 dst->buffer->size = buffer_size;
769
770 uacpi_memcpy_zerout(dst->buffer->data, src, buffer_size, init_size);
771 return UACPI_STATUS_OK;
772}
773
775{
776 struct call_frame *frame = ctx->cur_frame;
778
780 uacpi_size length, max_bytes;
781
782 obj = item_array_last(&ctx->cur_op_ctx->items)->obj;
783 string = call_frame_cursor(frame);
784
785 // TODO: sanitize string for valid UTF-8
786 max_bytes = call_frame_code_bytes_left(frame);
787 length = uacpi_strnlen(string, max_bytes);
788
789 if (uacpi_unlikely((length == max_bytes) || (string[length++] != 0x00)))
791
792 obj->buffer->text = uacpi_kernel_alloc(length);
793 if (uacpi_unlikely(obj->buffer->text == UACPI_NULL))
795
796 uacpi_memcpy(obj->buffer->text, string, length);
797 obj->buffer->size = length;
798 frame->code_offset += length;
799 return UACPI_STATUS_OK;
800}
801
803{
804 struct op_context *op_ctx = ctx->cur_op_ctx;
805 uacpi_package *package;
806 uacpi_u32 num_elements, num_defined_elements, i;
807
808 /*
809 * Layout of items here:
810 * [0] -> Package length, not interesting
811 * [1] -> Immediate or integer object, depending on PackageOp/VarPackageOp
812 * [2..N-2] -> AML pc+Package element pairs
813 * [N-1] -> The resulting package object that we're constructing
814 */
815 package = item_array_last(&op_ctx->items)->obj->package;
816
817 // 1. Detect how many elements we have, do sanity checking
818 if (op_ctx->op->code == UACPI_AML_OP_VarPackageOp) {
819 uacpi_object *var_num_elements;
820
821 var_num_elements = item_array_at(&op_ctx->items, 1)->obj;
822 if (uacpi_unlikely(var_num_elements->integer > 0xE0000000)) {
824 "package is too large (%"UACPI_PRIu64"), assuming "
825 "corrupted bytestream", UACPI_FMT64(var_num_elements->integer)
826 );
828 }
829 num_elements = var_num_elements->integer;
830 } else {
831 num_elements = item_array_at(&op_ctx->items, 1)->immediate;
832 }
833
834 num_defined_elements = (item_array_size(&op_ctx->items) - 3) / 2;
835 if (uacpi_unlikely(num_defined_elements > num_elements)) {
837 "too many package initializers: %u, truncating to %u",
838 num_defined_elements, num_elements
839 );
840
841 num_defined_elements = num_elements;
842 }
843
844 // 2. Create every object in the package, start as uninitialized
845 if (uacpi_unlikely(!uacpi_package_fill(package, num_elements,
848
849 // 3. Go through every defined object and copy it into the package
850 for (i = 0; i < num_defined_elements; ++i) {
851 uacpi_size base_pkg_index;
853 struct item *item;
855
856 base_pkg_index = (i * 2) + 2;
857 item = item_array_at(&op_ctx->items, base_pkg_index + 1);
858 obj = item->obj;
859
860 if (obj != UACPI_NULL && obj->type == UACPI_OBJECT_REFERENCE) {
861 /*
862 * For named objects we don't actually need the object itself, but
863 * simply the path to it. Often times objects referenced by the
864 * package are not defined until later so it's not possible to
865 * resolve them. For uniformity and to follow the behavior of NT,
866 * simply convert the name string to a path string object to be
867 * resolved later when actually needed.
868 */
869 if (obj->flags == UACPI_REFERENCE_KIND_NAMED) {
872 obj = UACPI_NULL;
873 } else {
875 }
876 }
877
878 if (obj == UACPI_NULL) {
881
885
887 ctx->cur_frame,
888 item_array_at(&op_ctx->items, base_pkg_index)->immediate,
889 &path, &length
890 );
893 return ret;
894 }
895
897 obj->buffer->text = path;
898 obj->buffer->size = length;
899
900 item->obj = obj;
902 }
903
904 ret = uacpi_object_assign(package->objects[i], obj,
907 return ret;
908 }
909
910 return UACPI_STATUS_OK;
911}
912
914{
915 return g_uacpi_rt_ctx.is_rev1 ? 4 : 8;
916}
917
919 uacpi_object *obj, uacpi_data_view *out_buf, uacpi_bool include_null
920)
921{
922 switch (obj->type) {
924 out_buf->length = sizeof_int();
925 out_buf->data = &obj->integer;
926 break;
928 out_buf->length = obj->buffer->size;
929 if (out_buf->length && !include_null)
930 out_buf->length--;
931
932 out_buf->text = obj->buffer->text;
933 break;
935 if (obj->buffer->size == 0) {
936 out_buf->bytes = UACPI_NULL;
937 out_buf->length = 0;
938 break;
939 }
940
941 out_buf->length = obj->buffer->size;
942 out_buf->bytes = obj->buffer->data;
943 break;
946 default:
948 }
949
950 return UACPI_STATUS_OK;
951}
952
954{
955 uacpi_u8 *out_cursor;
956
957 out_cursor = buf_idx->buffer->data;
958 out_cursor += buf_idx->idx;
959
960 return out_cursor;
961}
962
964 uacpi_data_view *src_buf)
965{
967 1, src_buf->length);
968}
969
970/*
971 * The word "implicit cast" here is only because it's called that in
972 * the specification. In reality, we just copy one buffer to another
973 * because that's what NT does.
974 */
977)
978{
980 uacpi_data_view src_buf;
981
984 goto out_bad_cast;
985
986 switch (dst->type) {
989 case UACPI_OBJECT_BUFFER: {
990 uacpi_data_view dst_buf;
991
994 goto out_bad_cast;
995
997 dst_buf.bytes, src_buf.bytes, dst_buf.length, src_buf.length
998 );
999 break;
1000 }
1001
1004 &dst->buffer_field, src_buf.bytes, src_buf.length
1005 );
1006 break;
1007
1010 dst->field_unit, src_buf.bytes, src_buf.length,
1011 wtr_response
1012 );
1013
1015 write_buffer_index(&dst->buffer_index, &src_buf);
1016 break;
1017
1018 default:
1020 goto out_bad_cast;
1021 }
1022
1023 return ret;
1024
1025out_bad_cast:
1027 "attempted to perform an invalid implicit cast (%s -> %s)",
1030 );
1031 return ret;
1032}
1033
1037};
1038
1040 struct execution_context *ctx,
1042)
1043{
1044 uacpi_object **src;
1045 struct item *dst;
1046 enum uacpi_reference_kind kind;
1047
1048 if (type == ARGX) {
1049 src = &ctx->cur_frame->args[idx];
1051 } else {
1052 src = &ctx->cur_frame->locals[idx];
1054 }
1055
1056 if (*src == UACPI_NULL) {
1057 uacpi_object *default_value;
1058
1060 if (uacpi_unlikely(default_value == UACPI_NULL))
1062
1063 *src = uacpi_create_internal_reference(kind, default_value);
1064 if (uacpi_unlikely(*src == UACPI_NULL))
1066
1067 uacpi_object_unref(default_value);
1068 }
1069
1070 dst = item_array_last(&ctx->cur_op_ctx->items);
1071 dst->obj = *src;
1072 dst->type = ITEM_OBJECT;
1073 uacpi_object_ref(dst->obj);
1074
1075 return UACPI_STATUS_OK;
1076}
1077
1079{
1081 struct op_context *op_ctx = ctx->cur_op_ctx;
1082
1083 idx = op_ctx->op->code - UACPI_AML_OP_Local0Op;
1085}
1086
1088{
1090 struct op_context *op_ctx = ctx->cur_op_ctx;
1091
1092 idx = op_ctx->op->code - UACPI_AML_OP_Arg0Op;
1093 return handle_arg_or_local(ctx, idx, ARGX);
1094}
1095
1097{
1098 struct uacpi_namespace_node *src;
1099 struct item *dst;
1100
1101 src = item_array_at(&ctx->cur_op_ctx->items, 0)->node;
1102 dst = item_array_at(&ctx->cur_op_ctx->items, 1);
1103
1104 dst->obj = src->object;
1105 dst->type = ITEM_OBJECT;
1106 uacpi_object_ref(dst->obj);
1107
1108 return UACPI_STATUS_OK;
1109}
1110
1112{
1114
1115 src = item_array_at(&ctx->cur_op_ctx->items, 0)->node;
1116 dst = item_array_at(&ctx->cur_op_ctx->items, 1)->node;
1117
1118 dst->object = src->object;
1120 uacpi_object_ref(dst->object);
1121
1122 return UACPI_STATUS_OK;
1123}
1124
1126{
1129 uacpi_operation_region *op_region;
1130 uacpi_u64 region_end;
1131
1132 node = item_array_at(&ctx->cur_op_ctx->items, 0)->node;
1133 obj = item_array_at(&ctx->cur_op_ctx->items, 4)->obj;
1134 op_region = obj->op_region;
1135
1136 op_region->space = item_array_at(&ctx->cur_op_ctx->items, 1)->immediate;
1137 op_region->offset = item_array_at(&ctx->cur_op_ctx->items, 2)->obj->integer;
1138 op_region->length = item_array_at(&ctx->cur_op_ctx->items, 3)->obj->integer;
1139 region_end = op_region->offset + op_region->length;
1140
1141 if (uacpi_unlikely(op_region->length == 0)) {
1142 // Don't abort here, as long as it's never accessed we don't care
1143 uacpi_warn("unusable/empty operation region %.4s", node->name.text);
1144 } else if (uacpi_unlikely(op_region->offset > region_end)) {
1146 "invalid operation region %.4s bounds: offset=0x%"UACPI_PRIX64
1147 " length=0x%"UACPI_PRIX64"", node->name.text,
1148 UACPI_FMT64(op_region->offset), UACPI_FMT64(op_region->length)
1149 );
1151 }
1152
1153 if (op_region->space == UACPI_ADDRESS_SPACE_PCC && op_region->offset > 255) {
1154 uacpi_warn(
1155 "invalid PCC operation region %.4s subspace %"UACPI_PRIX64,
1156 node->name.text, UACPI_FMT64(op_region->offset)
1157 );
1158 }
1159
1162 );
1163 if (uacpi_unlikely(node->object == UACPI_NULL))
1165
1167 return UACPI_STATUS_OK;
1168}
1169
1171 const uacpi_char *opcode, const uacpi_char *arg,
1173)
1174{
1175 uacpi_error("%s: invalid %s '%s'", opcode, arg, str->text);
1177}
1178
1180 const uacpi_char *opcode, struct uacpi_table_identifiers *id,
1182)
1183{
1185 "%s: unable to find table '%.4s' (OEM ID '%.6s', "
1186 "OEM Table ID '%.8s'): %s",
1187 opcode, id->signature.text, id->oemid, id->oem_table_id,
1189 );
1190}
1191
1193 const uacpi_char *opcode,
1194 struct uacpi_table_identifiers *out_id,
1196 uacpi_buffer *oem_table_id
1197)
1198{
1199 if (uacpi_unlikely(signature->size != (sizeof(uacpi_object_name) + 1)))
1200 return table_id_error(opcode, "SignatureString", signature);
1201
1202 uacpi_memcpy(out_id->signature.text, signature->text,
1203 sizeof(uacpi_object_name));
1204
1205 if (uacpi_unlikely(oem_id->size > (sizeof(out_id->oemid) + 1)))
1206 return table_id_error(opcode, "OemIDString", oem_id);
1207
1209 out_id->oemid, oem_id->text,
1210 sizeof(out_id->oemid), oem_id->size ? oem_id->size - 1 : 0
1211 );
1212
1213 if (uacpi_unlikely(oem_table_id->size > (sizeof(out_id->oem_table_id) + 1)))
1214 return table_id_error(opcode, "OemTableIDString", oem_table_id);
1215
1217 out_id->oem_table_id, oem_table_id->text,
1218 sizeof(out_id->oem_table_id),
1219 oem_table_id->size ? oem_table_id->size - 1 : 0
1220 );
1221
1222 return UACPI_STATUS_OK;
1223}
1224
1226{
1228 struct item_array *items = &ctx->cur_op_ctx->items;
1229 struct uacpi_table_identifiers table_id;
1233 uacpi_operation_region *op_region;
1234
1235 node = item_array_at(items, 0)->node;
1236
1238 "DataTableRegion", &table_id,
1239 item_array_at(items, 1)->obj->buffer,
1240 item_array_at(items, 2)->obj->buffer,
1241 item_array_at(items, 3)->obj->buffer
1242 );
1244 return ret;
1245
1246 ret = uacpi_table_find(&table_id, &table);
1248 report_table_id_find_error("DataTableRegion", &table_id, ret);
1249 return ret;
1250 }
1251
1252 obj = item_array_at(items, 4)->obj;
1253 op_region = obj->op_region;
1255 op_region->offset = table.virt_addr;
1256 op_region->length = table.hdr->length;
1257 op_region->table_idx = table.index;
1258
1261 );
1262 if (uacpi_unlikely(node->object == UACPI_NULL))
1264
1266 return UACPI_STATUS_OK;
1267}
1268
1270{
1271 return cause != UACPI_TABLE_LOAD_CAUSE_INIT;
1272}
1273
1275 void *ptr, enum uacpi_table_load_cause cause,
1276 uacpi_control_method *in_method
1277)
1278{
1279 struct acpi_dsdt *dsdt = ptr;
1280 uacpi_log_level log_level = UACPI_LOG_TRACE;
1281 const uacpi_char *log_prefix = "load of";
1282
1283 if (uacpi_unlikely(dsdt->hdr.length < sizeof(dsdt->hdr)))
1285
1286 if (is_dynamic_table_load(cause)) {
1287 log_prefix = cause == UACPI_TABLE_LOAD_CAUSE_HOST ?
1288 "host-invoked load of" : "dynamic load of";
1289 log_level = UACPI_LOG_INFO;
1290 }
1291
1293 log_level, "%s "UACPI_PRI_TBL_HDR,
1294 log_prefix, UACPI_FMT_TBL_HDR(&dsdt->hdr)
1295 );
1296
1297 in_method->code = dsdt->definition_block;
1298 in_method->size = dsdt->hdr.length - sizeof(dsdt->hdr);
1299 in_method->named_objects_persist = UACPI_TRUE;
1300
1301 return UACPI_STATUS_OK;
1302}
1303
1305 uacpi_namespace_node *parent, struct acpi_sdt_hdr *tbl,
1306 enum uacpi_table_load_cause cause
1307)
1308{
1309 struct uacpi_control_method method = { 0 };
1311
1312 ret = prepare_table_load(tbl, cause, &method);
1314 return ret;
1315
1318 return ret;
1319
1320 if (is_dynamic_table_load(cause))
1322
1323 return ret;
1324}
1325
1327{
1329 struct item_array *items = &ctx->cur_op_ctx->items;
1330 struct item *root_node_item;
1331 struct uacpi_table_identifiers table_id;
1333 uacpi_buffer *root_path, *param_path;
1335 uacpi_namespace_node *root_node, *param_node = UACPI_NULL;
1336
1337 /*
1338 * If we already have the last true/false object loaded, this is a second
1339 * invocation of this handler. For the second invocation we want to detect
1340 * new AML GPE handlers that might've been loaded, as well as potentially
1341 * remove the target.
1342 */
1343 if (item_array_size(items) == 12) {
1345 struct uacpi_table tmp_table = { 0 };
1346
1347 idx = item_array_at(items, 2)->immediate;
1348 tmp_table.index = idx;
1349 uacpi_table_unref(&tmp_table);
1350
1351 /*
1352 * If this load failed, remove the target that was provided via
1353 * ParameterPathString so that it doesn't get stored to.
1354 */
1355 if (uacpi_unlikely(item_array_at(items, 11)->obj->integer == 0)) {
1357
1358 target = item_array_at(items, 3)->obj;
1359 if (target != UACPI_NULL) {
1361 item_array_at(items, 3)->obj = UACPI_NULL;
1362 }
1363
1364 return UACPI_STATUS_OK;
1365 }
1366
1368 return UACPI_STATUS_OK;
1369 }
1370
1372 "LoadTable", &table_id,
1373 item_array_at(items, 5)->obj->buffer,
1374 item_array_at(items, 6)->obj->buffer,
1375 item_array_at(items, 7)->obj->buffer
1376 );
1378 return ret;
1379
1380 root_path = item_array_at(items, 8)->obj->buffer;
1381 param_path = item_array_at(items, 9)->obj->buffer;
1382 root_node_item = item_array_at(items, 0);
1383
1384 if (root_path->size > 1) {
1386 ctx->cur_frame->cur_scope, root_path->text, UACPI_SHOULD_LOCK_NO,
1388 &root_node
1389 );
1391 table_id_error("LoadTable", "RootPathString", root_path);
1394 return ret;
1395 }
1396 } else {
1397 root_node = uacpi_namespace_root();
1398 }
1399
1400 if (param_path->size > 1) {
1401 struct item *param_item;
1402
1404 root_node, param_path->text, UACPI_SHOULD_LOCK_NO,
1406 &param_node
1407 );
1409 table_id_error("LoadTable", "ParameterPathString", root_path);
1412 return ret;
1413 }
1414
1415 param_item = item_array_at(items, 3);
1416 param_item->obj = param_node->object;
1417 uacpi_object_ref(param_item->obj);
1418 param_item->type = ITEM_OBJECT;
1419 }
1420
1421 ret = uacpi_table_find(&table_id, &table);
1423 report_table_id_find_error("LoadTable", &table_id, ret);
1424 return ret;
1425 }
1426
1427 method = item_array_at(items, 1)->obj->method;
1430 );
1433 return ret;
1434 }
1435
1437 item_array_at(items, 2)->immediate = table.index;
1438
1439 root_node_item->node = root_node;
1440 root_node_item->type = ITEM_NAMESPACE_NODE;
1441 uacpi_shareable_ref(root_node);
1442
1443 return UACPI_STATUS_OK;
1444}
1445
1447{
1449 struct item_array *items = &ctx->cur_op_ctx->items;
1453 struct acpi_sdt_hdr *src_table = UACPI_NULL;
1454 void *table_buffer;
1455 uacpi_size declared_size;
1456 uacpi_bool unmap_src = UACPI_FALSE;
1457
1458 /*
1459 * If we already have the last true/false object loaded, this is a second
1460 * invocation of this handler. For the second invocation we simply want to
1461 * detect new AML GPE handlers that might've been loaded.
1462 * We do this only if table load was successful though.
1463 */
1464 if (item_array_size(items) == 6) {
1466 uacpi_table tmp_table = { 0 };
1467
1468 idx = item_array_at(items, 2)->immediate;
1469 tmp_table.index = idx;
1470 uacpi_table_unref(&tmp_table);
1471
1472 if (item_array_at(items, 5)->obj->integer != 0)
1474 return UACPI_STATUS_OK;
1475 }
1476
1477 src = item_array_at(items, 3)->obj;
1478
1479 switch (src->type) {
1481 uacpi_operation_region *op_region;
1482
1483 op_region = src->op_region;
1484 if (uacpi_unlikely(
1486 )) {
1487 uacpi_error("Load: operation region is not SystemMemory");
1489 goto error_out;
1490 }
1491
1492 if (uacpi_unlikely(op_region->length < sizeof(struct acpi_sdt_hdr))) {
1494 "Load: operation region is too small: %"UACPI_PRIu64,
1495 UACPI_FMT64(op_region->length)
1496 );
1498 goto error_out;
1499 }
1500
1501 src_table = uacpi_kernel_map(op_region->offset, op_region->length);
1502 if (uacpi_unlikely(src_table == UACPI_MAP_FAILED)) {
1504 "Load: failed to map operation region "
1505 "0x%016"UACPI_PRIX64" -> 0x%016"UACPI_PRIX64,
1506 UACPI_FMT64(op_region->offset),
1507 UACPI_FMT64(op_region->offset + op_region->length)
1508 );
1510 goto error_out;
1511 }
1512
1513 unmap_src = UACPI_TRUE;
1514 declared_size = op_region->length;
1515 break;
1516 }
1517
1518 case UACPI_OBJECT_BUFFER: {
1520
1521 buffer = src->buffer;
1522 if (buffer->size < sizeof(struct acpi_sdt_hdr)) {
1524 "Load: buffer is too small: %zu",
1525 buffer->size
1526 );
1527
1529 goto error_out;
1530 }
1531
1532 src_table = buffer->data;
1533 declared_size = buffer->size;
1534 break;
1535 }
1536
1537 default:
1539 "Load: invalid argument '%s', expected "
1540 "Buffer/Field/OperationRegion",
1542 );
1544 goto error_out;
1545 }
1546
1547 if (uacpi_unlikely(src_table->length > declared_size)) {
1549 "Load: table size %u is larger than the declared size %zu",
1550 src_table->length, declared_size
1551 );
1553 goto error_out;
1554 }
1555
1556 if (uacpi_unlikely(src_table->length < sizeof(struct acpi_sdt_hdr))) {
1557 uacpi_error("Load: table size %u is too small", src_table->length);
1559 goto error_out;
1560 }
1561
1562 table_buffer = uacpi_kernel_alloc(src_table->length);
1563 if (uacpi_unlikely(table_buffer == UACPI_NULL)) {
1565 goto error_out;
1566 }
1567
1568 uacpi_memcpy(table_buffer, src_table, src_table->length);
1569
1570 if (unmap_src) {
1571 uacpi_kernel_unmap(src_table, declared_size);
1572 unmap_src = UACPI_FALSE;
1573 }
1574
1577 );
1579 uacpi_free(table_buffer, src_table->length);
1580
1581 /*
1582 * Treat DENIED as a soft error, that is, fail the Load but don't abort
1583 * the currently running method. We simply return False to the caller
1584 * to signify an error in this case.
1585 */
1588
1590 goto error_out;
1591 }
1592
1593 method = item_array_at(items, 1)->obj->method;
1597 goto error_out;
1598 }
1599
1601 item_array_at(items, 2)->immediate = table.index;
1602
1603 item_array_at(items, 0)->node = uacpi_namespace_root();
1604 return UACPI_STATUS_OK;
1605
1606error_out:
1607 if (unmap_src && src_table)
1608 uacpi_kernel_unmap(src_table, declared_size);
1609 return ret;
1610}
1611
1613{
1615
1618 return ret;
1619
1620 ret = do_load_table(uacpi_namespace_root(), tbl, cause);
1621
1623 return ret;
1624}
1625
1627{
1628 struct package_length *pkg = &item->pkg;
1629 return pkg->end - pkg->begin;
1630}
1631
1637};
1638
1640 uacpi_field_unit **out_field)
1641{
1643
1645 if (obj->type != UACPI_OBJECT_FIELD_UNIT) {
1647 "invalid argument: '%.4s' is not a field unit (%s)",
1648 node->name.text, uacpi_object_type_to_string(obj->type)
1649 );
1651 }
1652
1653 *out_field = obj->field_unit;
1654 return UACPI_STATUS_OK;
1655}
1656
1658 uacpi_namespace_node **out_node)
1659{
1661
1663 if (obj->type != UACPI_OBJECT_OPERATION_REGION) {
1665 "invalid argument: '%.4s' is not an operation region (%s)",
1666 node->name.text, uacpi_object_type_to_string(obj->type)
1667 );
1669 }
1670
1671 *out_node = node;
1672 return UACPI_STATUS_OK;
1673}
1674
1676{
1678 struct op_context *op_ctx = ctx->cur_op_ctx;
1680 uacpi_object *obj, *connection_obj = UACPI_NULL;
1681 struct field_specific_data field_data = { 0 };
1682 uacpi_size i = 1, bit_offset = 0;
1683 uacpi_u32 length, pin_offset = 0;
1684
1685 uacpi_u8 raw_value, access_type, lock_rule, update_rule;
1686 uacpi_u8 access_attrib = 0, access_length = 0;
1687
1688 switch (op_ctx->op->code) {
1689 case UACPI_AML_OP_FieldOp:
1690 node = item_array_at(&op_ctx->items, i++)->node;
1691 ret = ensure_is_an_op_region(node, &field_data.region);
1693 return ret;
1694 break;
1695
1696 case UACPI_AML_OP_BankFieldOp:
1697 node = item_array_at(&op_ctx->items, i++)->node;
1698 ret = ensure_is_an_op_region(node, &field_data.region);
1700 return ret;
1701
1702 node = item_array_at(&op_ctx->items, i++)->node;
1703 ret = ensure_is_a_field_unit(node, &field_data.field0);
1705 return ret;
1706
1707 field_data.value = item_array_at(&op_ctx->items, i++)->obj->integer;
1708 break;
1709
1710 case UACPI_AML_OP_IndexFieldOp:
1711 node = item_array_at(&op_ctx->items, i++)->node;
1712 ret = ensure_is_a_field_unit(node, &field_data.field0);
1714 return ret;
1715
1716 node = item_array_at(&op_ctx->items, i++)->node;
1717 ret = ensure_is_a_field_unit(node, &field_data.field1);
1719 return ret;
1720 break;
1721
1722 default:
1724 }
1725
1726 /*
1727 * ByteData
1728 * bit 0-3: AccessType
1729 * 0 AnyAcc
1730 * 1 ByteAcc
1731 * 2 WordAcc
1732 * 3 DWordAcc
1733 * 4 QWordAcc
1734 * 5 BufferAcc
1735 * 6 Reserved
1736 * 7-15 Reserved
1737 * bit 4: LockRule
1738 * 0 NoLock
1739 * 1 Lock
1740 * bit 5-6: UpdateRule
1741 * 0 Preserve
1742 * 1 WriteAsOnes
1743 * 2 WriteAsZeros
1744 * bit 7: Reserved (must be 0)
1745 */
1746 raw_value = item_array_at(&op_ctx->items, i++)->immediate;
1747 access_type = (raw_value >> 0) & 0xF;
1748 lock_rule = (raw_value >> 4) & 0x1;
1749 update_rule = (raw_value >> 5) & 0x3;
1750
1751 while (i < item_array_size(&op_ctx->items)) {
1752 struct item *item;
1753 item = item_array_at(&op_ctx->items, i++);
1754
1755 // An actual field object
1756 if (item->type == ITEM_NAMESPACE_NODE) {
1758
1759 length = get_field_length(item_array_at(&op_ctx->items, i++));
1760 node = item->node;
1761
1762 obj = item_array_at(&op_ctx->items, i++)->obj;
1763 field = obj->field_unit;
1764
1765 field->update_rule = update_rule;
1766 field->lock_rule = lock_rule;
1767 field->attributes = access_attrib;
1768 field->access_length = access_length;
1769
1770 /*
1771 * 0 AnyAcc
1772 * 1 ByteAcc
1773 * 2 WordAcc
1774 * 3 DWordAcc
1775 * 4 QWordAcc
1776 * 5 BufferAcc
1777 * 6 Reserved
1778 * 7-15 Reserved
1779 */
1780 switch (access_type) {
1781 case 0:
1782 // TODO: optimize to calculate best access strategy
1784 case 1:
1785 case 5:
1786 field->access_width_bytes = 1;
1787 break;
1788 case 2:
1789 field->access_width_bytes = 2;
1790 break;
1791 case 3:
1792 field->access_width_bytes = 4;
1793 break;
1794 case 4:
1795 field->access_width_bytes = 8;
1796 break;
1797 default:
1798 uacpi_error("invalid field '%.4s' access type %d",
1799 node->name.text, access_type);
1801 }
1802
1803 field->bit_length = length;
1804 field->pin_offset = pin_offset;
1805
1806 // FIXME: overflow, OOB, etc checks
1807 field->byte_offset = UACPI_ALIGN_DOWN(
1808 bit_offset / 8,
1809 field->access_width_bytes,
1811 );
1812
1813 field->bit_offset_within_first_byte =
1814 bit_offset & ((field->access_width_bytes * 8) - 1);
1815
1816 switch (op_ctx->op->code) {
1817 case UACPI_AML_OP_FieldOp:
1818 field->region = field_data.region;
1819 uacpi_shareable_ref(field->region);
1820
1822 break;
1823
1824 case UACPI_AML_OP_BankFieldOp:
1825 field->bank_region = field_data.region;
1826 uacpi_shareable_ref(field->bank_region);
1827
1828 field->bank_selection = field_data.field0;
1829 uacpi_shareable_ref(field->bank_selection);
1830
1831 field->bank_value = field_data.value;
1833 break;
1834
1835 case UACPI_AML_OP_IndexFieldOp:
1836 field->index = field_data.field0;
1837 uacpi_shareable_ref(field->index);
1838
1839 field->data = field_data.field1;
1841
1843 break;
1844
1845 default:
1847 }
1848
1849 field->connection = connection_obj;
1850 if (field->connection)
1851 uacpi_object_ref(field->connection);
1852
1855 );
1856 if (uacpi_unlikely(node->object == UACPI_NULL))
1858
1859 ret = do_install_node_item(ctx->cur_frame, item);
1861 uacpi_object_unref(node->object);
1862 node->object = UACPI_NULL;
1863 return ret;
1864 }
1865
1866 bit_offset += length;
1867 pin_offset += length;
1868 continue;
1869 }
1870
1871 // All other stuff
1872 switch ((int)item->immediate) {
1873 // ReservedField := 0x00 PkgLength
1874 case 0x00:
1875 length = get_field_length(item_array_at(&op_ctx->items, i++));
1876 bit_offset += length;
1877 pin_offset += length;
1878 break;
1879
1880 // AccessField := 0x01 AccessType AccessAttrib
1881 // ExtendedAccessField := 0x03 AccessType ExtendedAccessAttrib AccessLength
1882 case 0x01:
1883 case 0x03:
1884 raw_value = item_array_at(&op_ctx->items, i++)->immediate;
1885
1886 access_type = raw_value & 0xF;
1887 access_attrib = (raw_value >> 6) & 0x3;
1888
1889 raw_value = item_array_at(&op_ctx->items, i++)->immediate;
1890
1891 /*
1892 * Bits 7:6
1893 * 0 = AccessAttrib = Normal Access Attributes
1894 * 1 = AccessAttrib = AttribBytes (x)
1895 * 2 = AccessAttrib = AttribRawBytes (x)
1896 * 3 = AccessAttrib = AttribRawProcessBytes (x)
1897 * x is encoded as bits 0:7 of the AccessAttrib byte.
1898 */
1899 if (access_attrib) {
1900 switch (access_attrib) {
1901 case 1:
1902 access_attrib = UACPI_ACCESS_ATTRIBUTE_BYTES;
1903 break;
1904 case 2:
1905 access_attrib = UACPI_ACCESS_ATTRIBUTE_RAW_BYTES;
1906 break;
1907 case 3:
1909 break;
1910 }
1911
1912 access_length = raw_value;
1913 } else { // Normal access attributes
1914 access_attrib = raw_value;
1915 }
1916
1917 if (item->immediate == 3)
1918 access_length = item_array_at(&op_ctx->items, i++)->immediate;
1919 break;
1920
1921 // ConnectField := <0x02 NameString> | <0x02 BufferData>
1922 case 0x02:
1923 connection_obj = item_array_at(&op_ctx->items, i++)->obj;
1924 pin_offset = 0;
1925 break;
1926
1927 default:
1929 }
1930 }
1931
1932 return UACPI_STATUS_OK;
1933}
1934
1936{
1937 if (!g_uacpi_rt_ctx.is_rev1)
1938 return;
1939
1940 obj->integer &= 0xFFFFFFFF;
1941}
1942
1943static uacpi_u64 ones(void)
1944{
1945 return g_uacpi_rt_ctx.is_rev1 ? 0xFFFFFFFF : 0xFFFFFFFFFFFFFFFF;
1946}
1947
1949 uacpi_object **out_operand)
1950{
1952
1953 // Check if we're targeting the previous call frame
1954 depth = call_frame_array_size(&ctx->call_stack);
1955 if (depth > 1) {
1956 struct op_context *op_ctx;
1957 struct call_frame *frame;
1958
1959 frame = call_frame_array_at(&ctx->call_stack, depth - 2);
1960 depth = op_context_array_size(&frame->pending_ops);
1961
1962 // Ok, no one wants the return value at call site. Discard it.
1963 if (!depth) {
1964 *out_operand = UACPI_NULL;
1965 return UACPI_STATUS_OK;
1966 }
1967
1968 op_ctx = op_context_array_at(&frame->pending_ops, depth - 1);
1969
1970 /*
1971 * Prevent the table being dynamically loaded from attempting to return
1972 * a value to the caller. This is unlikely to be ever encountered in the
1973 * wild, but we should still guard against the possibility.
1974 */
1975 if (uacpi_unlikely(op_ctx->op->code == UACPI_AML_OP_LoadOp ||
1976 op_ctx->op->code == UACPI_AML_OP_LoadTableOp)) {
1977 *out_operand = UACPI_NULL;
1978 return UACPI_STATUS_OK;
1979 }
1980
1981 *out_operand = item_array_last(&op_ctx->items)->obj;
1982 return UACPI_STATUS_OK;
1983 }
1984
1986}
1987
1989 uacpi_object **out_obj)
1990{
1992
1993 ret = method_get_ret_target(ctx, out_obj);
1994 if (ret == UACPI_STATUS_NOT_FOUND) {
1995 *out_obj = ctx->ret;
1996 return UACPI_STATUS_OK;
1997 }
1998 if (ret != UACPI_STATUS_OK || *out_obj == UACPI_NULL)
1999 return ret;
2000
2001 *out_obj = uacpi_unwrap_internal_reference(*out_obj);
2002 return UACPI_STATUS_OK;
2003}
2004
2006 struct code_block_array *blocks, enum code_block_type type,
2007 uacpi_size *out_idx_plus_one
2008)
2009{
2010 uacpi_size i;
2011
2012 i = code_block_array_size(blocks);
2013 while (i-- > 0) {
2014 struct code_block *block;
2015
2016 block = code_block_array_at(blocks, i);
2017 if (block->type == type) {
2018 if (out_idx_plus_one != UACPI_NULL)
2019 *out_idx_plus_one = i + 1;
2020 return block;
2021 }
2022 }
2023
2024 if (out_idx_plus_one != UACPI_NULL)
2025 *out_idx_plus_one = 0;
2026 return UACPI_NULL;
2027}
2028
2030{
2031 struct call_frame *cur_frame = ctx->cur_frame;
2032 struct op_context *op_ctx = ctx->cur_op_ctx;
2033 struct package_length *pkg;
2034 struct code_block *block;
2035
2036 block = code_block_array_alloc(&cur_frame->code_blocks);
2039
2040 pkg = &item_array_at(&op_ctx->items, 0)->pkg;
2041
2042 // Disarm the tracked package so that we don't skip the Scope
2043 op_ctx->tracked_pkg_idx = 0;
2044
2045 switch (op_ctx->op->code) {
2046 case UACPI_AML_OP_IfOp:
2047 block->type = CODE_BLOCK_IF;
2048 break;
2049 case UACPI_AML_OP_ElseOp:
2050 block->type = CODE_BLOCK_ELSE;
2051 break;
2052 case UACPI_AML_OP_WhileOp:
2053 block->type = CODE_BLOCK_WHILE;
2054
2055 if (pkg->begin == cur_frame->prev_while_code_offset) {
2056 uacpi_u64 cur_ticks;
2057
2059
2060 if (uacpi_unlikely(cur_ticks > block->expiration_point)) {
2061 uacpi_error("loop time out after running for %u seconds",
2062 g_uacpi_rt_ctx.loop_timeout_seconds);
2063 code_block_array_pop(&cur_frame->code_blocks);
2065 }
2066
2067 block->expiration_point = cur_frame->prev_while_expiration;
2068 } else {
2069 /*
2070 * Calculate the expiration point for this loop.
2071 * If a loop is executed past this point, it will get aborted.
2072 */
2073 block->expiration_point = uacpi_kernel_get_nanoseconds_since_boot();
2074 block->expiration_point +=
2075 g_uacpi_rt_ctx.loop_timeout_seconds * UACPI_NANOSECONDS_PER_SEC;
2076 }
2077
2078 cur_frame->last_while_idx_plus_one = code_block_array_size(
2079 &cur_frame->code_blocks
2080 );
2081 break;
2082 case UACPI_AML_OP_ScopeOp:
2083 case UACPI_AML_OP_DeviceOp:
2084 case UACPI_AML_OP_ProcessorOp:
2085 case UACPI_AML_OP_PowerResOp:
2086 case UACPI_AML_OP_ThermalZoneOp:
2087 block->type = CODE_BLOCK_SCOPE;
2088 block->node = item_array_at(&op_ctx->items, 1)->node;
2089 cur_frame->cur_scope = block->node;
2090 break;
2091 default:
2092 code_block_array_pop(&cur_frame->code_blocks);
2094 }
2095
2096 // -1 because we want to re-evaluate at the start of the op next time
2097 block->begin = pkg->begin - 1;
2098 block->end = pkg->end;
2099 ctx->cur_block = block;
2100
2101 return UACPI_STATUS_OK;
2102}
2103
2105 enum code_block_type type)
2106{
2107 struct call_frame *frame = ctx->cur_frame;
2108
2109 if (type == CODE_BLOCK_WHILE) {
2110 struct code_block *block = ctx->cur_block;
2111
2112 // + 1 here to skip the WhileOp and get to the PkgLength
2113 frame->prev_while_code_offset = block->begin + 1;
2114 frame->prev_while_expiration = block->expiration_point;
2115 }
2116
2117 code_block_array_pop(&frame->code_blocks);
2118 ctx->cur_block = code_block_array_last(&frame->code_blocks);
2119
2120 if (type == CODE_BLOCK_WHILE) {
2122 &frame->code_blocks, type, &frame->last_while_idx_plus_one
2123 );
2124 } else if (type == CODE_BLOCK_SCOPE) {
2125 struct code_block *block;
2126
2129 );
2130 if (block == UACPI_NULL) {
2132 return;
2133 }
2134
2135 frame->cur_scope = block->node;
2136 }
2137}
2138
2140{
2141 switch (src->type) {
2143 uacpi_trace("%s Uninitialized", prefix);
2144 break;
2146 uacpi_trace("%s String => \"%s\"", prefix, src->buffer->text);
2147 break;
2149 if (g_uacpi_rt_ctx.is_rev1) {
2151 "%s Integer => 0x%08X", prefix, (uacpi_u32)src->integer
2152 );
2153 } else {
2155 "%s Integer => 0x%016"UACPI_PRIX64, prefix,
2156 UACPI_FMT64(src->integer)
2157 );
2158 }
2159 break;
2161 uacpi_trace("%s Reference @%p => %p", prefix, src, src->inner_object);
2162 break;
2165 "%s Package @%p (%p) (%zu elements)",
2166 prefix, src, src->package, src->package->count
2167 );
2168 break;
2171 "%s Buffer @%p (%p) (%zu bytes)",
2172 prefix, src, src->buffer, src->buffer->size
2173 );
2174 break;
2177 "%s OperationRegion (ASID %d) 0x%016"UACPI_PRIX64
2178 " -> 0x%016"UACPI_PRIX64, prefix,
2179 src->op_region->space, UACPI_FMT64(src->op_region->offset),
2180 UACPI_FMT64(src->op_region->offset + src->op_region->length)
2181 );
2182 break;
2185 "%s Power Resource %d %d",
2186 prefix, src->power_resource.system_level,
2187 src->power_resource.resource_order
2188 );
2189 break;
2192 "%s Processor[%d] 0x%08X (%d)",
2193 prefix, src->processor->id, src->processor->block_address,
2194 src->processor->block_length
2195 );
2196 break;
2199 "%s Buffer Index %p[%zu] => 0x%02X",
2200 prefix, src->buffer_index.buffer->data, src->buffer_index.idx,
2201 *buffer_index_cursor(&src->buffer_index)
2202 );
2203 break;
2204 case UACPI_OBJECT_MUTEX:
2206 "%s Mutex @%p (%p => %p) sync level %d",
2207 prefix, src, src->mutex, src->mutex->handle,
2208 src->mutex->sync_level
2209 );
2210 break;
2212 uacpi_trace("%s Method @%p (%p)", prefix, src, src->method);
2213 break;
2214 default:
2216 "%s %s @%p",
2218 );
2219 }
2220}
2221
2223{
2224 /*
2225 * Don't bother running the body if current log level is not set to trace.
2226 * All DebugOp logging is done as TRACE exclusively.
2227 */
2229 return UACPI_STATUS_OK;
2230
2232
2233 debug_store_no_recurse("[AML DEBUG]", src);
2234
2235 if (src->type == UACPI_OBJECT_PACKAGE) {
2236 uacpi_package *pkg = src->package;
2237 uacpi_size i;
2238
2239 for (i = 0; i < pkg->count; ++i) {
2240 uacpi_object *obj = pkg->objects[i];
2241 if (obj->type == UACPI_OBJECT_REFERENCE &&
2243 obj = obj->inner_object;
2244
2245 debug_store_no_recurse("Element:", obj);
2246 }
2247 }
2248
2249 return UACPI_STATUS_OK;
2250}
2251
2252/*
2253 * NOTE: this function returns the parent object
2254 */
2256{
2258
2259 while (obj) {
2260 if (obj->type != UACPI_OBJECT_REFERENCE)
2261 return parent;
2262
2263 parent = obj;
2264 obj = parent->inner_object;
2265 }
2266
2267 // This should be unreachable
2268 return UACPI_NULL;
2269}
2270
2272 void *user, uacpi_namespace_node *node, uacpi_u32 node_depth
2273)
2274{
2275 uacpi_object *target_object = user;
2276 UACPI_UNUSED(node_depth);
2277
2278 if (node->object == target_object) {
2281 }
2282
2284}
2285
2287{
2288 if (parent->flags == UACPI_REFERENCE_KIND_NAMED &&
2290
2291 /*
2292 * We're doing a CopyObject or similar to a namespace node that is an
2293 * operation region. Try to find the parent node and manually detach
2294 * the handler.
2295 */
2301 );
2302 }
2303
2306}
2307
2308/*
2309 * Breakdown of what happens here:
2310 *
2311 * CopyObject(..., Obj) where Obj is:
2312 * 1. LocalX -> Overwrite LocalX.
2313 * 2. NAME -> Overwrite NAME.
2314 * 3. ArgX -> Overwrite ArgX unless ArgX is a reference, in that case
2315 * overwrite the referenced object.
2316 * 4. RefOf -> Not allowed here.
2317 * 5. Index -> Overwrite Object stored at the index.
2318 */
2321{
2323 uacpi_object *src_obj, *new_obj;
2324
2325 switch (dst->flags) {
2327 uacpi_object *referenced_obj;
2328
2329 referenced_obj = uacpi_unwrap_internal_reference(dst);
2330 if (referenced_obj->type == UACPI_OBJECT_REFERENCE) {
2331 dst = reference_unwind(referenced_obj);
2332 break;
2333 }
2334
2336 }
2340 break;
2341 default:
2343 }
2344
2346
2348 if (uacpi_unlikely(new_obj == UACPI_NULL))
2350
2351 ret = uacpi_object_assign(new_obj, src_obj,
2354 return ret;
2355
2356 object_replace_child(dst, new_obj);
2357 uacpi_object_unref(new_obj);
2358
2359 return UACPI_STATUS_OK;
2360}
2361
2362/*
2363 * if Store(..., Obj) where Obj is:
2364 * 1. LocalX/Index -> OVERWRITE unless the object is a reference, in that
2365 * case store to the referenced object _with_ implicit
2366 * cast.
2367 * 2. ArgX -> OVERWRITE unless the object is a reference, in that
2368 * case OVERWRITE the referenced object.
2369 * 3. NAME -> Store with implicit cast.
2370 * 4. RefOf -> Not allowed here.
2371 */
2374)
2375{
2376 uacpi_object *src_obj;
2377 uacpi_bool overwrite = UACPI_FALSE;
2378
2379 switch (dst->flags) {
2383 uacpi_object *referenced_obj;
2384
2385 if (dst->flags == UACPI_REFERENCE_KIND_PKG_INDEX)
2386 referenced_obj = dst->inner_object;
2387 else
2388 referenced_obj = uacpi_unwrap_internal_reference(dst);
2389
2390 if (referenced_obj->type == UACPI_OBJECT_REFERENCE) {
2391 overwrite = dst->flags == UACPI_REFERENCE_KIND_ARG;
2392 dst = reference_unwind(referenced_obj);
2393 break;
2394 }
2395
2396 overwrite = UACPI_TRUE;
2397 break;
2398 }
2401 break;
2402 default:
2404 }
2405
2407 overwrite |= dst->inner_object->type == UACPI_OBJECT_UNINITIALIZED;
2408
2409 if (overwrite) {
2411 uacpi_object *new_obj;
2412
2414 if (uacpi_unlikely(new_obj == UACPI_NULL))
2416
2417 ret = uacpi_object_assign(new_obj, src_obj,
2420 uacpi_object_unref(new_obj);
2421 return ret;
2422 }
2423
2424 object_replace_child(dst, new_obj);
2425 uacpi_object_unref(new_obj);
2426 return UACPI_STATUS_OK;
2427 }
2428
2430 dst->inner_object, src_obj, wtr_response
2431 );
2432}
2433
2435{
2436 struct op_context *op_ctx = ctx->cur_op_ctx;
2437 uacpi_object *dst, *src;
2438
2439 src = item_array_at(&op_ctx->items, 0)->obj;
2440
2441 if (op_ctx->op->code == UACPI_AML_OP_CondRefOfOp)
2442 dst = item_array_at(&op_ctx->items, 2)->obj;
2443 else
2444 dst = item_array_at(&op_ctx->items, 1)->obj;
2445
2447 dst->inner_object = src;
2449 return UACPI_STATUS_OK;
2450}
2451
2454 uacpi_object *tgt0, uacpi_object *tgt1,
2456)
2457{
2458 uacpi_u64 lhs, rhs, res;
2459 uacpi_bool should_negate = UACPI_FALSE;
2460
2461 lhs = arg0->integer;
2462 rhs = arg1->integer;
2463
2464 switch (op)
2465 {
2466 case UACPI_AML_OP_AddOp:
2467 res = lhs + rhs;
2468 break;
2469 case UACPI_AML_OP_SubtractOp:
2470 res = lhs - rhs;
2471 break;
2472 case UACPI_AML_OP_MultiplyOp:
2473 res = lhs * rhs;
2474 break;
2475 case UACPI_AML_OP_ShiftLeftOp:
2476 case UACPI_AML_OP_ShiftRightOp:
2477 if (rhs <= (g_uacpi_rt_ctx.is_rev1 ? 31 : 63)) {
2478 if (op == UACPI_AML_OP_ShiftLeftOp)
2479 res = lhs << rhs;
2480 else
2481 res = lhs >> rhs;
2482 } else {
2483 res = 0;
2484 }
2485 break;
2486 case UACPI_AML_OP_NandOp:
2487 should_negate = UACPI_TRUE;
2489 case UACPI_AML_OP_AndOp:
2490 res = rhs & lhs;
2491 break;
2492 case UACPI_AML_OP_NorOp:
2493 should_negate = UACPI_TRUE;
2495 case UACPI_AML_OP_OrOp:
2496 res = rhs | lhs;
2497 break;
2498 case UACPI_AML_OP_XorOp:
2499 res = rhs ^ lhs;
2500 break;
2501 case UACPI_AML_OP_DivideOp:
2502 if (uacpi_unlikely(rhs == 0)) {
2503 uacpi_error("attempted to divide by zero");
2505 }
2506 tgt1->integer = lhs / rhs;
2507 res = lhs % rhs;
2508 break;
2509 case UACPI_AML_OP_ModOp:
2510 if (uacpi_unlikely(rhs == 0)) {
2511 uacpi_error("attempted to calculate modulo of zero");
2513 }
2514 res = lhs % rhs;
2515 break;
2516 default:
2518 }
2519
2520 if (should_negate)
2521 res = ~res;
2522
2523 tgt0->integer = res;
2524 return UACPI_STATUS_OK;
2525}
2526
2528{
2529 uacpi_object *arg0, *arg1, *tgt0, *tgt1;
2530 struct item_array *items = &ctx->cur_op_ctx->items;
2531 uacpi_aml_op op = ctx->cur_op_ctx->op->code;
2532
2533 arg0 = item_array_at(items, 0)->obj;
2534 arg1 = item_array_at(items, 1)->obj;
2535
2536 if (op == UACPI_AML_OP_DivideOp) {
2537 tgt0 = item_array_at(items, 4)->obj;
2538 tgt1 = item_array_at(items, 5)->obj;
2539 } else {
2540 tgt0 = item_array_at(items, 3)->obj;
2541 tgt1 = UACPI_NULL;
2542 }
2543
2544 return do_binary_math(arg0, arg1, tgt0, tgt1, op);
2545}
2546
2548{
2549 uacpi_object *arg, *tgt;
2550 struct item_array *items = &ctx->cur_op_ctx->items;
2551 uacpi_aml_op op = ctx->cur_op_ctx->op->code;
2552
2553 arg = item_array_at(items, 0)->obj;
2554 tgt = item_array_at(items, 2)->obj;
2555
2556 switch (op) {
2557 case UACPI_AML_OP_NotOp:
2558 tgt->integer = ~arg->integer;
2560 break;
2561 case UACPI_AML_OP_FindSetRightBitOp:
2562 tgt->integer = uacpi_bit_scan_forward(arg->integer);
2563 break;
2564 case UACPI_AML_OP_FindSetLeftBitOp:
2565 tgt->integer = uacpi_bit_scan_backward(arg->integer);
2566 break;
2567 default:
2569 }
2570
2571 return UACPI_STATUS_OK;
2572}
2573
2575 uacpi_size src_size)
2576{
2577 if (uacpi_likely(idx < src_size))
2578 return UACPI_STATUS_OK;
2579
2581 "invalid index %zu, %s@%p has %zu elements",
2582 idx, uacpi_object_type_to_string(obj->type), obj, src_size
2583 );
2585}
2586
2588{
2590 struct op_context *op_ctx = ctx->cur_op_ctx;
2592 struct item *dst;
2594
2595 src = item_array_at(&op_ctx->items, 0)->obj;
2596 idx = item_array_at(&op_ctx->items, 1)->obj->integer;
2597 dst = item_array_at(&op_ctx->items, 3);
2598
2599 switch (src->type) {
2601 case UACPI_OBJECT_STRING: {
2602 uacpi_buffer_index *buf_idx;
2605
2606 ret = ensure_valid_idx(src, idx, buf.length);
2608 return ret;
2609
2610 dst->type = ITEM_OBJECT;
2612 if (uacpi_unlikely(dst->obj == UACPI_NULL))
2614
2615 buf_idx = &dst->obj->buffer_index;
2616 buf_idx->idx = idx;
2617 buf_idx->buffer = src->buffer;
2618 uacpi_shareable_ref(buf_idx->buffer);
2619
2620 break;
2621 }
2622 case UACPI_OBJECT_PACKAGE: {
2623 uacpi_package *pkg = src->package;
2625
2626 ret = ensure_valid_idx(src, idx, pkg->count);
2628 return ret;
2629
2630 /*
2631 * Lazily transform the package element into an internal reference
2632 * to itself of type PKG_INDEX. This is needed to support stuff like
2633 * CopyObject(..., Index(pkg, X)) where the new object must be
2634 * propagated to anyone else with a currently alive index object.
2635 *
2636 * Sidenote: Yes, IndexOp is not a SimpleName, so technically it is
2637 * illegal to CopyObject to it. However, yet again we fall
2638 * victim to the NT ACPI driver implementation, which allows
2639 * it just fine.
2640 */
2641 obj = pkg->objects[idx];
2642 if (obj->type != UACPI_OBJECT_REFERENCE ||
2644
2647 );
2650
2651 pkg->objects[idx] = obj;
2652 uacpi_object_unref(obj->inner_object);
2653 }
2654
2655 dst->obj = obj;
2656 dst->type = ITEM_OBJECT;
2657 uacpi_object_ref(dst->obj);
2658 break;
2659 }
2660 default:
2662 "invalid argument for Index: %s, "
2663 "expected String/Buffer/Package",
2665 );
2667 }
2668
2669 return UACPI_STATUS_OK;
2670}
2671
2673 uacpi_size max_buffer_bytes)
2674{
2675 uacpi_u64 dst;
2676
2677 switch (obj->type) {
2679 dst = obj->integer;
2680 break;
2681 case UACPI_OBJECT_BUFFER: {
2683 bytes = UACPI_MIN(max_buffer_bytes, obj->buffer->size);
2684 uacpi_memcpy_zerout(&dst, obj->buffer->data, sizeof(dst), bytes);
2685 break;
2686 }
2689 obj->buffer->text, obj->buffer->size, UACPI_BASE_AUTO, &dst
2690 );
2691 break;
2692 default:
2693 dst = 0;
2694 break;
2695 }
2696
2697 return dst;
2698}
2699
2702)
2703{
2704 int repr_len;
2705 uacpi_char int_buf[21];
2706 uacpi_size final_size;
2707
2708 repr_len = uacpi_snprintf(
2709 int_buf, sizeof(int_buf),
2712 );
2713 if (uacpi_unlikely(repr_len < 0))
2715
2716 // 0x prefix + repr + \0
2717 final_size = (is_hex ? 2 : 0) + repr_len + 1;
2718
2719 str->data = uacpi_kernel_alloc(final_size);
2720 if (uacpi_unlikely(str->data == UACPI_NULL))
2722
2723 if (is_hex) {
2724 str->text[0] = '0';
2725 str->text[1] = 'x';
2726 }
2727 uacpi_memcpy(str->text + (is_hex ? 2 : 0), int_buf, repr_len + 1);
2728 str->size = final_size;
2729
2730 return UACPI_STATUS_OK;
2731}
2732
2735)
2736{
2737 int repr_len;
2738 uacpi_char int_buf[5];
2739 uacpi_size i, final_size;
2741
2742 if (is_hex) {
2743 final_size = 4 * buf->size;
2744 } else {
2745 final_size = 0;
2746
2747 for (i = 0; i < buf->size; ++i) {
2748 uacpi_u8 value = ((uacpi_u8*)buf->data)[i];
2749
2750 if (value < 10)
2751 final_size += 1;
2752 else if (value < 100)
2753 final_size += 2;
2754 else
2755 final_size += 3;
2756 }
2757 }
2758
2759 // Comma for every value but one
2760 final_size += buf->size - 1;
2761
2762 // Null terminator
2763 final_size += 1;
2764
2765 str->data = uacpi_kernel_alloc(final_size);
2766 if (uacpi_unlikely(str->data == UACPI_NULL))
2768
2769 cursor = str->data;
2770
2771 for (i = 0; i < buf->size; ++i) {
2772 repr_len = uacpi_snprintf(
2773 int_buf, sizeof(int_buf),
2774 is_hex ? "0x%02X" : "%d",
2775 ((uacpi_u8*)buf->data)[i]
2776 );
2777 if (uacpi_unlikely(repr_len < 0)) {
2778 uacpi_free(str->data, final_size);
2779 str->data = UACPI_NULL;
2781 }
2782
2783 uacpi_memcpy(cursor, int_buf, repr_len + 1);
2784 cursor += repr_len;
2785
2786 if (i != buf->size - 1)
2787 *cursor++ = ',';
2788 }
2789
2790 str->size = final_size;
2791 return UACPI_STATUS_OK;
2792}
2793
2796{
2797 buf->text = uacpi_kernel_alloc_zeroed(sizeof(uacpi_char));
2798 if (uacpi_unlikely(buf->text == UACPI_NULL))
2800
2801 if (is_string)
2802 buf->size = sizeof(uacpi_char);
2803
2804 return UACPI_STATUS_OK;
2805}
2806
2808{
2810}
2811
2813{
2814 /*
2815 * Allocate at least 1 byte just to be safe,
2816 * even for empty buffers. We still set the
2817 * size to 0 though.
2818 */
2820}
2821
2823{
2825 struct op_context *op_ctx = ctx->cur_op_ctx;
2826 uacpi_object *src, *dst;
2827
2828 src = item_array_at(&op_ctx->items, 0)->obj;
2829 dst = item_array_at(&op_ctx->items, 2)->obj;
2830
2831 switch (op_ctx->op->code) {
2832 case UACPI_AML_OP_ToIntegerOp:
2833 dst->integer = object_to_integer(src, sizeof_int());
2834 break;
2835
2836 case UACPI_AML_OP_ToHexStringOp:
2837 case UACPI_AML_OP_ToDecimalStringOp: {
2838 uacpi_bool is_hex = op_ctx->op->code == UACPI_AML_OP_ToHexStringOp;
2839
2840 if (src->type == UACPI_OBJECT_INTEGER) {
2841 ret = integer_to_string(src->integer, dst->buffer, is_hex);
2842 break;
2843 } else if (src->type == UACPI_OBJECT_BUFFER) {
2844 if (uacpi_unlikely(src->buffer->size == 0))
2845 return make_null_string(dst->buffer);
2846
2847 ret = buffer_to_string(src->buffer, dst->buffer, is_hex);
2848 break;
2849 }
2851 }
2852 case UACPI_AML_OP_ToBufferOp: {
2854 uacpi_u8 *dst_buf;
2855
2858 return ret;
2859
2860 if (uacpi_unlikely(buf.length == 0))
2861 return make_null_buffer(dst->buffer);
2862
2863 dst_buf = uacpi_kernel_alloc(buf.length);
2864 if (uacpi_unlikely(dst_buf == UACPI_NULL))
2866
2867 uacpi_memcpy(dst_buf, buf.bytes, buf.length);
2868 dst->buffer->data = dst_buf;
2869 dst->buffer->size = buf.length;
2870 break;
2871 }
2872
2873 default:
2875 }
2876
2877 return ret;
2878}
2879
2881{
2882 struct op_context *op_ctx = ctx->cur_op_ctx;
2883 uacpi_buffer *src_buf, *dst_buf;
2884 uacpi_size req_len, len;
2885
2886 src_buf = item_array_at(&op_ctx->items, 0)->obj->buffer;
2887 req_len = item_array_at(&op_ctx->items, 1)->obj->integer;
2888 dst_buf = item_array_at(&op_ctx->items, 3)->obj->buffer;
2889
2890 len = UACPI_MIN(req_len, src_buf->size);
2891 if (uacpi_unlikely(len == 0))
2892 return make_null_string(dst_buf);
2893
2894 len = uacpi_strnlen(src_buf->text, len);
2895
2896 dst_buf->text = uacpi_kernel_alloc(len + 1);
2897 if (uacpi_unlikely(dst_buf->text == UACPI_NULL))
2899
2900 uacpi_memcpy(dst_buf->text, src_buf->data, len);
2901 dst_buf->text[len] = '\0';
2902 dst_buf->size = len + 1;
2903
2904 return UACPI_STATUS_OK;
2905}
2906
2908{
2909 struct op_context *op_ctx = ctx->cur_op_ctx;
2910 uacpi_object *src, *dst;
2911 uacpi_data_view src_buf;
2912 uacpi_buffer *dst_buf;
2915
2916 src = item_array_at(&op_ctx->items, 0)->obj;
2917 if (uacpi_unlikely(src->type != UACPI_OBJECT_STRING &&
2918 src->type != UACPI_OBJECT_BUFFER)) {
2920 "invalid argument for Mid: %s, expected String/Buffer",
2922 );
2924 }
2925
2926 idx = item_array_at(&op_ctx->items, 1)->obj->integer;
2927 len = item_array_at(&op_ctx->items, 2)->obj->integer;
2928 dst = item_array_at(&op_ctx->items, 4)->obj;
2929 dst_buf = dst->buffer;
2930
2933
2934 if (uacpi_unlikely(src_buf.length == 0 || idx >= src_buf.length ||
2935 len == 0)) {
2936 if (src->type == UACPI_OBJECT_STRING) {
2937 dst->type = UACPI_OBJECT_STRING;
2938 return make_null_string(dst_buf);
2939 }
2940
2941 return make_null_buffer(dst_buf);
2942 }
2943
2944 // Guaranteed to be at least 1 here
2945 len = UACPI_MIN(len, src_buf.length - idx);
2946
2947 dst_buf->data = uacpi_kernel_alloc(len + is_string);
2948 if (uacpi_unlikely(dst_buf->data == UACPI_NULL))
2950
2951 uacpi_memcpy(dst_buf->data, (uacpi_u8*)src_buf.bytes + idx, len);
2952 dst_buf->size = len;
2953
2954 if (is_string) {
2955 dst_buf->text[dst_buf->size++] = '\0';
2956 dst->type = UACPI_OBJECT_STRING;
2957 }
2958
2959 return UACPI_STATUS_OK;
2960}
2961
2963{
2965 struct op_context *op_ctx = ctx->cur_op_ctx;
2966 uacpi_object *arg0, *arg1, *dst;
2967 uacpi_u8 *dst_buf;
2968 uacpi_size buf_size = 0;
2969
2970 arg0 = item_array_at(&op_ctx->items, 0)->obj;
2971 arg1 = item_array_at(&op_ctx->items, 1)->obj;
2972 dst = item_array_at(&op_ctx->items, 3)->obj;
2973
2974 switch (arg0->type) {
2975 case UACPI_OBJECT_INTEGER: {
2976 uacpi_u64 arg1_as_int;
2977 uacpi_size int_size;
2978
2979 int_size = sizeof_int();
2980 buf_size = int_size * 2;
2981
2982 dst_buf = uacpi_kernel_alloc(buf_size);
2983 if (uacpi_unlikely(dst_buf == UACPI_NULL))
2985
2986 arg1_as_int = object_to_integer(arg1, int_size);
2987
2988 uacpi_memcpy(dst_buf, &arg0->integer, int_size);
2989 uacpi_memcpy(dst_buf+ int_size, &arg1_as_int, int_size);
2990 break;
2991 }
2992 case UACPI_OBJECT_BUFFER: {
2993 uacpi_buffer *arg0_buf = arg0->buffer;
2994 uacpi_data_view arg1_buf = { 0 };
2995
2996 get_object_storage(arg1, &arg1_buf, UACPI_TRUE);
2997 buf_size = arg0_buf->size + arg1_buf.length;
2998
2999 dst_buf = uacpi_kernel_alloc(buf_size);
3000 if (uacpi_unlikely(dst_buf == UACPI_NULL))
3002
3003 uacpi_memcpy(dst_buf, arg0_buf->data, arg0_buf->size);
3004 uacpi_memcpy(dst_buf + arg0_buf->size, arg1_buf.bytes, arg1_buf.length);
3005 break;
3006 }
3007 case UACPI_OBJECT_STRING: {
3008 uacpi_char int_buf[17];
3009 void *arg1_ptr;
3010 uacpi_size arg0_size, arg1_size;
3011 uacpi_buffer *arg0_buf = arg0->buffer;
3012
3013 switch (arg1->type) {
3014 case UACPI_OBJECT_INTEGER: {
3015 int size;
3016 size = uacpi_snprintf(int_buf, sizeof(int_buf), "%"UACPI_PRIx64,
3017 UACPI_FMT64(arg1->integer));
3018 if (size < 0)
3020
3021 arg1_ptr = int_buf;
3022 arg1_size = size + 1;
3023 break;
3024 }
3026 arg1_ptr = arg1->buffer->data;
3027 arg1_size = arg1->buffer->size;
3028 break;
3029 case UACPI_OBJECT_BUFFER: {
3030 uacpi_buffer tmp_buf;
3031
3032 ret = buffer_to_string(arg1->buffer, &tmp_buf, UACPI_TRUE);
3034 return ret;
3035
3036 arg1_ptr = tmp_buf.data;
3037 arg1_size = tmp_buf.size;
3038 break;
3039 }
3040 default:
3042 }
3043
3044 arg0_size = arg0_buf->size ? arg0_buf->size - 1 : arg0_buf->size;
3045 buf_size = arg0_size + arg1_size;
3046
3047 dst_buf = uacpi_kernel_alloc(buf_size);
3048 if (uacpi_unlikely(dst_buf == UACPI_NULL)) {
3050 goto cleanup;
3051 }
3052
3053 uacpi_memcpy(dst_buf, arg0_buf->data, arg0_size);
3054 uacpi_memcpy(dst_buf + arg0_size, arg1_ptr, arg1_size);
3055 dst->type = UACPI_OBJECT_STRING;
3056
3057 cleanup:
3058 if (arg1->type == UACPI_OBJECT_BUFFER)
3059 uacpi_free(arg1_ptr, arg1_size);
3060 break;
3061 }
3062 default:
3064 }
3065
3067 dst->buffer->data = dst_buf;
3068 dst->buffer->size = buf_size;
3069 }
3070 return ret;
3071}
3072
3074{
3076 struct op_context *op_ctx = ctx->cur_op_ctx;
3078 uacpi_object *arg0, *arg1, *dst;
3079 uacpi_u8 *dst_buf;
3080 uacpi_size dst_size, arg0_size, arg1_size;
3081
3082 arg0 = item_array_at(&op_ctx->items, 0)->obj;
3083 arg1 = item_array_at(&op_ctx->items, 1)->obj;
3084 dst = item_array_at(&op_ctx->items, 3)->obj;
3085
3089 return ret;
3090
3091 uacpi_buffer_to_view(arg1->buffer, &buffer);
3094 return ret;
3095
3096 dst_size = arg0_size + arg1_size + sizeof(struct acpi_resource_end_tag);
3097
3098 dst_buf = uacpi_kernel_alloc(dst_size);
3099 if (uacpi_unlikely(dst_buf == UACPI_NULL))
3101
3102 dst->buffer->data = dst_buf;
3103 dst->buffer->size = dst_size;
3104
3105 uacpi_memcpy(dst_buf, arg0->buffer->data, arg0_size);
3106 uacpi_memcpy(dst_buf + arg0_size, arg1->buffer->data, arg1_size);
3107
3108 /*
3109 * Small item (0), End Tag (0x0F), length 1
3110 * Leave the checksum as 0
3111 */
3112 dst_buf[dst_size - 2] =
3114 (sizeof(struct acpi_resource_end_tag) - 1);
3115 dst_buf[dst_size - 1] = 0;
3116
3117 return UACPI_STATUS_OK;
3118}
3119
3121{
3122 struct op_context *op_ctx = ctx->cur_op_ctx;
3123 uacpi_object *src, *dst;
3124
3125 src = item_array_at(&op_ctx->items, 0)->obj;
3126 dst = item_array_at(&op_ctx->items, 1)->obj;
3127
3130
3131 switch (src->type) {
3133 case UACPI_OBJECT_BUFFER: {
3136
3137 dst->integer = buf.length;
3138 break;
3139 }
3140
3142 dst->integer = src->package->count;
3143 break;
3144
3145 default:
3147 "invalid argument for Sizeof: %s, "
3148 "expected String/Buffer/Package",
3150 );
3152 }
3153
3154 return UACPI_STATUS_OK;
3155}
3156
3158{
3159 struct op_context *op_ctx = ctx->cur_op_ctx;
3160 uacpi_object *src, *dst;
3161
3162 src = item_array_at(&op_ctx->items, 0)->obj;
3163 dst = item_array_at(&op_ctx->items, 1)->obj;
3164
3167
3168 dst->integer = src->type;
3169 if (dst->integer == UACPI_OBJECT_BUFFER_INDEX)
3170 dst->integer = UACPI_OBJECT_BUFFER_FIELD;
3171
3172 return UACPI_STATUS_OK;
3173}
3174
3176{
3177 struct op_context *op_ctx = ctx->cur_op_ctx;
3179
3180 dst = item_array_at(&op_ctx->items, 0)->obj;
3182
3183 return UACPI_STATUS_OK;
3184}
3185
3187{
3188 struct op_context *op_ctx = ctx->cur_op_ctx;
3190
3191 time = item_array_at(&op_ctx->items, 0)->obj->integer;
3192
3193 if (op_ctx->op->code == UACPI_AML_OP_SleepOp) {
3194 /*
3195 * ACPICA doesn't allow sleeps longer than 2 seconds,
3196 * so we shouldn't either.
3197 */
3198 if (time > 2000)
3199 time = 2000;
3200
3204 } else {
3205 // Spec says this must evaluate to a ByteData
3206 if (time > 0xFF)
3207 time = 0xFF;
3209 }
3210
3211 return UACPI_STATUS_OK;
3212}
3213
3215{
3216 struct op_context *op_ctx = ctx->cur_op_ctx;
3217 uacpi_u64 src, dst = 0;
3218 uacpi_size i;
3219 uacpi_object *dst_obj;
3220
3221 src = item_array_at(&op_ctx->items, 0)->obj->integer;
3222 dst_obj = item_array_at(&op_ctx->items, 2)->obj;
3223 i = 64;
3224
3225 /*
3226 * NOTE: ACPICA just errors out for invalid BCD, but NT allows it just fine.
3227 * FromBCD matches NT behavior 1:1 even for invalid BCD, but ToBCD
3228 * produces different results when the input is too large.
3229 */
3230 if (op_ctx->op->code == UACPI_AML_OP_FromBCDOp) {
3231 do {
3232 i -= 4;
3233 dst *= 10;
3234 dst += (src >> i) & 0xF;
3235 } while (i);
3236 } else {
3237 while (src != 0) {
3238 dst >>= 4;
3239 i -= 4;
3240 dst |= (src % 10) << 60;
3241 src /= 10;
3242 }
3243
3244 dst >>= (i % 64);
3245 }
3246
3247 dst_obj->integer = dst;
3248 return UACPI_STATUS_OK;
3249}
3250
3252{
3254
3255 /*
3256 * Technically this doesn't exist in the wild, from the dumps that I have
3257 * the only user of the Unload opcode is the Surface Pro 3, which triggers
3258 * an unload of some I2C-related table as a response to some event.
3259 *
3260 * This op has been long deprecated by the specification exactly because
3261 * it hasn't really been used by anyone and the fact that it introduces
3262 * an enormous layer of complexity, which no driver is really prepared to
3263 * deal with (aka namespace nodes disappearing under its feet).
3264 *
3265 * Just pretend we have actually unloaded whatever the AML asked for, if it
3266 * ever tries to re-load this table that will just skip opcodes that create
3267 * already existing objects, which should be good enough and mostly
3268 * transparent to the AML.
3269 */
3270 uacpi_warn("refusing to unload a table from AML");
3271 return UACPI_STATUS_OK;
3272}
3273
3275{
3276 struct op_context *op_ctx = ctx->cur_op_ctx;
3277 uacpi_object *src, *dst;
3278
3279 src = item_array_at(&op_ctx->items, 0)->obj;
3280 dst = item_array_at(&op_ctx->items, 1)->obj;
3281
3282 dst->type = UACPI_OBJECT_INTEGER;
3283 dst->integer = src->integer ? 0 : ones();
3284
3285 return UACPI_STATUS_OK;
3286}
3287
3289{
3291
3292 if (lhs->type == UACPI_OBJECT_STRING || lhs->type == UACPI_OBJECT_BUFFER) {
3293 res = lhs->buffer->size == rhs->buffer->size;
3294
3295 if (res && lhs->buffer->size) {
3296 res = uacpi_memcmp(
3297 lhs->buffer->data,
3298 rhs->buffer->data,
3299 lhs->buffer->size
3300 ) == 0;
3301 }
3302 } else if (lhs->type == UACPI_OBJECT_INTEGER) {
3303 res = lhs->integer == rhs->integer;
3304 }
3305
3306 return res;
3307}
3308
3311)
3312{
3313 if (lhs->type == UACPI_OBJECT_STRING || lhs->type == UACPI_OBJECT_BUFFER) {
3314 int res;
3315 uacpi_buffer *lhs_buf, *rhs_buf;
3316
3317 lhs_buf = lhs->buffer;
3318 rhs_buf = rhs->buffer;
3319
3320 res = uacpi_memcmp(lhs_buf->data, rhs_buf->data,
3321 UACPI_MIN(lhs_buf->size, rhs_buf->size));
3322 if (res == 0) {
3323 if (lhs_buf->size < rhs_buf->size)
3324 res = -1;
3325 else if (lhs_buf->size > rhs_buf->size)
3326 res = 1;
3327 }
3328
3329 if (op == UACPI_AML_OP_LLessOp)
3330 return res < 0;
3331
3332 return res > 0;
3333 }
3334
3335 if (op == UACPI_AML_OP_LLessOp)
3336 return lhs->integer < rhs->integer;
3337
3338 return lhs->integer > rhs->integer;
3339}
3340
3342{
3343 struct op_context *op_ctx = ctx->cur_op_ctx;
3344 uacpi_aml_op op = op_ctx->op->code;
3345 uacpi_object *lhs, *rhs, *dst;
3347
3348 lhs = item_array_at(&op_ctx->items, 0)->obj;
3349 rhs = item_array_at(&op_ctx->items, 1)->obj;
3350 dst = item_array_at(&op_ctx->items, 2)->obj;
3351
3352 switch (op) {
3353 case UACPI_AML_OP_LEqualOp:
3354 case UACPI_AML_OP_LLessOp:
3355 case UACPI_AML_OP_LGreaterOp:
3356 // TODO: typecheck at parse time
3357 if (lhs->type != rhs->type) {
3359 "don't know how to do a logical comparison of '%s' and '%s'",
3362 );
3364 }
3365
3366 if (op == UACPI_AML_OP_LEqualOp)
3367 res = handle_logical_equality(lhs, rhs);
3368 else
3370 break;
3371 default: {
3372 uacpi_u64 lhs_int, rhs_int;
3373
3374 // NT only looks at the first 4 bytes of a buffer
3375 lhs_int = object_to_integer(lhs, 4);
3376 rhs_int = object_to_integer(rhs, 4);
3377
3378 if (op == UACPI_AML_OP_LandOp)
3379 res = lhs_int && rhs_int;
3380 else
3381 res = lhs_int || rhs_int;
3382 break;
3383 }
3384 }
3385
3386 dst->integer = res ? ones() : 0;
3387 return UACPI_STATUS_OK;
3388}
3389
3391 MTR = 0,
3392 MEQ = 1,
3393 MLE = 2,
3394 MLT = 3,
3395 MGE = 4,
3396 MGT = 5,
3397};
3398
3400{
3401 switch (op) {
3402 case MTR:
3403 return UACPI_TRUE;
3404 case MEQ:
3405 return lhs == rhs;
3406 case MLE:
3407 return lhs <= rhs;
3408 case MLT:
3409 return lhs < rhs;
3410 case MGE:
3411 return lhs >= rhs;
3412 case MGT:
3413 return lhs > rhs;
3414 default:
3415 return UACPI_FALSE;
3416 }
3417}
3418
3420{
3421 struct op_context *op_ctx = ctx->cur_op_ctx;
3422 uacpi_package *pkg;
3423 uacpi_u64 operand0, operand1, start_idx, i;
3424 enum match_op mop0, mop1;
3426
3427 pkg = item_array_at(&op_ctx->items, 0)->obj->package;
3428 mop0 = item_array_at(&op_ctx->items, 1)->immediate;
3429 operand0 = item_array_at(&op_ctx->items, 2)->obj->integer;
3430 mop1 = item_array_at(&op_ctx->items, 3)->immediate;
3431 operand1 = item_array_at(&op_ctx->items, 4)->obj->integer;
3432 start_idx = item_array_at(&op_ctx->items, 5)->obj->integer;
3433 dst = item_array_at(&op_ctx->items, 6)->obj;
3434
3435 for (i = start_idx; i < pkg->count; ++i) {
3436 uacpi_object *obj = pkg->objects[i];
3437
3438 if (obj->type != UACPI_OBJECT_INTEGER)
3439 continue;
3440
3441 if (match_one(mop0, obj->integer, operand0) &&
3442 match_one(mop1, obj->integer, operand1))
3443 break;
3444 }
3445
3446 if (i < pkg->count)
3447 dst->integer = i;
3448 else
3449 dst->integer = ones();
3450
3451 return UACPI_STATUS_OK;
3452}
3453
3454/*
3455 * PkgLength :=
3456 * PkgLeadByte |
3457 * <pkgleadbyte bytedata> |
3458 * <pkgleadbyte bytedata bytedata> | <pkgleadbyte bytedata bytedata bytedata>
3459 * PkgLeadByte :=
3460 * <bit 7-6: bytedata count that follows (0-3)>
3461 * <bit 5-4: only used if pkglength < 63>
3462 * <bit 3-0: least significant package length nybble>
3463 */
3465 struct package_length *out_pkg)
3466{
3468 uacpi_u8 *data, marker_length;
3469
3470 out_pkg->begin = frame->code_offset;
3471 marker_length = 1;
3472
3474 if (uacpi_unlikely(left < 1))
3476
3477 data = call_frame_cursor(frame);
3478 marker_length += *data >> 6;
3479
3480 if (uacpi_unlikely(left < marker_length))
3482
3483 switch (marker_length) {
3484 case 1:
3485 size = *data & 0x3F;
3486 break;
3487 case 2:
3488 case 3:
3489 case 4: {
3490 uacpi_u32 temp_byte = 0;
3491
3492 size = *data & 0xF;
3493 uacpi_memcpy(&temp_byte, data + 1, marker_length - 1);
3494
3495 // marker_length - 1 is at most 3, so this shift is safe
3496 size |= temp_byte << 4;
3497 break;
3498 }
3499 }
3500
3501 frame->code_offset += marker_length;
3502
3503 out_pkg->end = out_pkg->begin + size;
3504 if (uacpi_unlikely(out_pkg->end < out_pkg->begin)) {
3506 "PkgLength overflow: start=%u, size=%u", out_pkg->begin, size
3507 );
3509 }
3510
3511 return UACPI_STATUS_OK;
3512}
3513
3514/*
3515 * ByteData
3516 * // bit 0-2: ArgCount (0-7)
3517 * // bit 3: SerializeFlag
3518 * // 0 NotSerialized
3519 * // 1 Serialized
3520 * // bit 4-7: SyncLevel (0x00-0x0f)
3521 */
3523{
3524 method->args = flags_byte & 0x7;
3525 method->is_serialized = (flags_byte >> 3) & 1;
3526 method->sync_level = flags_byte >> 4;
3527}
3528
3530{
3531 struct op_context *op_ctx = ctx->cur_op_ctx;
3532 struct uacpi_control_method *this_method, *method;
3533 struct package_length *pkg;
3534 struct uacpi_namespace_node *node;
3535 struct uacpi_object *dst;
3536 uacpi_u32 method_begin_offset, method_size;
3537
3538 this_method = ctx->cur_frame->method;
3539 pkg = &item_array_at(&op_ctx->items, 0)->pkg;
3540 node = item_array_at(&op_ctx->items, 1)->node;
3541 method_begin_offset = item_array_at(&op_ctx->items, 3)->immediate;
3542
3543 if (uacpi_unlikely(pkg->end < pkg->begin ||
3544 pkg->end < method_begin_offset ||
3545 pkg->end > this_method->size)) {
3547 "invalid method %.4s bounds [%u..%u] (parent size is %u)",
3548 node->name.text, method_begin_offset, pkg->end, this_method->size
3549 );
3551 }
3552
3553 dst = item_array_at(&op_ctx->items, 4)->obj;
3554
3555 method = dst->method;
3556 method_size = pkg->end - method_begin_offset;
3557
3558 if (method_size) {
3559 method->code = uacpi_kernel_alloc(method_size);
3560 if (uacpi_unlikely(method->code == UACPI_NULL))
3562
3564 method->code,
3565 ctx->cur_frame->method->code + method_begin_offset,
3566 method_size
3567 );
3568 method->size = method_size;
3569 method->owns_code = 1;
3570 }
3571
3572 init_method_flags(method, item_array_at(&op_ctx->items, 2)->immediate);
3573
3575 dst);
3576 if (uacpi_unlikely(node->object == UACPI_NULL))
3578
3579 return UACPI_STATUS_OK;
3580}
3581
3583{
3584 struct op_context *op_ctx = ctx->cur_op_ctx;
3587
3588 node = item_array_at(&op_ctx->items, 0)->node;
3589
3590 if (op_ctx->op->code == UACPI_AML_OP_MutexOp) {
3591 dst = item_array_at(&op_ctx->items, 2)->obj;
3592
3593 // bits 0-3: SyncLevel (0x00-0x0f), bits 4-7: Reserved (must be 0)
3594 dst->mutex->sync_level = item_array_at(&op_ctx->items, 1)->immediate;
3595 dst->mutex->sync_level &= 0xF;
3596 } else {
3597 dst = item_array_at(&op_ctx->items, 1)->obj;
3598 }
3599
3602 dst
3603 );
3604 if (uacpi_unlikely(node->object == UACPI_NULL))
3606
3607 return UACPI_STATUS_OK;
3608}
3609
3611{
3612 struct op_context *op_ctx = ctx->cur_op_ctx;
3614
3616 item_array_at(&op_ctx->items, 0)->obj
3617 );
3618 if (uacpi_unlikely(obj->type != UACPI_OBJECT_EVENT)) {
3620 "%s: invalid argument '%s', expected an Event object",
3621 op_ctx->op->name, uacpi_object_type_to_string(obj->type)
3622 );
3624 }
3625
3626 switch (op_ctx->op->code)
3627 {
3628 case UACPI_AML_OP_SignalOp:
3629 uacpi_kernel_signal_event(obj->event->handle);
3630 break;
3631 case UACPI_AML_OP_ResetOp:
3632 uacpi_kernel_reset_event(obj->event->handle);
3633 break;
3634 case UACPI_AML_OP_WaitOp: {
3637
3638 timeout = item_array_at(&op_ctx->items, 1)->obj->integer;
3639 if (timeout > 0xFFFF)
3640 timeout = 0xFFFF;
3641
3643 ret = uacpi_kernel_wait_for_event(obj->event->handle, timeout);
3645
3646 /*
3647 * The return value here is inverted, we return 0 for success and Ones
3648 * for timeout and everything else.
3649 */
3650 if (ret)
3651 item_array_at(&op_ctx->items, 2)->obj->integer = 0;
3652 break;
3653 }
3654 default:
3656 }
3657
3658 return UACPI_STATUS_OK;
3659}
3660
3662{
3663 struct op_context *op_ctx = ctx->cur_op_ctx;
3665
3667 item_array_at(&op_ctx->items, 0)->obj
3668 );
3669 if (uacpi_unlikely(obj->type != UACPI_OBJECT_MUTEX)) {
3671 "%s: invalid argument '%s', expected a Mutex object",
3672 op_ctx->op->name, uacpi_object_type_to_string(obj->type)
3673 );
3675 }
3676
3677 switch (op_ctx->op->code)
3678 {
3679 case UACPI_AML_OP_AcquireOp: {
3681 uacpi_u64 *return_value;
3683
3684 return_value = &item_array_at(&op_ctx->items, 2)->obj->integer;
3685
3686 if (uacpi_unlikely(ctx->sync_level > obj->mutex->sync_level)) {
3687 uacpi_warn(
3688 "ignoring attempt to acquire mutex @%p with a lower sync level "
3689 "(%d < %d)", obj->mutex, obj->mutex->sync_level,
3690 ctx->sync_level
3691 );
3692 break;
3693 }
3694
3695 timeout = item_array_at(&op_ctx->items, 1)->immediate;
3696 if (timeout > 0xFFFF)
3697 timeout = 0xFFFF;
3698
3702 *return_value = 0;
3703 break;
3704 }
3705
3708 break;
3709
3710 ret = held_mutexes_array_push(&ctx->held_mutexes, obj->mutex);
3713 return ret;
3714 }
3715
3716 ctx->sync_level = obj->mutex->sync_level;
3717 *return_value = 0;
3718 break;
3719 }
3720
3721 case UACPI_AML_OP_ReleaseOp: {
3723
3725 uacpi_warn(
3726 "attempted to release not-previously-acquired mutex object "
3727 "@%p (%p)", obj->mutex, obj->mutex->handle
3728 );
3729 break;
3730 }
3731
3733 &ctx->held_mutexes, obj->mutex,
3735 );
3737 uacpi_mutex **last_mutex;
3738
3739 last_mutex = held_mutexes_array_last(&ctx->held_mutexes);
3740 if (last_mutex == UACPI_NULL) {
3741 ctx->sync_level = 0;
3742 break;
3743 }
3744
3745 ctx->sync_level = (*last_mutex)->sync_level;
3746 }
3747 break;
3748 }
3749
3750 default:
3752 }
3753
3754 return UACPI_STATUS_OK;
3755}
3756
3758{
3760 struct op_context *op_ctx = ctx->cur_op_ctx;
3761 struct uacpi_namespace_node *node;
3763
3764 node = item_array_at(&op_ctx->items, 0)->node;
3765 value = item_array_at(&op_ctx->items, 1)->obj->integer;
3766
3769 return ret;
3770
3772 const uacpi_char *path;
3773
3775 uacpi_warn(
3776 "ignoring firmware Notify(%s, 0x%"UACPI_PRIX64") request, "
3777 "no listeners", path, UACPI_FMT64(value)
3778 );
3780
3781 return UACPI_STATUS_OK;
3782 }
3783
3785 uacpi_error("Notify() called on an invalid object %.4s",
3786 node->name.text);
3788 }
3789
3790 return ret;
3791}
3792
3794{
3795 struct op_context *op_ctx = ctx->cur_op_ctx;
3796 uacpi_firmware_request req = { 0 };
3797
3798 switch (op_ctx->op->code) {
3799 case UACPI_AML_OP_BreakPointOp:
3801 req.breakpoint.ctx = ctx;
3802 break;
3803 case UACPI_AML_OP_FatalOp:
3805 req.fatal.type = item_array_at(&op_ctx->items, 0)->immediate;
3806 req.fatal.code = item_array_at(&op_ctx->items, 1)->immediate;
3807 req.fatal.arg = item_array_at(&op_ctx->items, 2)->obj->integer;
3808 break;
3809 default:
3811 }
3812
3816
3817 return UACPI_STATUS_OK;
3818}
3819
3821{
3822 struct op_context *op_ctx = ctx->cur_op_ctx;
3823 struct uacpi_namespace_node *node;
3825
3826 node = item_array_at(&op_ctx->items, 0)->node;
3827 src = item_array_at(&op_ctx->items, 1)->obj;
3828
3830 src);
3831 if (uacpi_unlikely(node->object == UACPI_NULL))
3833
3834 return UACPI_STATUS_OK;
3835}
3836
3839)
3840{
3841 if (field->bit_length > (g_uacpi_rt_ctx.is_rev1 ? 32u : 64u) ||
3842 field->force_buffer)
3843 return UACPI_OBJECT_BUFFER;
3844
3845 return UACPI_OBJECT_INTEGER;
3846}
3847
3850)
3851{
3852 if (obj->type == UACPI_OBJECT_BUFFER_FIELD) {
3853 *out_type = buffer_field_get_read_type(&obj->buffer_field);
3854 return UACPI_STATUS_OK;
3855 }
3856
3857 return uacpi_field_unit_get_read_type(obj->field_unit, out_type);
3858}
3859
3862)
3863{
3864 uacpi_size bit_length;
3865
3866 if (obj->type == UACPI_OBJECT_BUFFER_FIELD) {
3867 bit_length = obj->buffer_field.bit_length;
3868 } else {
3870
3871 ret = uacpi_field_unit_get_bit_length(obj->field_unit, &bit_length);
3873 return ret;
3874 }
3875
3877 return UACPI_STATUS_OK;
3878}
3879
3881{
3882 uacpi_object *src, *unwound_src, *dst;
3883 uacpi_object_type read_type;
3884 bool is_field;
3886
3887 struct op_context *op_ctx = ctx->cur_op_ctx;
3888
3889 src = item_array_at(&op_ctx->items, 0)->obj;
3890 dst = item_array_at(&op_ctx->items, 1)->obj;
3891
3892 if (src->type == UACPI_OBJECT_BUFFER_INDEX) {
3893 uacpi_buffer_index *buf_idx = &src->buffer_index;
3894
3895 dst->type = UACPI_OBJECT_INTEGER;
3897 &dst->integer, buffer_index_cursor(buf_idx),
3898 sizeof(dst->integer), 1
3899 );
3900 return UACPI_STATUS_OK;
3901 }
3902
3903 /*
3904 * Explicit dereferencing [DerefOf] behavior:
3905 * Simply grabs the bottom-most object that is not a reference.
3906 * This mimics the behavior of NT Acpi.sys: any DerfOf fetches
3907 * the bottom-most reference. Note that this is different from
3908 * ACPICA where DerefOf dereferences one level.
3909 */
3910 unwound_src = reference_unwind(src)->inner_object;
3911 is_field = uacpi_object_is_one_of(
3912 unwound_src,
3914 );
3915
3916 /*
3917 * If the object is a field, find out how to read it and transform this
3918 * DerefOf into a field read op. Otherwise, simply assign this object to the
3919 * destination.
3920 */
3921 if (is_field) {
3922 uacpi_aml_op new_op;
3923
3924 ret = field_get_read_type(unwound_src, &read_type);
3927 "unable to perform a read from field %p: "
3928 "parent opregion gone", unwound_src
3929 );
3930 return ret;
3931 }
3932
3933 switch (read_type) {
3935 new_op = UACPI_AML_OP_InternalOpReadFieldAsBuffer;
3936 break;
3938 new_op = UACPI_AML_OP_InternalOpReadFieldAsInteger;
3939 break;
3940 default:
3942 }
3943
3944 op_ctx->op = uacpi_get_op_spec(new_op);
3945 op_ctx->pc = 0;
3946
3947 uacpi_object_ref(unwound_src);
3948 item_array_at(&op_ctx->items, 0)->obj = unwound_src;
3950
3951 /*
3952 * A proper destination object will be allocated by the op we have just
3953 * switched to. This one is not needed anymore.
3954 */
3956 item_array_pop(&op_ctx->items);
3957
3958 return UACPI_STATUS_OK;
3959 }
3960
3961 return uacpi_object_assign(
3962 dst, unwound_src,
3964 );
3965}
3966
3968{
3970 struct op_context *op_ctx = ctx->cur_op_ctx;
3971 struct item *src_item;
3972 uacpi_object *src_obj, *dst_obj;
3973 uacpi_size dst_size;
3974 void *dst = UACPI_NULL;
3975 uacpi_data_view wtr_response = { 0 };
3976
3977 src_item = item_array_at(&op_ctx->items, 0);
3978
3979 /*
3980 * Source may be a namespace node or an object depending on how we ended up
3981 * here, check explicitly.
3982 */
3983 if (src_item->type == ITEM_NAMESPACE_NODE) {
3985
3986 node = item_array_at(&op_ctx->items, 0)->node;
3988 } else {
3989 src_obj = src_item->obj;
3990 }
3991
3992 dst_obj = item_array_at(&op_ctx->items, 1)->obj;
3993
3994 if (op_ctx->op->code == UACPI_AML_OP_InternalOpReadFieldAsBuffer) {
3996
3997 ret = field_byte_size(src_obj, &dst_size);
3999 return ret;
4000
4001 if (dst_size != 0) {
4002 buf = dst_obj->buffer;
4003
4004 dst = uacpi_kernel_alloc_zeroed(dst_size);
4005 if (dst == UACPI_NULL)
4007
4008 buf->data = dst;
4009 buf->size = dst_size;
4010 }
4011 } else {
4012 dst = &dst_obj->integer;
4013 dst_size = sizeof(uacpi_u64);
4014 }
4015
4016 if (src_obj->type == UACPI_OBJECT_BUFFER_FIELD) {
4018 return UACPI_STATUS_OK;
4019 }
4020
4022 src_obj->field_unit, dst, dst_size, &wtr_response
4023 );
4025 return ret;
4026
4027 if (wtr_response.data != UACPI_NULL) {
4029
4030 buf = dst_obj->buffer;
4031 buf->data = wtr_response.data;
4032 buf->size = wtr_response.length;
4033 }
4034
4035 return ret;
4036}
4037
4039{
4040 struct op_context *op_ctx = ctx->cur_op_ctx;
4041 struct uacpi_namespace_node *node;
4042 uacpi_buffer *src_buf;
4043 uacpi_object *field_obj;
4045
4046 /*
4047 * Layout of items here:
4048 * [0] -> Type checked source buffer object
4049 * [1] -> Byte/bit index integer object
4050 * [2] ( if CreateField) -> bit length integer object
4051 * [3] (2 if not CreateField) -> the new namespace node
4052 * [4] (3 if not CreateField) -> the buffer field object we're creating here
4053 */
4054 src_buf = item_array_at(&op_ctx->items, 0)->obj->buffer;
4055
4056 if (op_ctx->op->code == UACPI_AML_OP_CreateFieldOp) {
4057 uacpi_object *idx_obj, *len_obj;
4058
4059 idx_obj = item_array_at(&op_ctx->items, 1)->obj;
4060 len_obj = item_array_at(&op_ctx->items, 2)->obj;
4061 node = item_array_at(&op_ctx->items, 3)->node;
4062 field_obj = item_array_at(&op_ctx->items, 4)->obj;
4063 field = &field_obj->buffer_field;
4064
4065 field->bit_index = idx_obj->integer;
4066
4067 if (uacpi_unlikely(!len_obj->integer ||
4068 len_obj->integer > 0xFFFFFFFF)) {
4069 uacpi_error("invalid bit field length (%u)", field->bit_length);
4071 }
4072
4073 field->bit_length = len_obj->integer;
4074 field->force_buffer = UACPI_TRUE;
4075 } else {
4076 uacpi_object *idx_obj;
4077
4078 idx_obj = item_array_at(&op_ctx->items, 1)->obj;
4079 node = item_array_at(&op_ctx->items, 2)->node;
4080 field_obj = item_array_at(&op_ctx->items, 3)->obj;
4081 field = &field_obj->buffer_field;
4082
4083 field->bit_index = idx_obj->integer;
4084 switch (op_ctx->op->code) {
4085 case UACPI_AML_OP_CreateBitFieldOp:
4086 field->bit_length = 1;
4087 break;
4088 case UACPI_AML_OP_CreateByteFieldOp:
4089 field->bit_length = 8;
4090 break;
4091 case UACPI_AML_OP_CreateWordFieldOp:
4092 field->bit_length = 16;
4093 break;
4094 case UACPI_AML_OP_CreateDWordFieldOp:
4095 field->bit_length = 32;
4096 break;
4097 case UACPI_AML_OP_CreateQWordFieldOp:
4098 field->bit_length = 64;
4099 break;
4100 default:
4102 }
4103
4104 if (op_ctx->op->code != UACPI_AML_OP_CreateBitFieldOp)
4105 field->bit_index *= 8;
4106 }
4107
4108 if (uacpi_unlikely((field->bit_index + field->bit_length) >
4109 src_buf->size * 8)) {
4111 "invalid buffer field: bits [%zu..%zu], buffer size is %zu bytes",
4112 field->bit_index, field->bit_index + field->bit_length,
4113 src_buf->size
4114 );
4116 }
4117
4118 field->backing = src_buf;
4119 uacpi_shareable_ref(field->backing);
4121 field_obj);
4122 if (uacpi_unlikely(node->object == UACPI_NULL))
4124
4125 return UACPI_STATUS_OK;
4126}
4127
4129{
4130 struct call_frame *frame = ctx->cur_frame;
4131 struct op_context *op_ctx = ctx->cur_op_ctx;
4132
4133 if (uacpi_unlikely(frame->last_while_idx_plus_one == 0)) {
4135 "attempting to %s outside of a While block",
4136 op_ctx->op->code == UACPI_AML_OP_BreakOp ? "Break" : "Continue"
4137 );
4139 }
4140
4141 for (;;) {
4142 if (code_block_array_size(&frame->code_blocks) >
4143 frame->last_while_idx_plus_one) {
4144 frame_reset_post_end_block(ctx, ctx->cur_block->type);
4145 continue;
4146 }
4147
4148 if (op_ctx->op->code == UACPI_AML_OP_BreakOp)
4149 frame->code_offset = ctx->cur_block->end;
4150 else
4151 frame->code_offset = ctx->cur_block->begin;
4152 frame_reset_post_end_block(ctx, ctx->cur_block->type);
4153 break;
4154 }
4155
4156 return UACPI_STATUS_OK;
4157}
4158
4160{
4163
4164 node = item_array_at(&op_ctx->items, 1)->node;
4165 obj = item_array_last(&op_ctx->items)->obj;
4166
4167 switch (op_ctx->op->code) {
4168 case UACPI_AML_OP_ProcessorOp: {
4169 uacpi_processor *proc = obj->processor;
4170 proc->id = item_array_at(&op_ctx->items, 2)->immediate;
4171 proc->block_address = item_array_at(&op_ctx->items, 3)->immediate;
4172 proc->block_length = item_array_at(&op_ctx->items, 4)->immediate;
4173 break;
4174 }
4175
4176 case UACPI_AML_OP_PowerResOp: {
4177 uacpi_power_resource *power_res = &obj->power_resource;
4178 power_res->system_level = item_array_at(&op_ctx->items, 2)->immediate;
4179 power_res->resource_order = item_array_at(&op_ctx->items, 3)->immediate;
4180 break;
4181 }
4182
4183 default:
4184 break;
4185 }
4186
4188 obj);
4189 if (uacpi_unlikely(node->object == UACPI_NULL))
4191
4192 return UACPI_STATUS_OK;
4193}
4194
4196{
4197 struct op_context *op_ctx = ctx->cur_op_ctx;
4198
4199 switch (op_ctx->op->code) {
4200 case UACPI_AML_OP_ProcessorOp:
4201 case UACPI_AML_OP_PowerResOp:
4202 case UACPI_AML_OP_ThermalZoneOp:
4203 case UACPI_AML_OP_DeviceOp: {
4205
4206 ret = create_named_scope(op_ctx);
4208 return ret;
4209
4211 }
4212 case UACPI_AML_OP_ScopeOp:
4213 case UACPI_AML_OP_IfOp:
4214 case UACPI_AML_OP_ElseOp:
4215 case UACPI_AML_OP_WhileOp: {
4216 break;
4217 }
4218 default:
4220 }
4221
4222 return begin_block_execution(ctx);
4223}
4224
4226{
4229
4230 ctx->cur_frame->code_offset = ctx->cur_frame->method->size;
4232
4234 return ret;
4235 if (dst == UACPI_NULL)
4236 return UACPI_STATUS_OK;
4237
4238 /*
4239 * Should be possible to move here if method returns a literal
4240 * like Return(Buffer { ... }), otherwise we have to copy just to
4241 * be safe.
4242 */
4243 return uacpi_object_assign(
4244 dst,
4245 item_array_at(&ctx->cur_op_ctx->items, 0)->obj,
4247 );
4248}
4249
4251{
4252 struct call_frame *frame = ctx->cur_frame;
4253
4254 if (frame == UACPI_NULL) {
4255 ctx->cur_op_ctx = UACPI_NULL;
4256 ctx->prev_op_ctx = UACPI_NULL;
4257 ctx->cur_block = UACPI_NULL;
4258 return;
4259 }
4260
4261 ctx->cur_op_ctx = op_context_array_last(&frame->pending_ops);
4262 ctx->prev_op_ctx = op_context_array_one_before_last(&frame->pending_ops);
4263 ctx->cur_block = code_block_array_last(&frame->code_blocks);
4264}
4265
4267{
4268 return ctx->cur_op_ctx && !ctx->cur_op_ctx->preempted;
4269}
4270
4275};
4276
4277static const uacpi_char *const op_trace_action_types[3] = {
4278 [OP_TRACE_ACTION_BEGIN] = "BEGIN",
4279 [OP_TRACE_ACTION_RESUME] = "RESUME",
4280 [OP_TRACE_ACTION_END] = "END",
4281};
4282
4283static inline void trace_op(
4284 const struct uacpi_op_spec *op, enum op_trace_action_type action
4285)
4286{
4288 "%s OP '%s' (0x%04X)",
4289 op_trace_action_types[action], op->name, op->code
4290 );
4291}
4292
4293static inline void trace_pop(uacpi_u8 pop)
4294{
4295 uacpi_debug(" pOP: %s (0x%02X)", uacpi_parse_op_to_string(pop), pop);
4296}
4297
4299 struct op_context *op_ctx)
4300{
4301 uacpi_size i;
4302
4303 /*
4304 * MethodCall items:
4305 * items[0] -> method namespace node
4306 * items[1] -> immediate that was used for parsing the arguments
4307 * items[2...nargs-1] -> method arguments
4308 * items[-1] -> return value object
4309 *
4310 * Here we only care about the arguments though.
4311 */
4312 for (i = 2; i < item_array_size(&op_ctx->items) - 1; i++) {
4313 uacpi_object *src, *dst;
4314
4315 src = item_array_at(&op_ctx->items, i)->obj;
4316
4320
4321 frame->args[i - 2] = dst;
4322 }
4323
4324 return UACPI_STATUS_OK;
4325}
4326
4328 uacpi_namespace_node *scope,
4330{
4331 struct code_block *block;
4332
4333 block = code_block_array_alloc(&frame->code_blocks);
4336
4337 block->type = CODE_BLOCK_SCOPE;
4338 block->node = scope;
4339 block->begin = 0;
4340 block->end = method->size;
4341 frame->method = method;
4342 frame->cur_scope = scope;
4343 return UACPI_STATUS_OK;
4344}
4345
4347 struct call_frame **out_frame)
4348{
4349 struct call_frame_array *call_stack = &ctx->call_stack;
4350 struct call_frame *prev_frame;
4351
4352 *out_frame = call_frame_array_calloc(call_stack);
4353 if (uacpi_unlikely(*out_frame == UACPI_NULL))
4355
4356 /*
4357 * Allocating a new frame might have reallocated the dynamic buffer so our
4358 * execution_context members might now be pointing to freed memory.
4359 * Refresh them here.
4360 */
4361 prev_frame = call_frame_array_one_before_last(call_stack);
4362 ctx->cur_frame = prev_frame;
4364
4365 return UACPI_STATUS_OK;
4366}
4367
4369{
4370 struct code_block *block = ctx->cur_block;
4371 struct call_frame *cur_frame = ctx->cur_frame;
4372
4373 if (!block)
4374 return UACPI_FALSE;
4375 if (cur_frame->code_offset != block->end)
4376 return UACPI_FALSE;
4377
4378 if (block->type == CODE_BLOCK_WHILE)
4379 cur_frame->code_offset = block->begin;
4380
4382 return UACPI_TRUE;
4383}
4384
4387)
4388{
4390
4391 switch (dst->type) {
4392 case UACPI_OBJECT_DEBUG:
4393 ret = debug_store(src);
4394 break;
4396 ret = store_to_reference(dst, src, wtr_response);
4397 break;
4398
4401 ret = object_assign_with_implicit_cast(dst, src, wtr_response);
4402 break;
4403
4405 // NULL target
4406 if (dst->integer == 0) {
4408 break;
4409 }
4411 default:
4412 uacpi_error("attempted to store to an invalid target: %s",
4415 }
4416
4417 return ret;
4418}
4419
4421{
4422 uacpi_object *src, *dst;
4423 struct op_context *op_ctx = ctx->cur_op_ctx;
4424
4425 src = item_array_at(&op_ctx->items, 0)->obj;
4426 dst = item_array_at(&op_ctx->items, 1)->obj;
4427
4428 if (op_ctx->op->code == UACPI_AML_OP_StoreOp) {
4430 uacpi_data_view wtr_response = { 0 };
4431
4432 ret = store_to_target(dst, src, &wtr_response);
4434 return ret;
4435
4436 /*
4437 * This was a write-then-read field access since we got a response
4438 * buffer back from this store. Now we have to return this buffer
4439 * as a prvalue from the StoreOp so that it can be used by AML to
4440 * retrieve the response.
4441 */
4442 if (wtr_response.data != UACPI_NULL) {
4443 uacpi_object *wtr_response_obj;
4444
4445 wtr_response_obj = uacpi_create_object(UACPI_OBJECT_BUFFER);
4446 if (uacpi_unlikely(wtr_response_obj == UACPI_NULL)) {
4447 uacpi_free(wtr_response.data, wtr_response.length);
4449 }
4450
4451 wtr_response_obj->buffer->data = wtr_response.data;
4452 wtr_response_obj->buffer->size = wtr_response.length;
4453
4455 item_array_at(&op_ctx->items, 0)->obj = wtr_response_obj;
4456 }
4457
4458 return ret;
4459 }
4460
4461 if (dst->type != UACPI_OBJECT_REFERENCE)
4463
4465}
4466
4468{
4469 uacpi_object *src, *dst;
4470 struct op_context *op_ctx = ctx->cur_op_ctx;
4471 uacpi_bool field_allowed = UACPI_FALSE;
4472 uacpi_object_type true_src_type;
4474
4475 src = item_array_at(&op_ctx->items, 0)->obj;
4476 dst = item_array_at(&op_ctx->items, 1)->obj;
4477
4478 if (src->type == UACPI_OBJECT_REFERENCE) {
4479 /*
4480 * Increment/Decrement are the only two operators that modify the value
4481 * in-place, thus we need very specific dereference rules here.
4482 *
4483 * Reading buffer fields & field units is only allowed if we were passed
4484 * a namestring directly as opposed to some nested reference chain
4485 * containing a field at the bottom.
4486 */
4487 if (src->flags == UACPI_REFERENCE_KIND_NAMED)
4488 field_allowed = src->inner_object->type != UACPI_OBJECT_REFERENCE;
4489
4491 } // else buffer index
4492
4493 true_src_type = src->type;
4494
4495 switch (true_src_type) {
4497 dst->integer = src->integer;
4498 break;
4501 if (uacpi_unlikely(!field_allowed))
4502 goto out_bad_type;
4503
4504 ret = field_get_read_type(src, &true_src_type);
4506 goto out_bad_type;
4507 if (true_src_type != UACPI_OBJECT_INTEGER)
4508 goto out_bad_type;
4509
4510 if (src->type == UACPI_OBJECT_FIELD_UNIT) {
4512 src->field_unit, &dst->integer, sizeof_int(),
4514 );
4516 return ret;
4517 } else {
4518 uacpi_read_buffer_field(&src->buffer_field, &dst->integer);
4519 }
4520 break;
4522 dst->integer = *buffer_index_cursor(&src->buffer_index);
4523 break;
4524 default:
4525 goto out_bad_type;
4526 }
4527
4528 if (op_ctx->op->code == UACPI_AML_OP_IncrementOp)
4529 dst->integer++;
4530 else
4531 dst->integer--;
4532
4533 return UACPI_STATUS_OK;
4534
4535out_bad_type:
4536 uacpi_error("Increment/Decrement: invalid object type '%s'",
4537 uacpi_object_type_to_string(true_src_type));
4539}
4540
4542 struct execution_context *ctx, struct call_frame *new_frame,
4544)
4545{
4547
4549
4550 if (!method->is_serialized)
4551 return ret;
4552
4553 if (uacpi_unlikely(ctx->sync_level > method->sync_level)) {
4555 "cannot invoke method @%p, sync level %d is too low "
4556 "(current is %d)",
4557 method, method->sync_level, ctx->sync_level
4558 );
4560 }
4561
4562 if (method->mutex == UACPI_NULL) {
4563 method->mutex = uacpi_create_mutex();
4564 if (uacpi_unlikely(method->mutex == UACPI_NULL))
4566 method->mutex->sync_level = method->sync_level;
4567 }
4568
4570 ret = uacpi_acquire_aml_mutex(method->mutex, 0xFFFF);
4572 return ret;
4573
4574 ret = held_mutexes_array_push(&ctx->held_mutexes, method->mutex);
4577 return ret;
4578 }
4579 }
4580
4581 new_frame->prev_sync_level = ctx->sync_level;
4582 ctx->sync_level = method->sync_level;
4583 return UACPI_STATUS_OK;
4584}
4585
4587{
4588 struct call_frame *frame = ctx->cur_frame;
4589 struct op_context *op_ctx;
4590
4591 op_ctx = op_context_array_calloc(&frame->pending_ops);
4592 if (op_ctx == UACPI_NULL)
4594
4595 op_ctx->op = ctx->cur_op;
4597 return UACPI_STATUS_OK;
4598}
4599
4600static uacpi_bool pop_item(struct op_context *op_ctx)
4601{
4602 struct item *item;
4603
4604 if (item_array_size(&op_ctx->items) == 0)
4605 return UACPI_FALSE;
4606
4607 item = item_array_last(&op_ctx->items);
4608
4609 if (item->type == ITEM_OBJECT)
4611
4614
4615 item_array_pop(&op_ctx->items);
4616 return UACPI_TRUE;
4617}
4618
4619static void pop_op(struct execution_context *ctx)
4620{
4621 struct call_frame *frame = ctx->cur_frame;
4622 struct op_context *cur_op_ctx = ctx->cur_op_ctx;
4623
4624 while (pop_item(cur_op_ctx));
4625
4626 item_array_clear(&cur_op_ctx->items);
4627 op_context_array_pop(&frame->pending_ops);
4629}
4630
4631static void call_frame_clear(struct call_frame *frame)
4632{
4633 uacpi_size i;
4634 op_context_array_clear(&frame->pending_ops);
4635 code_block_array_clear(&frame->code_blocks);
4636
4637 while (temp_namespace_node_array_size(&frame->temp_nodes) != 0) {
4639
4640 node = *temp_namespace_node_array_last(&frame->temp_nodes);
4642 temp_namespace_node_array_pop(&frame->temp_nodes);
4643 }
4644 temp_namespace_node_array_clear(&frame->temp_nodes);
4645
4646 for (i = 0; i < 7; ++i)
4647 uacpi_object_unref(frame->args[i]);
4648 for (i = 0; i < 8; ++i)
4649 uacpi_object_unref(frame->locals[i]);
4650
4651 uacpi_method_unref(frame->method);
4652}
4653
4686};
4687
4688static const uacpi_u8 *op_decode_cursor(const struct op_context *ctx)
4689{
4690 const struct uacpi_op_spec *spec = ctx->op;
4691
4693 return &spec->indirect_decode_ops[ctx->pc];
4694
4695 return &spec->decode_ops[ctx->pc];
4696}
4697
4699{
4700 uacpi_u8 byte;
4701
4702 byte = *op_decode_cursor(ctx);
4703 ctx->pc++;
4704
4705 return byte;
4706}
4707
4709{
4710 uacpi_aml_op op = 0;
4711
4712 op |= op_decode_byte(op_ctx);
4713 op |= op_decode_byte(op_ctx) << 8;
4714
4715 return op;
4716}
4717
4718// MSVC doesn't support __VA_OPT__ so we do this weirdness
4719#define EXEC_OP_DO_LVL(lvl, reason, ...) \
4720 uacpi_##lvl("Op 0x%04X ('%s'): "reason, \
4721 op_ctx->op->code, op_ctx->op->name __VA_ARGS__)
4722
4723#define EXEC_OP_DO_ERR(reason, ...) EXEC_OP_DO_LVL(error, reason, __VA_ARGS__)
4724#define EXEC_OP_DO_WARN(reason, ...) EXEC_OP_DO_LVL(warn, reason, __VA_ARGS__)
4725
4726#define EXEC_OP_ERR_3(reason, arg0, arg1, arg2) \
4727 EXEC_OP_DO_ERR(reason, ,arg0, arg1, arg2)
4728#define EXEC_OP_ERR_2(reason, arg0, arg1) EXEC_OP_DO_ERR(reason, ,arg0, arg1)
4729#define EXEC_OP_ERR_1(reason, arg0) EXEC_OP_DO_ERR(reason, ,arg0)
4730#define EXEC_OP_ERR(reason) EXEC_OP_DO_ERR(reason)
4731
4732#define EXEC_OP_WARN(reason) EXEC_OP_DO_WARN(reason)
4733
4734#define SPEC_SIMPLE_NAME "SimpleName := NameString | ArgObj | LocalObj"
4735#define SPEC_SUPER_NAME \
4736 "SuperName := SimpleName | DebugObj | ReferenceTypeOpcode"
4737#define SPEC_TERM_ARG \
4738 "TermArg := ExpressionOpcode | DataObject | ArgObj | LocalObj"
4739#define SPEC_OPERAND "Operand := TermArg => Integer"
4740#define SPEC_STRING "String := TermArg => String"
4741#define SPEC_TARGET "Target := SuperName | NullName"
4742
4743#define SPEC_COMPUTATIONAL_DATA \
4744 "ComputationalData := ByteConst | WordConst | DWordConst | QWordConst " \
4745 "| String | ConstObj | RevisionOp | DefBuffer"
4746
4748{
4749 switch (op) {
4754 return UACPI_TRUE;
4755 default:
4756 return UACPI_FALSE;
4757 }
4758}
4759
4761{
4762 switch (op) {
4768 return UACPI_TRUE;
4769 default:
4770 return UACPI_FALSE;
4771 }
4772}
4773
4775{
4776 switch (op) {
4780 return UACPI_TRUE;
4781 default:
4782 return UACPI_FALSE;
4783 }
4784}
4785
4787{
4788 switch (op) {
4791 return UACPI_TRUE;
4792 default:
4793 return UACPI_FALSE;
4794 }
4795}
4796
4797static uacpi_status op_typecheck(const struct op_context *op_ctx,
4798 const struct op_context *cur_op_ctx)
4799{
4800 const uacpi_char *expected_type_str;
4801 uacpi_u8 ok_mask = 0;
4802 uacpi_u8 props = cur_op_ctx->op->properties;
4803
4804 switch (*op_decode_cursor(op_ctx)) {
4805 // SimpleName := NameString | ArgObj | LocalObj
4807 expected_type_str = SPEC_SIMPLE_NAME;
4809 break;
4810
4811 // Target := SuperName | NullName
4813 expected_type_str = SPEC_TARGET;
4815 break;
4816
4817 // SuperName := SimpleName | DebugObj | ReferenceTypeOpcode
4820 expected_type_str = SPEC_SUPER_NAME;
4821 ok_mask |= UACPI_OP_PROPERTY_SUPERNAME;
4822 break;
4823
4824 // TermArg := ExpressionOpcode | DataObject | ArgObj | LocalObj
4832 expected_type_str = SPEC_TERM_ARG;
4833 ok_mask |= UACPI_OP_PROPERTY_TERM_ARG;
4834 break;
4835 default:
4837 }
4838
4839 if (!(props & ok_mask)) {
4840 EXEC_OP_ERR_2("invalid argument: '%s', expected a %s",
4841 cur_op_ctx->op->name, expected_type_str);
4843 }
4844
4845 return UACPI_STATUS_OK;
4846}
4847
4849 const struct op_context *op_ctx,
4850 const uacpi_object *obj,
4851 enum uacpi_object_type expected_type,
4852 const uacpi_char *spec_desc
4853)
4854{
4855 if (uacpi_likely(obj->type == expected_type))
4856 return UACPI_STATUS_OK;
4857
4858 EXEC_OP_ERR_2("invalid argument type: %s, expected a %s",
4859 uacpi_object_type_to_string(obj->type), spec_desc);
4861}
4862
4864 const struct op_context *op_ctx,
4865 const uacpi_object *obj
4866)
4867{
4869}
4870
4872 const struct op_context *op_ctx,
4873 const uacpi_object *obj
4874)
4875{
4877}
4878
4880 const struct op_context *op_ctx,
4881 const uacpi_object *obj
4882)
4883{
4884 switch (obj->type) {
4888 return UACPI_STATUS_OK;
4889 default:
4891 "invalid argument type: %s, expected a %s",
4894 );
4896 }
4897}
4898
4899static void emit_op_skip_warn(const struct op_context *op_ctx)
4900{
4901 EXEC_OP_WARN("skipping due to previous errors");
4902}
4903
4905 struct call_frame *frame, uacpi_size offset, enum uacpi_parse_op op,
4907)
4908{
4909 static const uacpi_char *oom_prefix = "<...>";
4910 static const uacpi_char *empty_string = "";
4911 static const uacpi_char *unknown_path = "<unknown-path>";
4912 static const uacpi_char *invalid_path = "<invalid-path>";
4913
4914 uacpi_status conv_ret;
4915 const uacpi_char *action;
4916 const uacpi_char *requested_path_to_print;
4917 const uacpi_char *middle_part = UACPI_NULL;
4918 const uacpi_char *prefix_path = UACPI_NULL;
4919 uacpi_char *requested_path = UACPI_NULL;
4921 uacpi_bool is_create;
4922
4923 is_create = op == UACPI_PARSE_OP_CREATE_NAMESTRING ||
4925
4926 if (is_create)
4927 action = "create";
4928 else
4929 action = "lookup";
4930
4931 conv_ret = name_string_to_path(
4932 frame, offset, &requested_path, &length
4933 );
4934 if (uacpi_unlikely_error(conv_ret)) {
4935 if (conv_ret == UACPI_STATUS_OUT_OF_MEMORY)
4936 requested_path_to_print = unknown_path;
4937 else
4938 requested_path_to_print = invalid_path;
4939 } else {
4940 requested_path_to_print = requested_path;
4941 }
4942
4943 if (requested_path && requested_path[0] != '\\') {
4945 frame->cur_scope
4946 );
4947 if (uacpi_unlikely(prefix_path == UACPI_NULL))
4948 prefix_path = oom_prefix;
4949
4950 if (prefix_path[1] != '\0')
4951 middle_part = ".";
4952 } else {
4953 prefix_path = empty_string;
4954 }
4955
4956 if (middle_part == UACPI_NULL)
4957 middle_part = empty_string;
4958
4959 if (length == 5 && !is_create) {
4961 level,
4962 "unable to %s named object '%s' within (or above) "
4963 "scope '%s': %s", action, requested_path_to_print,
4964 prefix_path, uacpi_status_to_string(ret)
4965 );
4966 } else {
4968 level,
4969 "unable to %s named object '%s%s%s': %s",
4970 action, prefix_path, middle_part,
4971 requested_path_to_print, uacpi_status_to_string(ret)
4972 );
4973 }
4974
4975 uacpi_free(requested_path, length);
4976 if (prefix_path != oom_prefix && prefix_path != empty_string)
4977 uacpi_free_dynamic_string(prefix_path);
4978}
4979
4981{
4982 struct op_context *op_ctx = ctx->cur_op_ctx;
4983
4984 EXEC_OP_ERR("no dedicated handler installed");
4986}
4987
5035};
5036
5038 /*
5039 * All OPs that don't have a handler dispatch to here if
5040 * UACPI_PARSE_OP_INVOKE_HANDLER is reached.
5041 */
5088};
5089
5091 [UACPI_AML_OP_Local0Op] = OP_HANDLER_LOCAL,
5092 [UACPI_AML_OP_Local1Op] = OP_HANDLER_LOCAL,
5093 [UACPI_AML_OP_Local2Op] = OP_HANDLER_LOCAL,
5094 [UACPI_AML_OP_Local3Op] = OP_HANDLER_LOCAL,
5095 [UACPI_AML_OP_Local4Op] = OP_HANDLER_LOCAL,
5096 [UACPI_AML_OP_Local5Op] = OP_HANDLER_LOCAL,
5097 [UACPI_AML_OP_Local6Op] = OP_HANDLER_LOCAL,
5098 [UACPI_AML_OP_Local7Op] = OP_HANDLER_LOCAL,
5099
5100 [UACPI_AML_OP_Arg0Op] = OP_HANDLER_ARG,
5101 [UACPI_AML_OP_Arg1Op] = OP_HANDLER_ARG,
5102 [UACPI_AML_OP_Arg2Op] = OP_HANDLER_ARG,
5103 [UACPI_AML_OP_Arg3Op] = OP_HANDLER_ARG,
5104 [UACPI_AML_OP_Arg4Op] = OP_HANDLER_ARG,
5105 [UACPI_AML_OP_Arg5Op] = OP_HANDLER_ARG,
5106 [UACPI_AML_OP_Arg6Op] = OP_HANDLER_ARG,
5107
5108 [UACPI_AML_OP_StringPrefix] = OP_HANDLER_STRING,
5109
5110 [UACPI_AML_OP_AddOp] = OP_HANDLER_BINARY_MATH,
5111 [UACPI_AML_OP_SubtractOp] = OP_HANDLER_BINARY_MATH,
5112 [UACPI_AML_OP_MultiplyOp] = OP_HANDLER_BINARY_MATH,
5113 [UACPI_AML_OP_DivideOp] = OP_HANDLER_BINARY_MATH,
5114 [UACPI_AML_OP_ShiftLeftOp] = OP_HANDLER_BINARY_MATH,
5115 [UACPI_AML_OP_ShiftRightOp] = OP_HANDLER_BINARY_MATH,
5116 [UACPI_AML_OP_AndOp] = OP_HANDLER_BINARY_MATH,
5117 [UACPI_AML_OP_NandOp] = OP_HANDLER_BINARY_MATH,
5118 [UACPI_AML_OP_OrOp] = OP_HANDLER_BINARY_MATH,
5119 [UACPI_AML_OP_NorOp] = OP_HANDLER_BINARY_MATH,
5120 [UACPI_AML_OP_XorOp] = OP_HANDLER_BINARY_MATH,
5121 [UACPI_AML_OP_ModOp] = OP_HANDLER_BINARY_MATH,
5122
5123 [UACPI_AML_OP_IfOp] = OP_HANDLER_CODE_BLOCK,
5124 [UACPI_AML_OP_ElseOp] = OP_HANDLER_CODE_BLOCK,
5125 [UACPI_AML_OP_WhileOp] = OP_HANDLER_CODE_BLOCK,
5126 [UACPI_AML_OP_ScopeOp] = OP_HANDLER_CODE_BLOCK,
5127
5128 [UACPI_AML_OP_ContinueOp] = OP_HANDLER_CONTROL_FLOW,
5129 [UACPI_AML_OP_BreakOp] = OP_HANDLER_CONTROL_FLOW,
5130
5131 [UACPI_AML_OP_ReturnOp] = OP_HANDLER_RETURN,
5132
5133 [UACPI_AML_OP_MethodOp] = OP_HANDLER_CREATE_METHOD,
5134
5135 [UACPI_AML_OP_StoreOp] = OP_HANDLER_COPY_OBJECT_OR_STORE,
5136 [UACPI_AML_OP_CopyObjectOp] = OP_HANDLER_COPY_OBJECT_OR_STORE,
5137
5138 [UACPI_AML_OP_IncrementOp] = OP_HANDLER_INC_DEC,
5139 [UACPI_AML_OP_DecrementOp] = OP_HANDLER_INC_DEC,
5140
5141 [UACPI_AML_OP_RefOfOp] = OP_HANDLER_REF_OF,
5142 [UACPI_AML_OP_DerefOfOp] = OP_HANDLER_DEREF_OF,
5143
5144 [UACPI_AML_OP_LnotOp] = OP_HANDLER_LOGICAL_NOT,
5145
5146 [UACPI_AML_OP_LEqualOp] = OP_HANDLER_BINARY_LOGIC,
5147 [UACPI_AML_OP_LandOp] = OP_HANDLER_BINARY_LOGIC,
5148 [UACPI_AML_OP_LorOp] = OP_HANDLER_BINARY_LOGIC,
5149 [UACPI_AML_OP_LGreaterOp] = OP_HANDLER_BINARY_LOGIC,
5150 [UACPI_AML_OP_LLessOp] = OP_HANDLER_BINARY_LOGIC,
5151
5152 [UACPI_AML_OP_InternalOpNamedObject] = OP_HANDLER_NAMED_OBJECT,
5153
5154 [UACPI_AML_OP_BufferOp] = OP_HANDLER_BUFFER,
5155
5156 [UACPI_AML_OP_PackageOp] = OP_HANDLER_PACKAGE,
5157 [UACPI_AML_OP_VarPackageOp] = OP_HANDLER_PACKAGE,
5158
5159 [UACPI_AML_OP_NameOp] = OP_HANDLER_CREATE_NAMED,
5160
5161 [UACPI_AML_OP_CreateBitFieldOp] = OP_HANDLER_CREATE_BUFFER_FIELD,
5162 [UACPI_AML_OP_CreateByteFieldOp] = OP_HANDLER_CREATE_BUFFER_FIELD,
5163 [UACPI_AML_OP_CreateWordFieldOp] = OP_HANDLER_CREATE_BUFFER_FIELD,
5164 [UACPI_AML_OP_CreateDWordFieldOp] = OP_HANDLER_CREATE_BUFFER_FIELD,
5165 [UACPI_AML_OP_CreateQWordFieldOp] = OP_HANDLER_CREATE_BUFFER_FIELD,
5166
5167 [UACPI_AML_OP_InternalOpReadFieldAsBuffer] = OP_HANDLER_READ_FIELD,
5168 [UACPI_AML_OP_InternalOpReadFieldAsInteger] = OP_HANDLER_READ_FIELD,
5169
5170 [UACPI_AML_OP_ToIntegerOp] = OP_HANDLER_TO,
5171 [UACPI_AML_OP_ToBufferOp] = OP_HANDLER_TO,
5172 [UACPI_AML_OP_ToDecimalStringOp] = OP_HANDLER_TO,
5173 [UACPI_AML_OP_ToHexStringOp] = OP_HANDLER_TO,
5174 [UACPI_AML_OP_ToStringOp] = OP_HANDLER_TO_STRING,
5175
5176 [UACPI_AML_OP_AliasOp] = OP_HANDLER_ALIAS,
5177
5178 [UACPI_AML_OP_ConcatOp] = OP_HANDLER_CONCATENATE,
5179 [UACPI_AML_OP_ConcatResOp] = OP_HANDLER_CONCATENATE_RES,
5180
5181 [UACPI_AML_OP_SizeOfOp] = OP_HANDLER_SIZEOF,
5182
5183 [UACPI_AML_OP_NotOp] = OP_HANDLER_UNARY_MATH,
5184 [UACPI_AML_OP_FindSetLeftBitOp] = OP_HANDLER_UNARY_MATH,
5185 [UACPI_AML_OP_FindSetRightBitOp] = OP_HANDLER_UNARY_MATH,
5186
5187 [UACPI_AML_OP_IndexOp] = OP_HANDLER_INDEX,
5188
5189 [UACPI_AML_OP_ObjectTypeOp] = OP_HANDLER_OBJECT_TYPE,
5190
5191 [UACPI_AML_OP_MidOp] = OP_HANDLER_MID,
5192
5193 [UACPI_AML_OP_MatchOp] = OP_HANDLER_MATCH,
5194
5195 [UACPI_AML_OP_NotifyOp] = OP_HANDLER_NOTIFY,
5196
5197 [UACPI_AML_OP_BreakPointOp] = OP_HANDLER_FIRMWARE_REQUEST,
5198};
5199
5200#define EXT_OP_IDX(op) (op & 0xFF)
5201
5203 [EXT_OP_IDX(UACPI_AML_OP_CreateFieldOp)] = OP_HANDLER_CREATE_BUFFER_FIELD,
5204 [EXT_OP_IDX(UACPI_AML_OP_CondRefOfOp)] = OP_HANDLER_REF_OF,
5205 [EXT_OP_IDX(UACPI_AML_OP_OpRegionOp)] = OP_HANDLER_CREATE_OP_REGION,
5206 [EXT_OP_IDX(UACPI_AML_OP_DeviceOp)] = OP_HANDLER_CODE_BLOCK,
5207 [EXT_OP_IDX(UACPI_AML_OP_ProcessorOp)] = OP_HANDLER_CODE_BLOCK,
5208 [EXT_OP_IDX(UACPI_AML_OP_PowerResOp)] = OP_HANDLER_CODE_BLOCK,
5209 [EXT_OP_IDX(UACPI_AML_OP_ThermalZoneOp)] = OP_HANDLER_CODE_BLOCK,
5210 [EXT_OP_IDX(UACPI_AML_OP_TimerOp)] = OP_HANDLER_TIMER,
5211 [EXT_OP_IDX(UACPI_AML_OP_MutexOp)] = OP_HANDLER_CREATE_MUTEX_OR_EVENT,
5212 [EXT_OP_IDX(UACPI_AML_OP_EventOp)] = OP_HANDLER_CREATE_MUTEX_OR_EVENT,
5213
5214 [EXT_OP_IDX(UACPI_AML_OP_FieldOp)] = OP_HANDLER_CREATE_FIELD,
5215 [EXT_OP_IDX(UACPI_AML_OP_IndexFieldOp)] = OP_HANDLER_CREATE_FIELD,
5216 [EXT_OP_IDX(UACPI_AML_OP_BankFieldOp)] = OP_HANDLER_CREATE_FIELD,
5217
5218 [EXT_OP_IDX(UACPI_AML_OP_FromBCDOp)] = OP_HANDLER_BCD,
5219 [EXT_OP_IDX(UACPI_AML_OP_ToBCDOp)] = OP_HANDLER_BCD,
5220
5221 [EXT_OP_IDX(UACPI_AML_OP_DataRegionOp)] = OP_HANDLER_CREATE_DATA_REGION,
5222
5223 [EXT_OP_IDX(UACPI_AML_OP_LoadTableOp)] = OP_HANDLER_LOAD_TABLE,
5224 [EXT_OP_IDX(UACPI_AML_OP_LoadOp)] = OP_HANDLER_LOAD,
5225 [EXT_OP_IDX(UACPI_AML_OP_UnloadOp)] = OP_HANDLER_UNLOAD,
5226
5227 [EXT_OP_IDX(UACPI_AML_OP_StallOp)] = OP_HANDLER_STALL_OR_SLEEP,
5228 [EXT_OP_IDX(UACPI_AML_OP_SleepOp)] = OP_HANDLER_STALL_OR_SLEEP,
5229
5230 [EXT_OP_IDX(UACPI_AML_OP_SignalOp)] = OP_HANDLER_EVENT_CTL,
5231 [EXT_OP_IDX(UACPI_AML_OP_ResetOp)] = OP_HANDLER_EVENT_CTL,
5232 [EXT_OP_IDX(UACPI_AML_OP_WaitOp)] = OP_HANDLER_EVENT_CTL,
5233
5234 [EXT_OP_IDX(UACPI_AML_OP_AcquireOp)] = OP_HANDLER_MUTEX_CTL,
5235 [EXT_OP_IDX(UACPI_AML_OP_ReleaseOp)] = OP_HANDLER_MUTEX_CTL,
5236
5237 [EXT_OP_IDX(UACPI_AML_OP_FatalOp)] = OP_HANDLER_FIRMWARE_REQUEST,
5238};
5239
5244};
5245
5250)
5251{
5253 struct call_frame *frame;
5254
5255 if (uacpi_unlikely(call_frame_array_size(&ctx->call_stack) >=
5256 g_uacpi_rt_ctx.max_call_stack_depth))
5258
5259 ret = push_new_frame(ctx, &frame);
5261 return ret;
5262
5263 ret = enter_method(ctx, frame, method);
5265 goto method_dispatch_error;
5266
5267 if (type == METHOD_CALL_NATIVE) {
5268 uacpi_u8 arg_count;
5269
5270 arg_count = args ? args->count : 0;
5271 if (uacpi_unlikely(arg_count != method->args)) {
5273 "invalid number of arguments %zu to call %.4s, expected %d",
5274 args ? args->count : 0, node->name.text, method->args
5275 );
5276
5278 goto method_dispatch_error;
5279 }
5280
5281 if (args != UACPI_NULL) {
5282 uacpi_u8 i;
5283
5284 for (i = 0; i < method->args; ++i) {
5285 frame->args[i] = args->objects[i];
5286 uacpi_object_ref(args->objects[i]);
5287 }
5288 }
5289 } else if (type == METHOD_CALL_AML) {
5290 ret = frame_push_args(frame, ctx->cur_op_ctx);
5292 goto method_dispatch_error;
5293 }
5294
5297 goto method_dispatch_error;
5298
5299 ctx->cur_frame = frame;
5300 ctx->cur_op_ctx = UACPI_NULL;
5301 ctx->prev_op_ctx = UACPI_NULL;
5302 ctx->cur_block = code_block_array_last(&ctx->cur_frame->code_blocks);
5303
5304 if (method->native_call) {
5306
5309 goto method_dispatch_error;
5310
5311 return method->handler(ctx, retval);
5312 }
5313
5314 return UACPI_STATUS_OK;
5315
5316method_dispatch_error:
5317 call_frame_clear(frame);
5318 call_frame_array_pop(&ctx->call_stack);
5319 return ret;
5320}
5321
5323 struct call_frame *frame, struct op_context *op_ctx
5324)
5325{
5326 struct item *item;
5327
5328 if (op_ctx->tracked_pkg_idx == 0)
5329 return;
5330
5331 item = item_array_at(&op_ctx->items, op_ctx->tracked_pkg_idx - 1);
5332 frame->code_offset = item->pkg.end;
5333}
5334
5336{
5338 struct call_frame *frame = ctx->cur_frame;
5339 struct op_context *op_ctx;
5340 struct item *item = UACPI_NULL;
5341 enum uacpi_parse_op prev_op = 0, op;
5342
5343 /*
5344 * Allocate a new op context if previous is preempted (looking for a
5345 * dynamic argument), or doesn't exist at all.
5346 */
5348 ret = push_op(ctx);
5350 return ret;
5351 } else {
5352 trace_op(ctx->cur_op_ctx->op, OP_TRACE_ACTION_RESUME);
5353 }
5354
5355 if (ctx->prev_op_ctx)
5356 prev_op = *op_decode_cursor(ctx->prev_op_ctx);
5357
5358 for (;;) {
5360 return ret;
5361
5362 op_ctx = ctx->cur_op_ctx;
5363 frame = ctx->cur_frame;
5364
5365 if (op_ctx->pc == 0 && ctx->prev_op_ctx) {
5366 /*
5367 * Type check the current arg type against what is expected by the
5368 * preempted op. This check is able to catch most type violations
5369 * with the only exception being Operand as we only know whether
5370 * that evaluates to an integer after the fact.
5371 */
5372 ret = op_typecheck(ctx->prev_op_ctx, ctx->cur_op_ctx);
5374 return ret;
5375 }
5376
5377 op = op_decode_byte(op_ctx);
5378 trace_pop(op);
5379
5381 item = item_array_alloc(&op_ctx->items);
5384
5386 if (item->type == ITEM_OBJECT) {
5388
5390 type = op_decode_byte(op_ctx);
5391
5395 } else {
5397 }
5398 } else if (item == UACPI_NULL) {
5399 item = item_array_last(&op_ctx->items);
5400 }
5401
5402 switch (op) {
5403 case UACPI_PARSE_OP_END:
5405 trace_op(ctx->cur_op_ctx->op, OP_TRACE_ACTION_END);
5406
5408 uacpi_u8 idx;
5409
5410 idx = op_decode_byte(op_ctx);
5411 if (item_array_at(&op_ctx->items, idx)->handle != UACPI_NULL)
5412 break;
5413
5414 emit_op_skip_warn(op_ctx);
5415 }
5416
5417 apply_tracked_pkg(frame, op_ctx);
5418
5419 pop_op(ctx);
5420 if (ctx->cur_op_ctx) {
5421 ctx->cur_op_ctx->preempted = UACPI_FALSE;
5422 ctx->cur_op_ctx->pc++;
5423 }
5424
5425 return UACPI_STATUS_OK;
5426 }
5427
5429 emit_op_skip_warn(op_ctx);
5430 break;
5431
5443 /*
5444 * Preempt this op parsing for now as we wait for the dynamic arg
5445 * to be parsed.
5446 */
5447 op_ctx->preempted = UACPI_TRUE;
5448 op_ctx->pc--;
5449 return UACPI_STATUS_OK;
5450
5452 op_ctx->tracked_pkg_idx = item_array_size(&op_ctx->items);
5455 ret = parse_package_length(frame, &item->pkg);
5456 break;
5457
5460 void *dst;
5461 uacpi_u8 src_width;
5462
5465 dst = &item->obj->integer;
5466 src_width = 8;
5467 } else {
5468 dst = &item->immediate;
5469 src_width = op_decode_byte(op_ctx);
5470 }
5471
5473 dst, op_decode_cursor(op_ctx),
5474 sizeof(uacpi_u64), src_width
5475 );
5476 op_ctx->pc += src_width;
5477 break;
5478 }
5479
5481 break;
5482
5486 void *dst;
5487
5488 width = op_decode_byte(op_ctx);
5491
5494 item->obj->integer = 0;
5495 dst = &item->obj->integer;
5496 } else {
5498 }
5499
5501 frame->code_offset += width;
5502 break;
5503 }
5504
5508 obj->type = UACPI_OBJECT_INTEGER;
5509 obj->integer = op == UACPI_PARSE_OP_LOAD_FALSE_OBJECT ? 0 : ones();
5510 break;
5511 }
5512
5514 item->immediate = frame->code_offset;
5515 break;
5516
5519 break;
5520
5522 uacpi_object_type expected_type;
5523
5524 expected_type = op_decode_byte(op_ctx);
5525
5526 if (uacpi_unlikely(item->obj->type != expected_type)) {
5527 EXEC_OP_ERR_2("bad object type: expected %s, got %s!",
5528 uacpi_object_type_to_string(expected_type),
5531 }
5532
5533 break;
5534 }
5535
5537 uacpi_object_type_bits expected_mask = 0;
5538 uacpi_bool one_of;
5540 uacpi_u8 num_types, i;
5541
5542 num_types = op_decode_byte(op_ctx);
5543 for (i = 0; i < num_types; i++) {
5544 type = op_decode_byte(op_ctx);
5545 if (i < UACPI_ARRAY_SIZE(types))
5546 types[i] = type;
5547
5548 expected_mask |= 1u << type;
5549 }
5550
5551 one_of = uacpi_object_is_one_of(item->obj, expected_mask);
5552 if (uacpi_likely(one_of))
5553 break;
5554
5556
5557 if (i == 2) {
5559 "bad object type: expected one of %s/%s, got %s!",
5563 );
5564 break;
5565 }
5566
5568 "bad object type: expected one of 0x%08X, got %s!",
5569 expected_mask, uacpi_object_type_to_string(item->obj->type)
5570 );
5571 break;
5572 }
5573
5575 frame->code_offset--;
5576 break;
5577
5579 item_array_at(&op_ctx->items, op_decode_byte(op_ctx))->immediate--;
5580 break;
5581
5583 pop_item(op_ctx);
5584 item = item_array_last(&op_ctx->items);
5585 break;
5586
5588 uacpi_size pkg_idx = op_ctx->tracked_pkg_idx - 1;
5589 struct package_length *pkg;
5590 uacpi_u8 bytes_skip;
5591
5592 bytes_skip = op_decode_byte(op_ctx);
5593 pkg = &item_array_at(&op_ctx->items, pkg_idx)->pkg;
5594
5595 if (frame->code_offset >= pkg->end)
5596 op_ctx->pc += bytes_skip;
5597
5598 break;
5599 }
5600
5605 uacpi_u8 idx, bytes_skip;
5606 uacpi_bool is_null, skip_if_null;
5607
5611 } else {
5612 idx = op_decode_byte(op_ctx);
5613 is_null = item_array_at(&op_ctx->items, idx)->handle == UACPI_NULL;
5614 }
5615
5616 bytes_skip = op_decode_byte(op_ctx);
5617 skip_if_null = op == UACPI_PARSE_OP_IF_NOT_NULL ||
5619
5620 if (is_null == skip_if_null)
5621 op_ctx->pc += bytes_skip;
5622
5623 break;
5624 }
5625
5627 uacpi_u8 value, bytes_skip;
5628
5629 value = op_decode_byte(op_ctx);
5630 bytes_skip = op_decode_byte(op_ctx);
5631
5632 if (item->immediate != value)
5633 op_ctx->pc += bytes_skip;
5634
5635 break;
5636 }
5637
5640 uacpi_u8 bytes_skip;
5641 uacpi_bool is_false, skip_if_false;
5642
5643 bytes_skip = op_decode_byte(op_ctx);
5644 is_false = item->obj->integer == 0;
5645 skip_if_false = op == UACPI_PARSE_OP_IF_LAST_TRUE;
5646
5647 if (is_false == skip_if_false)
5648 op_ctx->pc += bytes_skip;
5649
5650 break;
5651 }
5652
5653 case UACPI_PARSE_OP_JMP: {
5654 op_ctx->pc = op_decode_byte(op_ctx);
5655 break;
5656 }
5657
5663 uacpi_size offset = frame->code_offset;
5664 enum resolve_behavior behavior;
5665
5669 else
5671
5672 ret = resolve_name_string(frame, behavior, &item->node);
5673
5674 if (ret == UACPI_STATUS_NOT_FOUND) {
5675 uacpi_bool is_ok;
5676
5677 if (prev_op) {
5678 is_ok = op_allows_unresolved(prev_op);
5679 is_ok &= op_allows_unresolved(op);
5680 } else {
5681 // This is the only standalone op where we allow unresolved
5682 is_ok = op_ctx->op->code == UACPI_AML_OP_ExternalOp;
5683 }
5684
5685 if (is_ok)
5687 }
5688
5691 uacpi_status trace_ret = ret;
5692 uacpi_bool abort_whileif = UACPI_FALSE;
5693
5694 if (frame->method->named_objects_persist &&
5697 struct op_context *first_ctx;
5698
5699 first_ctx = op_context_array_at(&frame->pending_ops, 0);
5700 abort_whileif = first_ctx->op->code == UACPI_AML_OP_WhileOp ||
5701 first_ctx->op->code == UACPI_AML_OP_IfOp;
5702
5703 if (op_allows_unresolved_if_load(op) || abort_whileif) {
5704 lvl = UACPI_LOG_WARN;
5706 }
5707 }
5708
5710 frame, offset, op, trace_ret, lvl
5711 );
5712
5713 if (abort_whileif) {
5714 while (op_context_array_size(&frame->pending_ops) != 1)
5715 pop_op(ctx);
5716
5717 op_ctx = op_context_array_at(&frame->pending_ops, 0);
5718 op_ctx->pc++;
5719 op_ctx->preempted = UACPI_FALSE;
5720 break;
5721 }
5722
5725 }
5726
5728 !frame->method->named_objects_persist)
5730
5731 break;
5732 }
5733
5735 uacpi_aml_op code = op_ctx->op->code;
5736 uacpi_u8 idx;
5737
5738 if (code <= 0xFF)
5740 else
5742
5743 ret = op_handlers[idx](ctx);
5744 break;
5745 }
5746
5748 item = item_array_at(&op_ctx->items, op_decode_byte(op_ctx));
5749 ret = do_install_node_item(frame, item);
5751 uacpi_object_unref(item->node->object);
5752 item->node->object = UACPI_NULL;
5753 }
5754 break;
5755
5759 struct item *dst;
5760
5761 if (!ctx->prev_op_ctx)
5762 break;
5763
5764 switch (prev_op) {
5770
5771 if (prev_op == UACPI_PARSE_OP_OPERAND)
5772 ret = typecheck_operand(ctx->prev_op_ctx, src);
5773 else if (prev_op == UACPI_PARSE_OP_STRING)
5774 ret = typecheck_string(ctx->prev_op_ctx, src);
5775 else if (prev_op == UACPI_PARSE_OP_COMPUTATIONAL_DATA)
5776 ret = typecheck_computational_data(ctx->prev_op_ctx, src);
5777
5778 break;
5781 src = item->obj;
5782 break;
5783
5789 src = item->obj;
5790 break;
5791
5792 default:
5793 EXEC_OP_ERR_1("don't know how to copy/transfer object to %d",
5794 prev_op);
5796 break;
5797 }
5798
5800 dst = item_array_last(&ctx->prev_op_ctx->items);
5801 dst->type = ITEM_OBJECT;
5802
5804 dst->obj = src;
5805 uacpi_object_ref(dst->obj);
5806 } else {
5808 if (uacpi_unlikely(dst->obj == UACPI_NULL)) {
5810 break;
5811 }
5812
5815 }
5816 }
5817 break;
5818 }
5819
5822 uacpi_object *dst, *src;
5823
5824 dst = item_array_at(&op_ctx->items, op_decode_byte(op_ctx))->obj;
5825
5827 src = item_array_at(&op_ctx->items,
5828 op_decode_byte(op_ctx))->obj;
5829 } else {
5830 src = item->obj;
5831 }
5832
5834 break;
5835 }
5836
5837 // Nothing to do here, object is allocated automatically
5841 break;
5842
5846 enum uacpi_assign_behavior behavior;
5847
5848 item_array_pop(&op_ctx->items);
5849 item = item_array_last(&op_ctx->items);
5850
5853 else
5855
5856 ret = uacpi_object_assign(temp, item->obj, behavior);
5858 break;
5859
5861 item->obj = temp;
5862 break;
5863 }
5864
5866 struct uacpi_namespace_node *node;
5868
5869 node = item_array_at(&op_ctx->items, 0)->node;
5871
5874 );
5875 return ret;
5876 }
5877
5879 struct uacpi_namespace_node *node;
5881
5882 node = item_array_at(&op_ctx->items, 0)->node;
5883 method = item_array_at(&op_ctx->items, 1)->obj->method;
5884
5887 );
5888 return ret;
5889 }
5890
5892 uacpi_aml_op new_op = UACPI_AML_OP_InternalOpNamedObject;
5894
5895 if (item->node == UACPI_NULL) {
5896 if (!op_allows_unresolved(prev_op))
5898 break;
5899 }
5900
5902
5903 switch (obj->type) {
5904 case UACPI_OBJECT_METHOD: {
5905 uacpi_bool should_invoke;
5906
5907 switch (prev_op) {
5910 should_invoke = UACPI_FALSE;
5911 break;
5912 default:
5913 should_invoke = !op_wants_supername(prev_op);
5914 }
5915
5916 if (!should_invoke)
5917 break;
5918
5919 new_op = UACPI_AML_OP_InternalOpMethodCall0Args;
5920 new_op += obj->method->args;
5921 break;
5922 }
5923
5927
5928 if (!op_wants_term_arg_or_operand(prev_op))
5929 break;
5930
5933 const uacpi_char *field_path;
5934
5936 item->node
5937 );
5938
5940 "unable to perform a read from field %s: "
5941 "parent opregion gone", field_path
5942 );
5943 uacpi_free_absolute_path(field_path);
5944 }
5945
5946 switch (type) {
5948 new_op = UACPI_AML_OP_InternalOpReadFieldAsBuffer;
5949 break;
5951 new_op = UACPI_AML_OP_InternalOpReadFieldAsInteger;
5952 break;
5953 default:
5955 continue;
5956 }
5957 break;
5958 }
5959 default:
5960 break;
5961 }
5962
5963 op_ctx->pc = 0;
5964 op_ctx->op = uacpi_get_op_spec(new_op);
5965 break;
5966 }
5967
5969 uacpi_aml_op next_op, target_op;
5970 uacpi_u32 cur_offset;
5971 uacpi_u8 op_length;
5972
5973 cur_offset = frame->code_offset;
5974 apply_tracked_pkg(frame, op_ctx);
5975 op_length = peek_next_op(frame, &next_op);
5976
5977 target_op = op_decode_aml_op(op_ctx);
5978 if (op_length == 0 || next_op != target_op) {
5979 // Revert tracked package
5980 frame->code_offset = cur_offset;
5981 break;
5982 }
5983
5984 frame->code_offset += op_length;
5985 op_ctx->switched_from = op_ctx->op->code;
5986 op_ctx->op = uacpi_get_op_spec(target_op);
5987 op_ctx->pc = 0;
5988 break;
5989 }
5990
5992 uacpi_aml_op target_op;
5993 uacpi_u8 skip_bytes;
5994
5995 target_op = op_decode_aml_op(op_ctx);
5996 skip_bytes = op_decode_byte(op_ctx);
5997
5998 if (op_ctx->switched_from != target_op)
5999 op_ctx->pc += skip_bytes;
6000 break;
6001 }
6002
6003 default:
6004 EXEC_OP_ERR_1("unhandled parser op '%d'", op);
6006 break;
6007 }
6008 }
6009}
6010
6012{
6013 uacpi_control_method *method = ctx->cur_frame->method;
6014
6015 if (method->is_serialized) {
6017 &ctx->held_mutexes, method->mutex, FORCE_RELEASE_YES
6018 );
6019 ctx->sync_level = ctx->cur_frame->prev_sync_level;
6020 }
6021
6022 call_frame_clear(ctx->cur_frame);
6023 call_frame_array_pop(&ctx->call_stack);
6024
6025 ctx->cur_frame = call_frame_array_last(&ctx->call_stack);
6027}
6028
6031 uacpi_u32 aml_offset, uacpi_u32 method_size, const uacpi_char *op
6032)
6033{
6034 static const uacpi_char *unknown_path = "<unknown>";
6035 uacpi_char oom_absolute_path[9] = "<?>.";
6036
6037 const uacpi_char *absolute_path;
6038
6039 if (block != UACPI_NULL && block->type == CODE_BLOCK_SCOPE) {
6041 if (uacpi_unlikely(absolute_path == UACPI_NULL))
6042 uacpi_memcpy(oom_absolute_path + 4, block->node->name.text, 4);
6043 } else {
6044 absolute_path = unknown_path;
6045 }
6046
6048 " #%zu in %s()+%u/%u at %s",
6049 depth, absolute_path, aml_offset, method_size, op
6050 );
6051
6052 if (absolute_path != oom_absolute_path && absolute_path != unknown_path)
6053 uacpi_free_dynamic_string(absolute_path);
6054}
6055
6057{
6059 uacpi_bool should_stop;
6060
6061 /*
6062 * Non-empty call stack here means the execution was aborted at some point,
6063 * probably due to a bytecode error.
6064 */
6065 depth = call_frame_array_size(&ctx->call_stack);
6066
6067 if (depth != 0) {
6068 uacpi_size idx = 0;
6069 uacpi_bool table_level_code;
6070 const struct uacpi_op_spec *op;
6071 const uacpi_char *op_name;
6072
6073 do {
6074 op = UACPI_NULL;
6075 table_level_code = ctx->cur_frame->method->named_objects_persist;
6076
6077 if (table_level_code && idx != 0)
6078 /*
6079 * This isn't the first frame that we are aborting.
6080 * If this is table-level code, we have just unwound a call
6081 * chain that had triggered an abort. Stop here, no need to
6082 * abort table load because of it.
6083 */
6084 break;
6085
6086 while (op_context_array_size(&ctx->cur_frame->pending_ops) != 0) {
6087 if (op == UACPI_NULL)
6088 op = op_context_array_last(
6089 &ctx->cur_frame->pending_ops
6090 )->op;
6091
6092 pop_op(ctx);
6093 }
6094
6095 /*
6096 * For the very first frame, fetch the opcode from the execution
6097 * context directly if we got nothing from the pending_ops array.
6098 * The reason we do this is because in case this was an invalid
6099 * opcode it won't actually end up in the pending_ops array at all.
6100 * This is only possible for the first frame, since all the frames
6101 * below are guaranteed to be either in MethodCallOp or
6102 * Load{Table}Op.
6103 */
6104 if (op == UACPI_NULL && idx == 0)
6105 op = ctx->cur_op;
6106
6107 if (uacpi_likely(op != UACPI_NULL)) {
6108 op_name = op->name;
6109
6110 if (op_is_internal(op))
6111 /*
6112 * All internal OPs are prefixed with this, strip to
6113 * make them look nicer in the backtrace.
6114 */
6115 op_name += sizeof("InternalOp") - 1;
6116 } else {
6117 op_name = "<unknown>";
6118 }
6119
6121 code_block_array_at(&ctx->cur_frame->code_blocks, 0), idx,
6122 ctx->cur_frame->code_offset, ctx->cur_frame->method->size,
6123 op_name
6124 );
6125
6126 should_stop = idx++ == 0 && table_level_code;
6128 } while (--depth && !should_stop);
6129 }
6130}
6131
6133{
6134 if (ctx->ret)
6135 uacpi_object_unref(ctx->ret);
6136
6137 while (held_mutexes_array_size(&ctx->held_mutexes) != 0) {
6139 &ctx->held_mutexes,
6140 *held_mutexes_array_last(&ctx->held_mutexes),
6142 );
6143 }
6144
6145 call_frame_array_clear(&ctx->call_stack);
6146 held_mutexes_array_clear(&ctx->held_mutexes);
6147 uacpi_free(ctx, sizeof(*ctx));
6148}
6149
6152 const uacpi_object_array *args, uacpi_object **out_obj
6153)
6154{
6156 struct execution_context *ctx;
6157
6158 ctx = uacpi_kernel_alloc_zeroed(sizeof(*ctx));
6161
6162 if (out_obj != UACPI_NULL) {
6164 if (uacpi_unlikely(ctx->ret == UACPI_NULL)) {
6166 goto out;
6167 }
6168 }
6169
6172 goto out;
6173
6174 for (;;) {
6176 if (ctx->cur_frame == UACPI_NULL)
6177 break;
6178
6179 if (maybe_end_block(ctx))
6180 continue;
6181
6182 if (!call_frame_has_code(ctx->cur_frame)) {
6184 continue;
6185 }
6186
6187 ret = get_op(ctx);
6189 goto handle_method_abort;
6190
6192 }
6193
6194 ret = exec_op(ctx);
6196 goto handle_method_abort;
6197
6198 continue;
6199
6200 handle_method_abort:
6201 uacpi_error("aborting %s due to previous error: %s",
6202 ctx->cur_frame->method->named_objects_persist ?
6203 "table load" : "method invocation",
6206
6207 /*
6208 * Having a frame here implies that we just aborted a dynamic table
6209 * load. Signal to the caller that it failed by setting the return
6210 * value to false.
6211 */
6212 if (ctx->cur_frame) {
6213 struct item *it;
6214
6215 it = item_array_last(&ctx->cur_op_ctx->items);
6216 if (it != UACPI_NULL && it->obj != UACPI_NULL)
6217 it->obj->integer = 0;
6218 }
6219 }
6220
6221out:
6222 if (ctx->ret != UACPI_NULL) {
6223 uacpi_object *ret_obj = UACPI_NULL;
6224
6225 if (ctx->ret->type != UACPI_OBJECT_UNINITIALIZED) {
6226 ret_obj = ctx->ret;
6227 uacpi_object_ref(ret_obj);
6228 }
6229
6230 *out_obj = ret_obj;
6231 }
6232
6234 return ret;
6235}
6236
6238{
6239 struct execution_context *ctx = handle;
6240 uacpi_bool is_supported;
6243
6244 arg = uacpi_unwrap_internal_reference(ctx->cur_frame->args[0]);
6245 if (arg->type != UACPI_OBJECT_STRING) {
6246 uacpi_error("_OSI: invalid argument type %s, expected a String",
6249 }
6250
6251 if (retval == UACPI_NULL)
6252 return UACPI_STATUS_OK;
6253
6255
6256 ret = uacpi_handle_osi(arg->buffer->text, &is_supported);
6258 return ret;
6259
6260 retval->integer = is_supported ? ones() : 0;
6261
6262 uacpi_trace("_OSI(%s) => reporting as %ssupported",
6263 arg->buffer->text, is_supported ? "" : "un");
6264 return UACPI_STATUS_OK;
6265}
6266
6267#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:202
uacpi_status uacpi_release_aml_mutex(uacpi_mutex *)
Definition: mutex.c:242
uacpi_bool uacpi_this_thread_owns_aml_mutex(uacpi_mutex *)
Definition: mutex.c:194
UINT op
Definition: effect.c:236
unsigned int idx
Definition: utils.c:41
static void cleanup(void)
Definition: main.c:1335
BOOL force
Definition: metahost.c:100
#define byte(x, n)
Definition: tomcrypt.h:118
method
Definition: dragdrop.c:54
#define ACPI_SMALL_ITEM_NAME_IDX
Definition: acpi.h:1224
struct uacpi_runtime_context g_uacpi_rt_ctx
Definition: uacpi.c:17
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:148
uacpi_status uacpi_field_unit_get_bit_length(struct uacpi_field_unit *field, uacpi_size *out_length)
Definition: io.c:721
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:692
uacpi_status uacpi_read_field_unit(uacpi_field_unit *field, void *dst, uacpi_size size, uacpi_data_view *wtr_response)
Definition: io.c:530
uacpi_status uacpi_write_field_unit(uacpi_field_unit *field, const void *src, uacpi_size size, uacpi_data_view *wtr_response)
Definition: io.c:662
#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:834
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:89
uacpi_namespace_node * uacpi_namespace_node_find_sub_node(uacpi_namespace_node *parent, uacpi_object_name name)
Definition: namespace.c:446
#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:646
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:349
@ UACPI_SHOULD_LOCK_NO
Definition: namespace.h:94
uacpi_status uacpi_namespace_write_lock(void)
Definition: namespace.c:46
@ UACPI_MAY_SEARCH_ABOVE_PARENT_YES
Definition: namespace.h:85
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:491
#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:1379
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
uacpi_i32 uacpi_snprintf(uacpi_char *buffer, uacpi_size capacity, const uacpi_char *fmt,...)
Definition: stdlib.c:684
#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:1471
@ UACPI_PREALLOC_OBJECTS_YES
Definition: types.h:293
uacpi_object * uacpi_create_object(uacpi_object_type type)
Definition: types.c:327
void uacpi_object_detach_child(uacpi_object *parent)
Definition: types.c:966
uacpi_bool uacpi_package_fill(uacpi_package *pkg, uacpi_size num_elements, enum uacpi_prealloc_objects prealloc_objects)
Definition: types.c:124
void uacpi_buffer_to_view(uacpi_buffer *, uacpi_data_view *)
Definition: types.c:1043
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:204
@ UACPI_FIELD_UNIT_KIND_BANK
Definition: types.h:206
@ UACPI_FIELD_UNIT_KIND_INDEX
Definition: types.h:205
uacpi_mutex * uacpi_create_mutex(void)
Definition: types.c:181
void uacpi_object_attach_child(uacpi_object *parent, uacpi_object *child)
Definition: types.c:950
uacpi_status uacpi_object_assign(uacpi_object *dst, uacpi_object *src, enum uacpi_assign_behavior)
Definition: types.c:1372
void uacpi_method_unref(uacpi_control_method *)
Definition: types.c:655
uacpi_assign_behavior
Definition: types.h:275
@ UACPI_ASSIGN_BEHAVIOR_DEEP_COPY
Definition: types.h:276
@ UACPI_ASSIGN_BEHAVIOR_SHALLOW_COPY
Definition: types.h:277
void uacpi_mutex_unref(uacpi_mutex *)
Definition: types.c:495
@ UACPI_STRING_KIND_PATH
Definition: types.h:21
uacpi_object * uacpi_unwrap_internal_reference(uacpi_object *object)
Definition: types.c:1486
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:1074
#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:1034
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:53
#define uacpi_unlikely_error(expr)
Definition: status.h:49
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_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:60
void uacpi_object_ref(uacpi_object *obj)
Definition: types.c:734
uacpi_bool uacpi_object_is_one_of(uacpi_object *, uacpi_object_type_bits type_mask)
Definition: types.c:997
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_FIELD_UNIT_BIT
Definition: types.h:139
@ UACPI_OBJECT_BUFFER_FIELD_BIT
Definition: types.h:148
@ UACPI_OBJECT_OPERATION_REGION_BIT
Definition: types.h:144
@ UACPI_ACCESS_ATTRIBUTE_RAW_BYTES
Definition: types.h:483
@ UACPI_ACCESS_ATTRIBUTE_RAW_PROCESS_BYTES
Definition: types.h:484
@ UACPI_ACCESS_ATTRIBUTE_BYTES
Definition: types.h:480
const uacpi_char * uacpi_object_type_to_string(uacpi_object_type)
Definition: types.c:51
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:518
@ UACPI_FIRMWARE_REQUEST_TYPE_BREAKPOINT
Definition: types.h:517
uacpi_bool uacpi_object_is(uacpi_object *, uacpi_object_type)
Definition: types.c:992
@ 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:762
void uacpi_events_match_post_dynamic_table_load(void)
Definition: event.c:970
static uacpi_status field_byte_size(uacpi_object *obj, uacpi_size *out_size)
Definition: interpreter.c:3860
static uacpi_status handle_arg(struct execution_context *ctx)
Definition: interpreter.c:1087
static uacpi_status handle_control_flow(struct execution_context *ctx)
Definition: interpreter.c:4128
static uacpi_status handle_create_field(struct execution_context *ctx)
Definition: interpreter.c:1675
static uacpi_status table_id_error(const uacpi_char *opcode, const uacpi_char *arg, uacpi_buffer *str)
Definition: interpreter.c:1170
static uacpi_status handle_concatenate(struct execution_context *ctx)
Definition: interpreter.c:2962
static uacpi_status handle_unload(struct execution_context *ctx)
Definition: interpreter.c:3251
#define AML_READ(ptr, offset)
Definition: interpreter.c:340
static const uacpi_char *const op_trace_action_types[3]
Definition: interpreter.c:4277
static uacpi_status handle_deref_of(struct execution_context *ctx)
Definition: interpreter.c:3880
static uacpi_status handle_field_read(struct execution_context *ctx)
Definition: interpreter.c:3967
match_op
Definition: interpreter.c:3390
@ MGE
Definition: interpreter.c:3395
@ MLT
Definition: interpreter.c:3394
@ MGT
Definition: interpreter.c:3396
@ MLE
Definition: interpreter.c:3393
@ MEQ
Definition: interpreter.c:3392
@ MTR
Definition: interpreter.c:3391
static uacpi_status frame_setup_base_scope(struct call_frame *frame, uacpi_namespace_node *scope, uacpi_control_method *method)
Definition: interpreter.c:4327
static uacpi_status typecheck_operand(const struct op_context *op_ctx, const uacpi_object *obj)
Definition: interpreter.c:4863
#define EXEC_OP_ERR_3(reason, arg0, arg1, arg2)
Definition: interpreter.c:4726
static uacpi_status prepare_table_load(void *ptr, enum uacpi_table_load_cause cause, uacpi_control_method *in_method)
Definition: interpreter.c:1274
static uacpi_status do_load_table(uacpi_namespace_node *parent, struct acpi_sdt_hdr *tbl, enum uacpi_table_load_cause cause)
Definition: interpreter.c:1304
static uacpi_status method_get_ret_target(struct execution_context *ctx, uacpi_object **out_operand)
Definition: interpreter.c:1948
static uacpi_status store_to_target(uacpi_object *dst, uacpi_object *src, uacpi_data_view *wtr_response)
Definition: interpreter.c:4385
static void apply_tracked_pkg(struct call_frame *frame, struct op_context *op_ctx)
Definition: interpreter.c:5322
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:5246
static uacpi_bool op_allows_unresolved_if_load(enum uacpi_parse_op op)
Definition: interpreter.c:4786
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:4737
static uacpi_status handle_code_block(struct execution_context *ctx)
Definition: interpreter.c:4195
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:6029
static void truncate_number_if_needed(uacpi_object *obj)
Definition: interpreter.c:1935
static uacpi_status handle_event_ctl(struct execution_context *ctx)
Definition: interpreter.c:3610
op_handler
Definition: interpreter.c:4988
@ OP_HANDLER_LOGICAL_NOT
Definition: interpreter.c:5002
@ OP_HANDLER_INDEX
Definition: interpreter.c:5015
@ OP_HANDLER_CREATE_METHOD
Definition: interpreter.c:4997
@ OP_HANDLER_MUTEX_CTL
Definition: interpreter.c:5032
@ OP_HANDLER_STALL_OR_SLEEP
Definition: interpreter.c:5030
@ OP_HANDLER_BINARY_MATH
Definition: interpreter.c:4993
@ OP_HANDLER_INC_DEC
Definition: interpreter.c:4999
@ OP_HANDLER_CREATE_DATA_REGION
Definition: interpreter.c:5018
@ OP_HANDLER_BINARY_LOGIC
Definition: interpreter.c:5003
@ OP_HANDLER_NOTIFY
Definition: interpreter.c:5033
@ OP_HANDLER_LOCAL
Definition: interpreter.c:4990
@ OP_HANDLER_LOAD_TABLE
Definition: interpreter.c:5028
@ OP_HANDLER_ALIAS
Definition: interpreter.c:5010
@ OP_HANDLER_REF_OF
Definition: interpreter.c:5000
@ OP_HANDLER_OBJECT_TYPE
Definition: interpreter.c:5016
@ OP_HANDLER_UNLOAD
Definition: interpreter.c:5027
@ OP_HANDLER_STRING
Definition: interpreter.c:4992
@ OP_HANDLER_BUFFER
Definition: interpreter.c:5005
@ OP_HANDLER_UNARY_MATH
Definition: interpreter.c:5014
@ OP_HANDLER_CREATE_MUTEX_OR_EVENT
Definition: interpreter.c:5025
@ OP_HANDLER_PACKAGE
Definition: interpreter.c:5006
@ OP_HANDLER_MID
Definition: interpreter.c:5023
@ OP_HANDLER_CREATE_FIELD
Definition: interpreter.c:5019
@ OP_HANDLER_COPY_OBJECT_OR_STORE
Definition: interpreter.c:4998
@ OP_HANDLER_BCD
Definition: interpreter.c:5026
@ OP_HANDLER_CODE_BLOCK
Definition: interpreter.c:4995
@ OP_HANDLER_TO_STRING
Definition: interpreter.c:5021
@ OP_HANDLER_SIZEOF
Definition: interpreter.c:5013
@ OP_HANDLER_NAMED_OBJECT
Definition: interpreter.c:5004
@ OP_HANDLER_LOAD
Definition: interpreter.c:5029
@ OP_HANDLER_CONCATENATE_RES
Definition: interpreter.c:5012
@ OP_HANDLER_READ_FIELD
Definition: interpreter.c:5009
@ OP_HANDLER_CONCATENATE
Definition: interpreter.c:5011
@ OP_HANDLER_EVENT_CTL
Definition: interpreter.c:5031
@ OP_HANDLER_CONTROL_FLOW
Definition: interpreter.c:4994
@ OP_HANDLER_MATCH
Definition: interpreter.c:5024
@ OP_HANDLER_RETURN
Definition: interpreter.c:4996
@ OP_HANDLER_FIRMWARE_REQUEST
Definition: interpreter.c:5034
@ OP_HANDLER_CREATE_BUFFER_FIELD
Definition: interpreter.c:5008
@ OP_HANDLER_TIMER
Definition: interpreter.c:5022
@ OP_HANDLER_ARG
Definition: interpreter.c:4991
@ OP_HANDLER_CREATE_NAMED
Definition: interpreter.c:5007
@ OP_HANDLER_UNINSTALLED
Definition: interpreter.c:4989
@ OP_HANDLER_CREATE_OP_REGION
Definition: interpreter.c:5017
@ OP_HANDLER_DEREF_OF
Definition: interpreter.c:5001
@ OP_HANDLER_TO
Definition: interpreter.c:5020
static uacpi_status debug_store(uacpi_object *src)
Definition: interpreter.c:2222
static uacpi_status field_get_read_type(uacpi_object *obj, uacpi_object_type *out_type)
Definition: interpreter.c:3848
static uacpi_status handle_create_named(struct execution_context *ctx)
Definition: interpreter.c:3820
static uacpi_status object_assign_with_implicit_cast(uacpi_object *dst, uacpi_object *src, uacpi_data_view *wtr_response)
Definition: interpreter.c:975
static uacpi_status ensure_valid_idx(uacpi_object *obj, uacpi_size idx, uacpi_size src_size)
Definition: interpreter.c:2574
#define SPEC_SUPER_NAME
Definition: interpreter.c:4735
static uacpi_status method_get_ret_object(struct execution_context *ctx, uacpi_object **out_obj)
Definition: interpreter.c:1988
static uacpi_status handle_to(struct execution_context *ctx)
Definition: interpreter.c:2822
static uacpi_u8 parse_op_generates_item[0x100]
Definition: interpreter.c:4654
static uacpi_status handle_return(struct execution_context *ctx)
Definition: interpreter.c:4225
static uacpi_bool maybe_end_block(struct execution_context *ctx)
Definition: interpreter.c:4368
static void init_method_flags(uacpi_control_method *method, uacpi_u8 flags_byte)
Definition: interpreter.c:3522
static uacpi_status handle_create_method(struct execution_context *ctx)
Definition: interpreter.c:3529
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:2907
static uacpi_u64 ones(void)
Definition: interpreter.c:1943
static uacpi_object_type buffer_field_get_read_type(struct uacpi_buffer_field *field)
Definition: interpreter.c:3837
static void trace_pop(uacpi_u8 pop)
Definition: interpreter.c:4293
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:2452
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:3582
static uacpi_status handle_inc_dec(struct execution_context *ctx)
Definition: interpreter.c:4467
static uacpi_status handle_unary_math(struct execution_context *ctx)
Definition: interpreter.c:2547
static uacpi_status handle_object_type(struct execution_context *ctx)
Definition: interpreter.c:3157
static void report_table_id_find_error(const uacpi_char *opcode, struct uacpi_table_identifiers *id, uacpi_status ret)
Definition: interpreter.c:1179
static uacpi_status handle_bcd(struct execution_context *ctx)
Definition: interpreter.c:3214
static void pop_op(struct execution_context *ctx)
Definition: interpreter.c:4619
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:4904
static uacpi_bool pop_item(struct op_context *op_ctx)
Definition: interpreter.c:4600
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:4038
#define SPEC_STRING
Definition: interpreter.c:4740
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:1192
static uacpi_u8 handler_idx_of_ext_op[0x100]
Definition: interpreter.c:5202
static uacpi_status handle_match(struct execution_context *ctx)
Definition: interpreter.c:3419
static void emit_op_skip_warn(const struct op_context *op_ctx)
Definition: interpreter.c:4899
static uacpi_status handle_stall_or_sleep(struct execution_context *ctx)
Definition: interpreter.c:3186
static uacpi_status handle_notify(struct execution_context *ctx)
Definition: interpreter.c:3757
argx_or_localx
Definition: interpreter.c:1034
@ LOCALX
Definition: interpreter.c:1036
@ ARGX
Definition: interpreter.c:1035
static uacpi_bool op_wants_supername(enum uacpi_parse_op op)
Definition: interpreter.c:4747
static uacpi_status do_make_empty_object(uacpi_buffer *buf, uacpi_bool is_string)
Definition: interpreter.c:2794
static uacpi_status handle_ref_of(struct execution_context *ctx)
Definition: interpreter.c:2434
static void write_buffer_index(uacpi_buffer_index *buf_idx, uacpi_data_view *src_buf)
Definition: interpreter.c:963
static uacpi_status push_op(struct execution_context *ctx)
Definition: interpreter.c:4586
static uacpi_status parse_package_length(struct call_frame *frame, struct package_length *out_pkg)
Definition: interpreter.c:3464
static uacpi_status handle_to_string(struct execution_context *ctx)
Definition: interpreter.c:2880
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:4420
static uacpi_status handle_string(struct execution_context *ctx)
Definition: interpreter.c:774
static uacpi_status handle_arg_or_local(struct execution_context *ctx, uacpi_size idx, enum argx_or_localx type)
Definition: interpreter.c:1039
static uacpi_status handle_timer(struct execution_context *ctx)
Definition: interpreter.c:3175
static uacpi_u8 op_decode_byte(struct op_context *ctx)
Definition: interpreter.c:4698
static void stack_unwind(struct execution_context *ctx)
Definition: interpreter.c:6056
static uacpi_bool op_wants_term_arg_or_operand(enum uacpi_parse_op op)
Definition: interpreter.c:4760
#define SPEC_TARGET
Definition: interpreter.c:4741
static uacpi_status create_named_scope(struct op_context *op_ctx)
Definition: interpreter.c:4159
static void debug_store_no_recurse(const uacpi_char *prefix, uacpi_object *src)
Definition: interpreter.c:2139
static uacpi_status exec_op(struct execution_context *ctx)
Definition: interpreter.c:5335
static uacpi_status begin_block_execution(struct execution_context *ctx)
Definition: interpreter.c:2029
static uacpi_u8 handler_idx_of_op[0x100]
Definition: interpreter.c:5090
static uacpi_object * reference_unwind(uacpi_object *obj)
Definition: interpreter.c:2255
uacpi_status uacpi_execute_table(void *tbl, enum uacpi_table_load_cause cause)
Definition: interpreter.c:1612
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:2271
static void object_replace_child(uacpi_object *parent, uacpi_object *new_child)
Definition: interpreter.c:2286
static void execution_context_release(struct execution_context *ctx)
Definition: interpreter.c:6132
static uacpi_status make_null_string(uacpi_buffer *buf)
Definition: interpreter.c:2807
static uacpi_bool op_allows_unresolved(enum uacpi_parse_op op)
Definition: interpreter.c:4774
static uacpi_status copy_object_to_reference(uacpi_object *dst, uacpi_object *src)
Definition: interpreter.c:2319
static uacpi_status handle_create_alias(struct execution_context *ctx)
Definition: interpreter.c:1111
static void trace_op(const struct uacpi_op_spec *op, enum op_trace_action_type action)
Definition: interpreter.c:4283
static uacpi_status typecheck_string(const struct op_context *op_ctx, const uacpi_object *obj)
Definition: interpreter.c:4871
#define EXEC_OP_ERR(reason)
Definition: interpreter.c:4730
static uacpi_status handle_load_table(struct execution_context *ctx)
Definition: interpreter.c:1326
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:2104
static uacpi_size sizeof_int(void)
Definition: interpreter.c:913
static uacpi_status handle_local(struct execution_context *ctx)
Definition: interpreter.c:1078
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:2005
static uacpi_status(* op_handlers[])(struct execution_context *ctx)
Definition: interpreter.c:5037
static uacpi_size call_frame_code_bytes_left(struct call_frame *frame)
Definition: interpreter.c:296
op_trace_action_type
Definition: interpreter.c:4271
@ OP_TRACE_ACTION_RESUME
Definition: interpreter.c:4273
@ OP_TRACE_ACTION_BEGIN
Definition: interpreter.c:4272
@ OP_TRACE_ACTION_END
Definition: interpreter.c:4274
static uacpi_aml_op op_decode_aml_op(struct op_context *op_ctx)
Definition: interpreter.c:4708
static uacpi_status handle_create_op_region(struct execution_context *ctx)
Definition: interpreter.c:1125
#define SPEC_SIMPLE_NAME
Definition: interpreter.c:4734
static void call_frame_clear(struct call_frame *frame)
Definition: interpreter.c:4631
method_call_type
Definition: interpreter.c:5240
@ METHOD_CALL_AML
Definition: interpreter.c:5242
@ METHOD_CALL_TABLE_LOAD
Definition: interpreter.c:5243
@ METHOD_CALL_NATIVE
Definition: interpreter.c:5241
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:3120
static uacpi_status handle_load(struct execution_context *ctx)
Definition: interpreter.c:1446
#define SPEC_COMPUTATIONAL_DATA
Definition: interpreter.c:4743
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:3793
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:6150
static uacpi_status handle_package(struct execution_context *ctx)
Definition: interpreter.c:802
#define EXEC_OP_ERR_1(reason, arg0)
Definition: interpreter.c:4729
static void refresh_ctx_pointers(struct execution_context *ctx)
Definition: interpreter.c:4250
static uacpi_bool is_dynamic_table_load(enum uacpi_table_load_cause cause)
Definition: interpreter.c:1269
#define EXEC_OP_ERR_2(reason, arg0, arg1)
Definition: interpreter.c:4728
static uacpi_u64 object_to_integer(const uacpi_object *obj, uacpi_size max_buffer_bytes)
Definition: interpreter.c:2672
static uacpi_status handle_logical_not(struct execution_context *ctx)
Definition: interpreter.c:3274
static uacpi_status make_null_buffer(uacpi_buffer *buf)
Definition: interpreter.c:2812
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:953
static uacpi_bool match_one(enum match_op op, uacpi_u64 lhs, uacpi_u64 rhs)
Definition: interpreter.c:3399
static uacpi_status get_object_storage(uacpi_object *obj, uacpi_data_view *out_buf, uacpi_bool include_null)
Definition: interpreter.c:918
static uacpi_status enter_method(struct execution_context *ctx, struct call_frame *new_frame, uacpi_control_method *method)
Definition: interpreter.c:4541
static void ctx_reload_post_ret(struct execution_context *ctx)
Definition: interpreter.c:6011
#define EXT_OP_IDX(op)
Definition: interpreter.c:5200
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:1639
static uacpi_status handle_mutex_ctl(struct execution_context *ctx)
Definition: interpreter.c:3661
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:4266
static uacpi_status typecheck_computational_data(const struct op_context *op_ctx, const uacpi_object *obj)
Definition: interpreter.c:4879
static uacpi_u32 get_field_length(struct item *item)
Definition: interpreter.c:1626
static uacpi_status store_to_reference(uacpi_object *dst, uacpi_object *src, uacpi_data_view *wtr_response)
Definition: interpreter.c:2372
static uacpi_status push_new_frame(struct execution_context *ctx, struct call_frame **out_frame)
Definition: interpreter.c:4346
static uacpi_status handle_concatenate_res(struct execution_context *ctx)
Definition: interpreter.c:3073
static uacpi_bool handle_logical_equality(uacpi_object *lhs, uacpi_object *rhs)
Definition: interpreter.c:3288
static uacpi_status ensure_is_an_op_region(uacpi_namespace_node *node, uacpi_namespace_node **out_node)
Definition: interpreter.c:1657
static uacpi_status handle_binary_math(struct execution_context *ctx)
Definition: interpreter.c:2527
static uacpi_status buffer_to_string(uacpi_buffer *buf, uacpi_buffer *str, uacpi_bool is_hex)
Definition: interpreter.c:2733
static uacpi_status handle_binary_logic(struct execution_context *ctx)
Definition: interpreter.c:3341
static uacpi_status handle_named_object(struct execution_context *ctx)
Definition: interpreter.c:1096
#define SPEC_OPERAND
Definition: interpreter.c:4739
static uacpi_status integer_to_string(uacpi_u64 integer, uacpi_buffer *str, uacpi_bool is_hex)
Definition: interpreter.c:2700
static uacpi_status frame_push_args(struct call_frame *frame, struct op_context *op_ctx)
Definition: interpreter.c:4298
static uacpi_status uninstalled_op_handler(struct execution_context *ctx)
Definition: interpreter.c:4980
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:4848
static uacpi_bool handle_logical_less_or_greater(uacpi_aml_op op, uacpi_object *lhs, uacpi_object *rhs)
Definition: interpreter.c:3309
static uacpi_status handle_create_data_region(struct execution_context *ctx)
Definition: interpreter.c:1225
static uacpi_status op_typecheck(const struct op_context *op_ctx, const struct op_context *cur_op_ctx)
Definition: interpreter.c:4797
#define EXEC_OP_WARN(reason)
Definition: interpreter.c:4732
uacpi_status uacpi_osi(uacpi_handle handle, uacpi_object *retval)
Definition: interpreter.c:6237
static const uacpi_u8 * op_decode_cursor(const struct op_context *ctx)
Definition: interpreter.c:4688
static uacpi_status handle_index(struct execution_context *ctx)
Definition: interpreter.c:2587
return ret
Definition: mutex.c:147
action
Definition: namespace.c:707
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 res
Definition: glext.h:9613
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
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
const char cursor[]
Definition: icontest.c:13
uacpi_status uacpi_notify_all(uacpi_namespace_node *node, uacpi_u64 value)
Definition: notify.c:69
void uacpi_opregion_uninstall_handler(uacpi_namespace_node *node)
Definition: opregion.c:403
uacpi_status uacpi_initialize_opregion_node(uacpi_namespace_node *node)
Definition: opregion.c:788
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
static BOOL is_null(jsval_t v)
Definition: jsval.h:185
uacpi_bool uacpi_kernel_wait_for_event(uacpi_handle, uacpi_u16)
Definition: uacpiosl.c:66
void * uacpi_kernel_alloc(uacpi_size size)
Definition: uacpiosl.c:111
void uacpi_kernel_reset_event(uacpi_handle)
Definition: uacpiosl.c:79
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
void uacpi_kernel_signal_event(uacpi_handle)
Definition: uacpiosl.c:73
__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:600
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
uacpi_u32 uacpi_shareable_ref(uacpi_handle)
Definition: shareable.c:31
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:1635
struct uacpi_field_unit * field0
Definition: interpreter.c:1634
uacpi_namespace_node * region
Definition: interpreter.c:1633
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: 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:178
uacpi_u8 * code
Definition: types.h:170
uacpi_u32 size
Definition: types.h:174
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::@711::@713 breakpoint
struct uacpi_firmware_request::@711::@714 fatal
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:257
uacpi_u8 type
Definition: types.h:249
uacpi_field_unit * field_unit
Definition: types.h:269
uacpi_buffer_field buffer_field
Definition: types.h:255
uacpi_u64 integer
Definition: types.h:253
uacpi_object * inner_object
Definition: types.h:256
uacpi_buffer * buffer
Definition: types.h:258
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:122
uacpi_u64 table_idx
Definition: types.h:127
uacpi_u16 space
Definition: types.h:120
uacpi_u64 length
Definition: types.h:123
uacpi_object ** objects
Definition: types.h:36
uacpi_size count
Definition: types.h:37
uacpi_u8 system_level
Definition: types.h:159
uacpi_u16 resource_order
Definition: types.h:160
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
Definition: dlist.c:348
uacpi_u32 id
Definition: types.h:25
uacpi_char text[4]
Definition: types.h:24
Definition: pdh_main.c:96
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