PatchworkOS  966e257
A non-POSIX operating system.
Loading...
Searching...
No Matches
object.c
Go to the documentation of this file.
2
3#include <kernel/log/log.h>
4#include <kernel/log/panic.h>
5#include <modules/acpi/acpi.h>
9
10#include <errno.h>
11#include <stddef.h>
12#include <stdlib.h>
13#include <sys/math.h>
14
15// Used to check for memory leaks
17
18// Cache for aml_object_t to avoid frequent allocations
20
22
27
28static void aml_object_free(aml_object_t* object)
29{
30 if (object == NULL)
31 {
32 return;
33 }
34
35 // Named objects should never be able to be freed while still being named as the parent would still have a reference
36 // to them, unless the object is root.
37 if ((object->flags & AML_OBJECT_NAMED) && !(object->flags & AML_OBJECT_ROOT))
38 {
39 panic(NULL, "Attempted to free named non-root AML object '%s'", AML_NAME_TO_STRING(object->name));
40 }
41
42 aml_object_clear(object);
43
44 if (object->dir != NULL)
45 {
46 UNREF(object->dir);
47 object->dir = NULL;
48 }
49
51 {
52 list_push_back(&objectsCache, &object->listEntry);
53 }
54 else
55 {
56 free(object);
57 }
58
60}
61
63{
64 aml_object_t* object = NULL;
66 {
68 }
69
70 if (object == NULL)
71 {
72 object = calloc(1, sizeof(aml_object_t));
73 if (object == NULL)
74 {
75 return NULL;
76 }
77 }
78
79 ref_init(&object->ref, aml_object_free);
80 object->id = newObjectId++;
81 object->name = AML_NAME_UNDEFINED;
82 map_entry_init(&object->mapEntry);
83 list_entry_init(&object->listEntry);
84 object->overlay = NULL;
85 list_init(&object->children);
86 list_entry_init(&object->siblingsEntry);
87 object->parent = NULL;
88 object->flags = AML_OBJECT_NONE;
89 object->type = AML_UNINITIALIZED;
90 object->dir = NULL;
91
93 return object;
94}
95
97{
98 if (object == NULL)
99 {
100 return;
101 }
102
103 if (object->type == AML_UNINITIALIZED)
104 {
105 return;
106 }
107
108 if (object->type & AML_NAMESPACES)
109 {
110 aml_object_t* child;
111 aml_object_t* temp;
112 LIST_FOR_EACH_SAFE(child, temp, &object->children, siblingsEntry)
113 {
115 }
116 }
117
118 switch (object->type)
119 {
120 case AML_BUFFER:
121 if (object->buffer.content != NULL && object->buffer.length > AML_SMALL_BUFFER_SIZE)
122 {
123 free(object->buffer.content);
124 }
125 object->buffer.content = NULL;
126 object->buffer.length = 0;
127 break;
128 case AML_BUFFER_FIELD:
129 if (object->bufferField.target != NULL)
130 {
131 UNREF(object->bufferField.target);
132 }
133 object->bufferField.target = NULL;
134 object->bufferField.bitOffset = 0;
135 object->bufferField.bitSize = 0;
136 break;
137 case AML_DEBUG_OBJECT:
138 break;
139 case AML_DEVICE:
140 if (object->device.cfg != NULL)
141 {
142 panic(NULL, "Attempted to free configured device object '%s'", AML_NAME_TO_STRING(object->name));
143 }
144 break;
145 case AML_EVENT:
146 break;
147 case AML_FIELD_UNIT:
148 switch (object->fieldUnit.fieldType)
149 {
151 UNREF(object->fieldUnit.index);
152 object->fieldUnit.index = NULL;
153 UNREF(object->fieldUnit.data);
154 object->fieldUnit.data = NULL;
155 break;
157 UNREF(object->fieldUnit.bank);
158 object->fieldUnit.bank = NULL;
159 UNREF(object->fieldUnit.bankValue);
160 object->fieldUnit.bankValue = NULL;
161 UNREF(object->fieldUnit.opregion);
162 object->fieldUnit.opregion = NULL;
163 break;
165 UNREF(object->fieldUnit.opregion);
166 object->fieldUnit.opregion = NULL;
167 break;
168 default:
169 break;
170 }
171 object->fieldUnit.fieldType = 0;
172 object->fieldUnit.bitOffset = 0;
173 object->fieldUnit.bitSize = 0;
174 break;
175 case AML_INTEGER:
176 object->integer.value = 0;
177 break;
178 case AML_METHOD:
179 object->method.implementation = NULL;
180 object->method.methodFlags = (aml_method_flags_t){0};
181 object->method.start = NULL;
182 object->method.end = NULL;
184 break;
185 case AML_MUTEX:
186 object->mutex.syncLevel = 0;
188 break;
190 if (object->objectReference.target != NULL)
191 {
193 }
194 object->objectReference.target = NULL;
195 break;
197 object->opregion.space = 0;
198 object->opregion.offset = 0;
199 object->opregion.length = 0;
200 break;
201 case AML_PACKAGE:
202 if (object->package.elements != NULL)
203 {
204 for (uint64_t i = 0; i < object->package.length; i++)
205 {
206 UNREF(object->package.elements[i]);
207 object->package.elements[i] = NULL;
208 }
210 {
211 free(object->package.elements);
212 }
213 }
214 object->package.elements = NULL;
215 object->package.length = 0;
216 break;
218 object->powerResource.systemLevel = 0;
219 object->powerResource.resourceOrder = 0;
220 break;
221 case AML_PROCESSOR:
222 object->processor.procId = 0;
223 object->processor.pblkAddr = 0;
224 object->processor.pblkLen = 0;
225 break;
226 case AML_STRING:
227 if (object->string.content != NULL && object->string.length > AML_SMALL_STRING_SIZE)
228 {
229 free(object->string.content);
230 }
231 object->string.content = NULL;
232 object->string.length = 0;
233 break;
234 case AML_THERMAL_ZONE:
235 break;
236 case AML_ALIAS:
237 if (object->alias.target != NULL)
238 {
239 UNREF(object->alias.target);
240 }
241 object->alias.target = NULL;
242 break;
243 case AML_UNRESOLVED:
245 if (object->unresolved.from != NULL)
246 {
247 UNREF(object->unresolved.from);
248 }
249 object->unresolved.from = NULL;
250 object->unresolved.nameString = (aml_name_string_t){0};
251 object->unresolved.callback = NULL;
252 break;
254 break;
255 case AML_LOCAL:
256 if (object->local.value != NULL)
257 {
258 UNREF(object->local.value);
259 }
260 object->local.value = NULL;
261 break;
262 case AML_ARG:
263 if (object->arg.value != NULL)
264 {
265 UNREF(object->arg.value);
266 }
267 object->arg.value = NULL;
268 break;
269 default:
270 panic(NULL, "Unknown AML data type %u", object->type);
271 break;
272 }
273
274 object->type = AML_UNINITIALIZED;
275}
276
278{
279 if (parent == NULL)
280 {
281 return 0;
282 }
283
284 uint64_t count = 0;
285
286 if (parent->type & AML_NAMESPACES)
287 {
288 aml_object_t* child = NULL;
289 LIST_FOR_EACH(child, &parent->children, siblingsEntry)
290 {
291 count++;
293 }
294
295 return count;
296 }
297
298 switch (parent->type)
299 {
300 case AML_PACKAGE:
301 for (uint64_t i = 0; i < parent->package.length; i++)
302 {
303 aml_object_t* element = parent->package.elements[i];
304 if (element != NULL)
305 {
306 count++;
308 }
309 }
310 break;
311 case AML_FIELD_UNIT:
312 if (parent->fieldUnit.bankValue != NULL)
313 {
314 count++;
315 }
316 break;
317 default:
318 break;
319 }
320
321 return count;
322}
323
324static inline void aml_copy_bits(uint8_t* dst, uint64_t dstOffset, const uint8_t* src, uint64_t srcOffset,
325 uint64_t bitCount)
326{
327 while (bitCount > 0)
328 {
329 uint64_t dstByte = dstOffset / 8;
330 uint64_t dstBit = dstOffset % 8;
331 uint64_t srcByte = srcOffset / 8;
332 uint64_t srcBit = srcOffset % 8;
333
334 uint64_t bitsInDstByte = 8 - dstBit;
335 uint64_t bitsInSrcByte = 8 - srcBit;
336 uint64_t bitsToCopy = (bitsInDstByte < bitsInSrcByte) ? bitsInDstByte : bitsInSrcByte;
337 bitsToCopy = (bitsToCopy < bitCount) ? bitsToCopy : bitCount;
338
339 uint8_t srcMask = ((1 << bitsToCopy) - 1) << srcBit;
340 uint8_t bits = (src[srcByte] & srcMask) >> srcBit;
341
342 uint8_t dstMask = ((1 << bitsToCopy) - 1) << dstBit;
343 dst[dstByte] = (dst[dstByte] & ~dstMask) | (bits << dstBit);
344
345 dstOffset += bitsToCopy;
346 srcOffset += bitsToCopy;
347 bitCount -= bitsToCopy;
348 }
349}
350
352{
353 if (object == NULL || data == NULL || bitSize == 0)
354 {
355 errno = EINVAL;
356 return ERR;
357 }
358
359 switch (object->type)
360 {
361 case AML_INTEGER:
362 {
363 uint64_t value = 0;
364 for (uint64_t i = 0; i < (bitSize + 7) / 8; i++)
365 {
366 value |= ((uint64_t)data[i]) << (i * 8);
367 }
368
369 uint64_t effectiveBitSize = bitSize;
370 if (bitOffset >= aml_integer_bit_size())
371 {
372 return 0;
373 }
374 if (bitOffset + bitSize > aml_integer_bit_size())
375 {
376 effectiveBitSize = aml_integer_bit_size() - bitOffset;
377 }
378
379 uint64_t mask = (effectiveBitSize >= aml_integer_bit_size()) ? aml_integer_ones()
380 : ((1ULL << effectiveBitSize) - 1) << bitOffset;
381
382 object->integer.value = (object->integer.value & ~mask) | ((value << bitOffset) & mask);
383 break;
384 }
385 case AML_BUFFER:
386 case AML_STRING:
387 {
388 uint64_t length = object->type == AML_BUFFER ? object->buffer.length : object->string.length;
389 uint8_t* content = object->type == AML_BUFFER ? object->buffer.content : (uint8_t*)object->string.content;
390 uint64_t totalBits = length * 8;
391
392 if (bitOffset >= totalBits)
393 {
394 return 0;
395 }
396 if (bitOffset + bitSize > totalBits)
397 {
398 bitSize = totalBits - bitOffset;
399 }
400
401 aml_copy_bits(content, bitOffset, data, 0, bitSize);
402 break;
403 }
404 default:
405 errno = EINVAL;
406 return ERR;
407 }
408
409 return 0;
410}
411
413{
414 if (object == NULL || out == NULL || bitSize == 0)
415 {
416 errno = EINVAL;
417 return ERR;
418 }
419
420 memset(out, 0, (bitSize + 7) / 8);
421
422 switch (object->type)
423 {
424 case AML_INTEGER:
425 {
426 if (bitOffset >= aml_integer_bit_size())
427 {
428 return 0;
429 }
430
431 uint64_t effectiveBitSize = bitSize;
432 if (bitOffset + bitSize > aml_integer_bit_size())
433 {
434 effectiveBitSize = aml_integer_bit_size() - bitOffset;
435 }
436
437 uint64_t mask =
438 (effectiveBitSize >= aml_integer_bit_size()) ? aml_integer_ones() : ((1ULL << effectiveBitSize) - 1);
439 uint64_t value = (object->integer.value >> bitOffset) & mask;
440
441 for (uint64_t i = 0; i < (effectiveBitSize + 7) / 8; i++)
442 {
443 out[i] = (value >> (i * 8)) & 0xFF;
444 }
445 break;
446 }
447 case AML_BUFFER:
448 case AML_STRING:
449 {
450 uint64_t length = object->type == AML_BUFFER ? object->buffer.length : object->string.length;
451 uint8_t* content = object->type == AML_BUFFER ? object->buffer.content : (uint8_t*)object->string.content;
452 uint64_t totalBits = length * 8;
453
454 if (bitOffset >= totalBits)
455 {
456 return 0;
457 }
458 if (bitOffset + bitSize > totalBits)
459 {
460 bitSize = totalBits - bitOffset;
461 }
462
463 aml_copy_bits(out, 0, content, bitOffset, bitSize);
464 break;
465 }
466 default:
467 errno = EINVAL;
468 return ERR;
469 }
470
471 return 0;
472}
473
475{
476 if (object == NULL)
477 {
478 errno = EINVAL;
479 return ERR;
480 }
481
482 if (object->type != AML_UNINITIALIZED)
483 {
484 aml_object_clear(object);
485 }
486
487 return 0;
488}
489
491{
492 if (buffer == NULL)
493 {
494 errno = EINVAL;
495 return ERR;
496 }
497
498 if (newLength <= AML_SMALL_BUFFER_SIZE)
499 {
500 if (buffer->content != buffer->smallBuffer)
501 {
502 memcpy(buffer->smallBuffer, buffer->content, MIN(buffer->length, newLength));
503 free(buffer->content);
504 buffer->content = buffer->smallBuffer;
505 }
506 buffer->length = newLength;
507 return 0;
508 }
509
510 if (buffer->content == buffer->smallBuffer)
511 {
512 buffer->content = calloc(1, newLength);
513 if (buffer->content == NULL)
514 {
515 return ERR;
516 }
517 memcpy(buffer->content, buffer->smallBuffer, buffer->length);
518 }
519 else
520 {
521 uint8_t* newContent = realloc(buffer->content, newLength);
522 if (newContent == NULL)
523 {
524 return ERR;
525 }
526 buffer->content = newContent;
527 memset(&buffer->content[buffer->length], 0, newLength - buffer->length);
528 }
529 buffer->length = newLength;
530 return 0;
531}
532
534{
535 if (object == NULL)
536 {
537 errno = EINVAL;
538 return ERR;
539 }
540
541 if (object->type == AML_BUFFER)
542 {
543 if (aml_buffer_resize(&object->buffer, length) == ERR)
544 {
545 return ERR;
546 }
547 }
548 else
549 {
550 if (aml_object_check_clear(object) == ERR)
551 {
552 return ERR;
553 }
554
555 if (length <= AML_SMALL_BUFFER_SIZE)
556 {
557 object->buffer.content = object->buffer.smallBuffer;
559 }
560 else
561 {
562 object->buffer.content = calloc(1, length);
563 if (object->buffer.content == NULL)
564 {
565 return ERR;
566 }
567 }
568 object->buffer.length = length;
569 }
570
571 object->buffer.length = length;
572 object->type = AML_BUFFER;
573 return 0;
574}
575
577{
578 if (object == NULL || buffer == NULL || bytesToCopy > length)
579 {
580 errno = EINVAL;
581 return ERR;
582 }
583
584 if (aml_buffer_set_empty(object, length) == ERR)
585 {
586 return ERR;
587 }
588
589 memcpy(object->buffer.content, buffer, bytesToCopy);
590 memset(&object->buffer.content[bytesToCopy], 0, length - bytesToCopy);
591 return 0;
592}
593
595 aml_bit_size_t bitSize)
596{
597 if (object == NULL || target == NULL || bitSize == 0)
598 {
599 errno = EINVAL;
600 return ERR;
601 }
602
603 if (target->type != AML_BUFFER && target->type != AML_STRING)
604 {
605 errno = EINVAL;
606 return ERR;
607 }
608
609 if (object->type != AML_BUFFER_FIELD)
610 {
611 if (aml_object_check_clear(object) == ERR)
612 {
613 return ERR;
614 }
615 }
616 else
617 {
618 UNREF(object->bufferField.target);
619 }
620
621 object->bufferField.target = REF(target);
622 object->bufferField.bitOffset = bitOffset;
623 object->bufferField.bitSize = bitSize;
624 object->type = AML_BUFFER_FIELD;
625 return 0;
626}
627
629{
630 if (object == NULL)
631 {
632 errno = EINVAL;
633 return ERR;
634 }
635
636 if (aml_object_check_clear(object) == ERR)
637 {
638 return ERR;
639 }
640
641 object->type = AML_DEBUG_OBJECT;
642 return 0;
643}
644
646{
647 if (object == NULL)
648 {
649 errno = EINVAL;
650 return ERR;
651 }
652
653 if (aml_object_check_clear(object) == ERR)
654 {
655 return ERR;
656 }
657
658 object->type = AML_DEVICE;
659 object->device.cfg = NULL;
660 return 0;
661}
662
664{
665 if (object == NULL)
666 {
667 errno = EINVAL;
668 return ERR;
669 }
670
671 if (aml_object_check_clear(object) == ERR)
672 {
673 return ERR;
674 }
675
676 object->type = AML_EVENT;
677 return 0;
678}
679
681 aml_bit_size_t bitOffset, aml_bit_size_t bitSize)
682{
683 if (object == NULL || opregion == NULL || bitSize == 0)
684 {
685 errno = EINVAL;
686 return ERR;
687 }
688
689 if (aml_object_check_clear(object) == ERR)
690 {
691 return ERR;
692 }
693
694 object->fieldUnit.fieldType = AML_FIELD_UNIT_FIELD;
695 object->fieldUnit.index = NULL;
696 object->fieldUnit.data = NULL;
697 object->fieldUnit.bankValue = NULL;
698 object->fieldUnit.bank = NULL;
699 object->fieldUnit.opregion = REF(opregion);
700 object->fieldUnit.fieldFlags = flags;
701 object->fieldUnit.bitOffset = bitOffset;
702 object->fieldUnit.bitSize = bitSize;
703 object->type = AML_FIELD_UNIT;
704 return 0;
705}
706
709{
710 if (object == NULL || index == NULL || data == NULL || bitSize == 0)
711 {
712 errno = EINVAL;
713 return ERR;
714 }
715
716 if (aml_object_check_clear(object) == ERR)
717 {
718 return ERR;
719 }
720
721 object->fieldUnit.fieldType = AML_FIELD_UNIT_INDEX_FIELD;
722 object->fieldUnit.index = REF(index);
723 object->fieldUnit.data = REF(data);
724 object->fieldUnit.bankValue = NULL;
725 object->fieldUnit.bank = NULL;
726 object->fieldUnit.opregion = NULL;
727 object->fieldUnit.fieldFlags = flags;
728 object->fieldUnit.bitOffset = bitOffset;
729 object->fieldUnit.bitSize = bitSize;
730 object->type = AML_FIELD_UNIT;
731 return 0;
732}
733
735 uint64_t bankValue, aml_field_flags_t flags, aml_bit_size_t bitOffset, aml_bit_size_t bitSize)
736{
737 if (object == NULL || opregion == NULL || bank == NULL || bitSize == 0)
738 {
739 errno = EINVAL;
740 return ERR;
741 }
742
743 aml_object_t* bankValueObj = aml_object_new();
744 if (bankValueObj == NULL)
745 {
746 return ERR;
747 }
748 UNREF_DEFER(bankValueObj);
749 if (aml_integer_set(bankValueObj, bankValue) == ERR)
750 {
751 return ERR;
752 }
753
754 if (aml_object_check_clear(object) == ERR)
755 {
756 return ERR;
757 }
758
759 object->fieldUnit.fieldType = AML_FIELD_UNIT_BANK_FIELD;
760 object->fieldUnit.index = NULL;
761 object->fieldUnit.data = NULL;
762 object->fieldUnit.bankValue = REF(bankValueObj);
763 object->fieldUnit.bank = REF(bank);
764 object->fieldUnit.opregion = REF(opregion);
765 object->fieldUnit.fieldFlags = flags;
766 object->fieldUnit.bitOffset = bitOffset;
767 object->fieldUnit.bitSize = bitSize;
768 object->type = AML_FIELD_UNIT;
769 return 0;
770}
771
773{
774 if (object == NULL)
775 {
776 errno = EINVAL;
777 return ERR;
778 }
779
780 if (object->type == AML_INTEGER)
781 {
782 object->integer.value = value & aml_integer_ones();
783 return 0;
784 }
785
786 if (aml_object_check_clear(object) == ERR)
787 {
788 return ERR;
789 }
790
791 object->integer.value = value & aml_integer_ones();
792 object->type = AML_INTEGER;
793 return 0;
794}
795
797 aml_method_implementation_t implementation)
798{
799 if (object == NULL || ((start == 0 || end == 0 || start > end) && implementation == NULL))
800 {
801 errno = EINVAL;
802 return ERR;
803 }
804
805 if (aml_object_check_clear(object) == ERR)
806 {
807 return ERR;
808 }
809
810 object->method.implementation = implementation;
811 object->method.methodFlags = flags;
812 object->method.start = start;
813 object->method.end = end;
815 object->type = AML_METHOD;
816 return 0;
817}
818
819static inline aml_method_t* aml_method_find_recursive(aml_object_t* current, const uint8_t* addr)
820{
821 if (current == NULL || addr == NULL)
822 {
823 return NULL;
824 }
825
826 if (current->type == AML_METHOD)
827 {
828 if (addr >= current->method.start && addr < current->method.end)
829 {
830 return REF(&current->method);
831 }
832 }
833
834 if (current->type & AML_NAMESPACES)
835 {
836 aml_object_t* child = NULL;
837 LIST_FOR_EACH(child, &current->children, siblingsEntry)
838 {
839 aml_method_t* result = aml_method_find_recursive(child, addr);
840 if (result != NULL)
841 {
842 // Check for methods in methods
843 aml_method_t* methodInMethod =
845 if (methodInMethod != NULL)
846 {
847 UNREF(result);
848 return methodInMethod; // Transfer ownership
849 }
850 return result; // Transfer ownership
851 }
852 }
853 }
854
855 return NULL;
856}
857
859{
860 if (addr == NULL)
861 {
862 errno = EINVAL;
863 return NULL;
864 }
865
867 if (root == NULL)
868 {
869 return NULL;
870 }
871 UNREF_DEFER(root);
872
873 return aml_method_find_recursive(root, addr); // Transfer ownership
874}
875
877{
878 if (object == NULL || syncLevel > 15)
879 {
880 errno = EINVAL;
881 return ERR;
882 }
883
884 if (aml_object_check_clear(object) == ERR)
885 {
886 return ERR;
887 }
888
889 object->mutex.syncLevel = syncLevel;
890 aml_mutex_id_init(&object->mutex.mutex);
891 object->type = AML_MUTEX;
892 return 0;
893}
894
896{
897 if (object == NULL || target == NULL)
898 {
899 errno = EINVAL;
900 return ERR;
901 }
902
903 if (object->type == AML_OBJECT_REFERENCE)
904 {
906 object->objectReference.target = REF(target);
907 return 0;
908 }
909
910 if (aml_object_check_clear(object) == ERR)
911 {
912 return ERR;
913 }
914
915 object->objectReference.target = REF(target);
916 object->type = AML_OBJECT_REFERENCE;
917 return 0;
918}
919
921{
922 if (object == NULL || length == 0)
923 {
924 errno = EINVAL;
925 return ERR;
926 }
927
928 if (aml_object_check_clear(object) == ERR)
929 {
930 return ERR;
931 }
932
933 object->opregion.space = space;
934 object->opregion.offset = offset;
935 object->opregion.length = length;
936 object->type = AML_OPERATION_REGION;
937 return 0;
938}
939
941{
942 if (object == NULL)
943 {
944 errno = EINVAL;
945 return ERR;
946 }
947
948 if (aml_object_check_clear(object) == ERR)
949 {
950 return ERR;
951 }
952
953 if (length <= AML_SMALL_PACKAGE_SIZE)
954 {
955 object->package.elements = object->package.smallElements;
956 }
957 else
958 {
959 object->package.elements = malloc(sizeof(aml_object_t*) * length);
960 if (object->package.elements == NULL)
961 {
962 return ERR;
963 }
964 }
965 memset(object->package.elements, 0, sizeof(aml_object_t*) * length);
966
967 for (uint64_t i = 0; i < length; i++)
968 {
969 object->package.elements[i] = aml_object_new();
970 if (object->package.elements[i] == NULL)
971 {
972 for (uint64_t j = 0; j < i; j++)
973 {
974 UNREF(object->package.elements[j]);
975 }
976 free(object->package.elements);
977 object->package.elements = NULL;
978 return ERR;
979 }
980 }
981 object->package.length = length;
982 object->type = AML_PACKAGE;
983 return 0;
984}
985
987 aml_resource_order_t resourceOrder)
988{
989 if (object == NULL)
990 {
991 errno = EINVAL;
992 return ERR;
993 }
994
995 if (aml_object_check_clear(object) == ERR)
996 {
997 return ERR;
998 }
999
1000 object->powerResource.systemLevel = systemLevel;
1001 object->powerResource.resourceOrder = resourceOrder;
1002 object->type = AML_POWER_RESOURCE;
1003 return 0;
1004}
1005
1007{
1008 if (object == NULL)
1009 {
1010 errno = EINVAL;
1011 return ERR;
1012 }
1013
1014 if (aml_object_check_clear(object) == ERR)
1015 {
1016 return ERR;
1017 }
1018
1019 object->processor.procId = procId;
1020 object->processor.pblkAddr = pblkAddr;
1021 object->processor.pblkLen = pblkLen;
1022 object->type = AML_PROCESSOR;
1023 return 0;
1024}
1025
1027{
1028 if (object == NULL)
1029 {
1030 errno = EINVAL;
1031 return ERR;
1032 }
1033
1034 if (object->type == AML_STRING)
1035 {
1036 if (aml_string_resize(&object->string, length) == ERR)
1037 {
1038 return ERR;
1039 }
1040 }
1041 else
1042 {
1043 if (aml_object_check_clear(object) == ERR)
1044 {
1045 return ERR;
1046 }
1047
1048 if (length <= AML_SMALL_STRING_SIZE)
1049 {
1050 object->string.content = object->string.smallString;
1052 }
1053 else
1054 {
1055 object->string.content = calloc(1, length + 1);
1056 if (object->string.content == NULL)
1057 {
1058 return ERR;
1059 }
1060 }
1061 object->string.length = length;
1062 }
1063
1064 object->type = AML_STRING;
1065 return 0;
1066}
1067
1068uint64_t aml_string_set(aml_object_t* object, const char* str)
1069{
1070 if (object == NULL || str == NULL)
1071 {
1072 errno = EINVAL;
1073 return ERR;
1074 }
1075
1076 size_t length = strlen(str);
1077 if (aml_string_set_empty(object, length) == ERR)
1078 {
1079 return ERR;
1080 }
1081 memcpy(object->string.content, str, length);
1082 return 0;
1083}
1084
1086{
1087 if (string == NULL)
1088 {
1089 errno = EINVAL;
1090 return ERR;
1091 }
1092
1093 if (newLength == string->length)
1094 {
1095 return 0;
1096 }
1097
1098 if (newLength <= AML_SMALL_STRING_SIZE)
1099 {
1100 if (string->content != string->smallString)
1101 {
1102 memcpy(string->smallString, string->content, MIN(string->length, newLength));
1103 free(string->content);
1104 string->content = string->smallString;
1105 }
1106 string->length = newLength;
1107 string->smallString[newLength] = '\0';
1108 return 0;
1109 }
1110
1111 if (string->content == string->smallString)
1112 {
1113 string->content = calloc(1, newLength + 1);
1114 if (string->content == NULL)
1115 {
1116 return ERR;
1117 }
1118 memcpy(string->content, string->smallString, MIN(string->length, newLength));
1119 }
1120 else
1121 {
1122 char* newContent = realloc(string->content, newLength + 1);
1123 if (newContent == NULL)
1124 {
1125 return ERR;
1126 }
1127 string->content = newContent;
1128 memset(&string->content[string->length], 0, newLength - string->length + 1);
1129 }
1130
1131 string->length = newLength;
1132 string->content[newLength] = '\0';
1133 return 0;
1134}
1135
1137{
1138 if (object == NULL)
1139 {
1140 errno = EINVAL;
1141 return ERR;
1142 }
1143
1144 if (aml_object_check_clear(object) == ERR)
1145 {
1146 return ERR;
1147 }
1148
1149 object->type = AML_THERMAL_ZONE;
1150 return 0;
1151}
1152
1154{
1155 if (object == NULL || target == NULL)
1156 {
1157 errno = EINVAL;
1158 return ERR;
1159 }
1160
1161 if (aml_object_check_clear(object) == ERR)
1162 {
1163 return ERR;
1164 }
1165
1166 object->alias.target = REF(target);
1167 object->type = AML_ALIAS;
1168 return 0;
1169}
1170
1172{
1173 if (alias == NULL)
1174 {
1175 return NULL;
1176 }
1177
1178 aml_object_t* current = REF(CONTAINER_OF(alias, aml_object_t, alias));
1179 while (current != NULL && current->type == AML_ALIAS)
1180 {
1181 aml_object_t* next = REF(current->alias.target);
1182 if (next == NULL)
1183 {
1184 return NULL;
1185 }
1186 UNREF(current);
1187 current = next;
1188 }
1189 return current;
1190}
1191
1194{
1195 if (object == NULL || nameString == NULL || callback == NULL)
1196 {
1197 errno = EINVAL;
1198 return ERR;
1199 }
1200
1201 if (aml_object_check_clear(object) == ERR)
1202 {
1203 return ERR;
1204 }
1205
1206 object->unresolved.nameString = *nameString;
1207 object->unresolved.from = REF(from);
1208 object->unresolved.callback = callback;
1209 object->type = AML_UNRESOLVED;
1210
1212 {
1213 object->type = AML_UNINITIALIZED;
1214 return ERR;
1215 }
1216 return 0;
1217}
1218
1220{
1221 if (object == NULL)
1222 {
1223 errno = EINVAL;
1224 return ERR;
1225 }
1226
1227 if (aml_object_check_clear(object) == ERR)
1228 {
1229 return ERR;
1230 }
1231
1232 object->type = AML_PREDEFINED_SCOPE;
1233 return 0;
1234}
1235
1237{
1238 if (object == NULL)
1239 {
1240 errno = EINVAL;
1241 return ERR;
1242 }
1243
1244 if (aml_object_check_clear(object) == ERR)
1245 {
1246 return ERR;
1247 }
1248
1249 if (value == NULL)
1250 {
1251 object->arg.value = NULL;
1252 object->type = AML_ARG;
1253 return 0;
1254 }
1255
1256 object->arg.value = REF(value);
1257 object->type = AML_ARG;
1258 return 0;
1259}
1260
1262{
1263 if (object == NULL)
1264 {
1265 errno = EINVAL;
1266 return ERR;
1267 }
1268
1269 if (aml_object_check_clear(object) == ERR)
1270 {
1271 return ERR;
1272 }
1273
1274 object->local.value = aml_object_new();
1275 if (object->local.value == NULL)
1276 {
1277 return ERR;
1278 }
1279 object->type = AML_LOCAL;
1280 return 0;
1281}
static fd_t data
Definition dwm.c:21
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:266
void map_entry_init(map_entry_t *entry)
Initialize a map entry.
Definition map.c:71
#define UNREF_DEFER(ptr)
RAII-style cleanup for scoped references.
Definition ref.h:54
static void ref_init(ref_t *ref, void *free)
Initialize a reference counter.
Definition ref.h:92
#define REF(ptr)
Increment reference count.
Definition ref.h:65
#define UNREF(ptr)
Decrement reference count.
Definition ref.h:80
#define EINVAL
Invalid argument.
Definition errno.h:142
#define errno
Error number variable.
Definition errno.h:27
#define LIST_FOR_EACH(elem, list, member)
Iterates over a list.
Definition list.h:63
static list_entry_t * list_pop_first(list_t *list)
Pops the first entry from the list.
Definition list.h:375
static uint64_t list_length(list_t *list)
Gets the length of the list.
Definition list.h:246
static void list_push_back(list_t *list, list_entry_t *entry)
Pushes an entry to the end of the list.
Definition list.h:343
#define LIST_CREATE(name)
Creates a list initializer.
Definition list.h:174
#define LIST_FOR_EACH_SAFE(elem, temp, list, member)
Safely iterates over a list, allowing for element removal during iteration.
Definition list.h:79
static bool list_is_empty(list_t *list)
Checks if a list is empty.
Definition list.h:227
static void list_entry_init(list_entry_t *entry)
Initializes a list entry.
Definition list.h:182
static void list_init(list_t *list)
Initializes a list.
Definition list.h:196
#define MIN(x, y)
Definition math.h:16
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
#define CONTAINER_OF(ptr, type, member)
Container of macro.
#define CONTAINER_OF_SAFE(ptr, type, member)
Safe container of macro.
uint64_t aml_bit_size_t
Represents a size in bits within an opregion.
uint8_t aml_proc_id_t
ProcID structure, deprecated in version 6.4 of the ACPI specification.
Definition named.h:151
uint32_t aml_pblk_addr_t
PblkAddr structure, deprecated in version 6.4 of the ACPI specification.
Definition named.h:156
uint8_t aml_system_level_t
SystemLevel structure.
Definition named.h:166
uint8_t aml_pblk_len_t
PblkLen structure, deprecated in version 6.4 of the ACPI specification.
Definition named.h:161
uint8_t aml_sync_level_t
Definition named.h:135
aml_region_space_t
Region Space Encoding.
Definition named.h:30
uint16_t aml_resource_order_t
ResourceOrder structure.
Definition named.h:171
uint8_t aml_integer_bit_size(void) PURE
Get the bit size of an AML integer.
Definition integer.c:27
aml_uint_t aml_integer_ones(void) PURE
Get a mask with all bits set for the current AML integer size.
Definition integer.c:32
uint64_t aml_uint_t
AML Integer type.
Definition integer.h:20
void aml_mutex_id_init(aml_mutex_id_t *mutex)
Create a new mutex and return its id.
Definition mutex.c:84
void aml_mutex_id_deinit(aml_mutex_id_t *mutex)
Destroy the mutex with the given id.
Definition mutex.c:89
#define AML_NAME_TO_STRING(name)
Macro to convert an aml_name_t to a stack allocated string.
Definition namespace.h:129
#define AML_NAME_UNDEFINED
Macro for an undefined name.
Definition namespace.h:121
void aml_namespace_remove(aml_object_t *object)
Remove an object from the namespace heirarchy it was added to.
Definition namespace.c:487
aml_object_t * aml_namespace_get_root(void)
Get the root object of the namespace heirarchy.
Definition namespace.c:149
uint64_t aml_object_reference_set(aml_object_t *object, aml_object_t *target)
Set a object as an ObjectReference to the given target object.
Definition object.c:895
uint64_t aml_buffer_resize(aml_buffer_t *buffer, uint64_t newLength)
Resize a buffer object to the new length.
Definition object.c:490
uint64_t aml_field_unit_bank_field_set(aml_object_t *object, aml_opregion_t *opregion, aml_field_unit_t *bank, uint64_t bankValue, aml_field_flags_t flags, aml_bit_size_t bitOffset, aml_bit_size_t bitSize)
Set a object as a field unit of type BankField.
Definition object.c:734
aml_method_t * aml_method_find(const uint8_t *addr)
Find the method which contains the provided address in its AML bytecode range.
Definition object.c:858
uint64_t aml_method_set(aml_object_t *object, aml_method_flags_t flags, const uint8_t *start, const uint8_t *end, aml_method_implementation_t implementation)
Set a object as a method with the given flags and address range.
Definition object.c:796
uint64_t aml_local_set(aml_object_t *object)
Set a object as a empty local variable.
Definition object.c:1261
uint64_t aml_event_set(aml_object_t *object)
Set a object as an event.
Definition object.c:663
uint64_t aml_device_set(aml_object_t *object)
Set a object as a device or bus.
Definition object.c:645
uint64_t aml_mutex_set(aml_object_t *object, aml_sync_level_t syncLevel)
Set a object as a mutex with the given synchronization level.
Definition object.c:876
uint64_t aml_power_resource_set(aml_object_t *object, aml_system_level_t systemLevel, aml_resource_order_t resourceOrder)
Set a object as a power resource with the given system level and resource order.
Definition object.c:986
uint64_t aml_package_set(aml_object_t *object, uint64_t length)
Set a object as a package with the given number of elements.
Definition object.c:940
#define AML_SMALL_STRING_SIZE
Size of string buffers used for small objects optimization, not including the null terminator.
Definition object.h:37
uint64_t aml_field_unit_index_field_set(aml_object_t *object, aml_field_unit_t *index, aml_field_unit_t *data, aml_field_flags_t flags, aml_bit_size_t bitOffset, aml_bit_size_t bitSize)
Set a object as a field unit of type IndexField.
Definition object.c:707
uint64_t aml_object_count_children(aml_object_t *parent)
Recursively count how many children an object has.
Definition object.c:277
uint64_t aml_field_unit_field_set(aml_object_t *object, aml_opregion_t *opregion, aml_field_flags_t flags, aml_bit_size_t bitOffset, aml_bit_size_t bitSize)
Set a object as a field unit of type Field.
Definition object.c:680
uint64_t aml_thermal_zone_set(aml_object_t *object)
Set a object as a thermal zone.
Definition object.c:1136
aml_object_t * aml_object_new(void)
Allocate a new ACPI object.
Definition object.c:62
uint64_t aml_string_set(aml_object_t *object, const char *str)
Set a object as a string with the given value.
Definition object.c:1068
uint64_t aml_object_set_bits_at(aml_object_t *object, aml_bit_size_t bitOffset, aml_bit_size_t bitSize, uint8_t *data)
Store bits into a object at the specified bit offset and size.
Definition object.c:351
uint64_t aml_alias_set(aml_object_t *object, aml_object_t *target)
Set a object as an alias to the given target object.
Definition object.c:1153
uint64_t aml_arg_set(aml_object_t *object, aml_object_t *value)
Set a object as an argument with the given target object.
Definition object.c:1236
aml_object_t * aml_alias_traverse(aml_alias_t *alias)
Traverse an alias object to get the target object.
Definition object.c:1171
uint64_t aml_predefined_scope_set(aml_object_t *object)
Set a object as a predefined scope with the given name.
Definition object.c:1219
uint64_t aml_buffer_set_empty(aml_object_t *object, uint64_t length)
Set a object as an empty buffer with the given length.
Definition object.c:533
uint64_t aml_buffer_field_set(aml_object_t *object, aml_object_t *target, aml_bit_size_t bitOffset, aml_bit_size_t bitSize)
Set a object as a buffer field with the given buffer, bit offset and bit size.
Definition object.c:594
uint64_t aml_string_set_empty(aml_object_t *object, uint64_t length)
Set a object as an empty string with the given length.
Definition object.c:1026
aml_object_t *(* aml_method_implementation_t)(aml_method_t *method, aml_object_t **args, uint64_t argCount)
Method Implementation function type.
Definition object.h:175
uint64_t aml_debug_object_set(aml_object_t *object)
Set a object as a debug object.
Definition object.c:628
#define AML_OBJECT_ID_NONE
Value for an invalid object id.
Definition object.h:153
void aml_object_clear(aml_object_t *object)
Clear the data of a object, setting its type to AML_UNINITIALIZED.
Definition object.c:96
uint64_t aml_object_get_bits_at(aml_object_t *object, aml_bit_size_t bitOffset, aml_bit_size_t bitSize, uint8_t *out)
Retrieve bits from a object at the specified bit offset and size.
Definition object.c:412
uint64_t aml_object_id_t
Object id type.
Definition object.h:148
uint64_t aml_processor_set(aml_object_t *object, aml_proc_id_t procId, aml_pblk_addr_t pblkAddr, aml_pblk_len_t pblkLen)
Set a object as a processor with the given ProcID, PblkAddr, and PblkLen.
Definition object.c:1006
#define AML_SMALL_BUFFER_SIZE
Size of buffers used for small objects optimization.
Definition object.h:32
uint64_t aml_object_get_total_count(void)
Get the total amount of allocated ACPI objects.
Definition object.c:23
uint64_t aml_integer_set(aml_object_t *object, aml_uint_t value)
Set a object as an integer with the given value and bit width.
Definition object.c:772
uint64_t aml_operation_region_set(aml_object_t *object, aml_region_space_t space, uintptr_t offset, uint32_t length)
Set a object as an operation region with the given space, offset, and length.
Definition object.c:920
uint64_t aml_unresolved_set(aml_object_t *object, const aml_name_string_t *nameString, aml_object_t *from, aml_patch_up_resolve_callback_t callback)
Set a object as an unresolved reference with the given namestring and starting point.
Definition object.c:1192
uint64_t aml_buffer_set(aml_object_t *object, const uint8_t *buffer, uint64_t bytesToCopy, uint64_t length)
Set a object as a buffer with the given content.
Definition object.c:576
uint64_t aml_string_resize(aml_string_t *string, uint64_t newLength)
Resize a string object to the new length.
Definition object.c:1085
#define AML_OBJECT_CACHE_SIZE
Amount of objects to store in the cache before freeing them instead.
Definition object.h:47
#define AML_SMALL_PACKAGE_SIZE
Size of package element arrays used for small objects optimization.
Definition object.h:42
@ AML_UNRESOLVED
Not in the spec, used internally to represent unresolved references.
Definition object.h:88
@ AML_METHOD
Definition object.h:77
@ AML_BUFFER_FIELD
Definition object.h:62
@ AML_PROCESSOR
Definition object.h:83
@ AML_PACKAGE
Definition object.h:81
@ AML_OBJECT_REFERENCE
Definition object.h:79
@ AML_OPERATION_REGION
Definition object.h:80
@ AML_DEBUG_OBJECT
Definition object.h:63
@ AML_STRING
Definition object.h:85
@ AML_ALIAS
Not in the spec, used internally to represent Aliases.
Definition object.h:87
@ AML_ARG
Not in the spec, used internally to represent method arguments.
Definition object.h:90
@ AML_THERMAL_ZONE
Definition object.h:86
@ AML_FIELD_UNIT
Definition object.h:66
@ AML_POWER_RESOURCE
Definition object.h:82
@ AML_EVENT
Definition object.h:65
@ AML_DEVICE
Definition object.h:64
@ AML_NAMESPACES
Definition object.h:109
@ AML_MUTEX
Definition object.h:78
@ AML_LOCAL
Not in the spec, used internally to represent method local variables.
Definition object.h:91
@ AML_INTEGER
Definition object.h:67
@ AML_PREDEFINED_SCOPE
Not in the spec, used internally to represent _SB, _GPE, etc.
Definition object.h:89
@ AML_UNINITIALIZED
Definition object.h:60
@ AML_BUFFER
Definition object.h:61
@ AML_FIELD_UNIT_BANK_FIELD
Definition object.h:168
@ AML_FIELD_UNIT_FIELD
Definition object.h:166
@ AML_FIELD_UNIT_INDEX_FIELD
Definition object.h:167
@ AML_OBJECT_ROOT
Is the root object.
Definition object.h:127
@ AML_OBJECT_NAMED
Appears in the namespace tree. Will be set in aml_object_add().
Definition object.h:128
@ AML_OBJECT_NONE
No flags.
Definition object.h:126
uint64_t aml_patch_up_add_unresolved(aml_unresolved_t *unresolved)
Adds a unresolved reference to the global list.
Definition patch_up.c:21
void aml_patch_up_remove_unresolved(aml_unresolved_t *unresolved)
Removes an unresolved reference from the global list.
Definition patch_up.c:41
uint64_t(* aml_patch_up_resolve_callback_t)(aml_state_t *state, aml_object_t *match, aml_object_t *unresolved)
Callback type for resolving a forward reference.
Definition patch_up.h:25
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
static aml_method_t * aml_method_find_recursive(aml_object_t *current, const uint8_t *addr)
Definition object.c:819
static aml_object_id_t newObjectId
Definition object.c:21
static uint64_t totalObjects
Definition object.c:16
static uint64_t aml_object_check_clear(aml_object_t *object)
Definition object.c:474
static void aml_copy_bits(uint8_t *dst, uint64_t dstOffset, const uint8_t *src, uint64_t srcOffset, uint64_t bitCount)
Definition object.c:324
static list_t objectsCache
Definition object.c:19
static void aml_object_free(aml_object_t *object)
Definition object.c:28
static const path_flag_t flags[]
Definition path.c:42
static void start()
Definition main.c:542
static atomic_long next
Definition main.c:11
static atomic_long count
Definition main.c:10
__UINT32_TYPE__ uint32_t
Definition stdint.h:15
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
__UINTPTR_TYPE__ uintptr_t
Definition stdint.h:43
_PUBLIC void * realloc(void *ptr, size_t size)
Definition realloc.c:13
_PUBLIC void * calloc(size_t nmemb, size_t size)
Definition calloc.c:6
_PUBLIC void * malloc(size_t size)
Definition malloc.c:5
_PUBLIC void free(void *ptr)
Definition free.c:11
_PUBLIC void * memcpy(void *_RESTRICT s1, const void *_RESTRICT s2, size_t n)
Definition memcpy.c:61
_PUBLIC size_t strlen(const char *s)
Definition strlen.c:3
_PUBLIC void * memset(void *s, int c, size_t n)
Definition memset.c:4
Data for an alias object.
Definition object.h:402
aml_object_t * target
Definition object.h:404
aml_object_t * value
The object that was passed as the argument.
Definition object.h:429
aml_object_t * target
Definition object.h:227
Data for a buffer object.
Definition object.h:213
uint64_t length
Definition object.h:216
uint8_t * content
Definition object.h:215
acpi_device_cfg_t * cfg
Definition object.h:249
FieldFlags structure.
Definition named.h:86
Data for a field unit object.
Definition object.h:268
aml_opregion_t * opregion
Used for Field and BankField.
Definition object.h:275
aml_object_t * bankValue
Used for BankField.
Definition object.h:273
aml_field_unit_t * bank
Used for BankField.
Definition object.h:274
aml_field_unit_type_t fieldType
The type of field unit.
Definition object.h:270
aml_field_unit_t * index
Used for IndexField.
Definition object.h:271
aml_field_unit_t * data
Used for IndexField.
Definition object.h:272
aml_object_t * value
The value of the local variable.
Definition object.h:439
MethodFlags structure.
Definition named.h:142
Data for a method object.
Definition object.h:306
aml_mutex_id_t mutex
Definition object.h:316
const uint8_t * start
Definition object.h:314
aml_mutex_id_t mutex
Definition object.h:327
A NameString structure.
Definition name.h:87
aml_object_t * target
Definition object.h:337
ACPI object.
Definition object.h:447
aml_package_t package
Definition object.h:464
aml_field_unit_t fieldUnit
Definition object.h:457
aml_unresolved_t unresolved
Definition object.h:470
aml_alias_t alias
Definition object.h:469
aml_buffer_t buffer
Definition object.h:453
aml_method_t method
Definition object.h:460
aml_string_t string
Definition object.h:467
aml_mutex_t mutex
Definition object.h:461
aml_local_t local
Definition object.h:472
aml_object_reference_t objectReference
Definition object.h:462
aml_device_t device
Definition object.h:455
aml_buffer_field_t bufferField
Definition object.h:454
aml_arg_t arg
Definition object.h:471
Data for an operation region object.
Definition object.h:345
aml_object_t ** elements
Definition object.h:361
uint64_t length
Definition object.h:362
Data for a string object.
Definition object.h:390
uint64_t length
Definition object.h:393
char smallString[AML_SMALL_STRING_SIZE+1]
Used for small object optimization.
Definition object.h:394
char * content
Definition object.h:392
aml_object_t * from
The object to start the search from when resolving the reference.
Definition object.h:415
aml_name_string_t nameString
The NameString representing the path to the target object.
Definition object.h:414
A doubly linked list.
Definition list.h:49