#uACPI - a portable and easy-to-integrate ACPI implementation
1 messages · Page 5 of 1
the MSDM table contains it
what in the actual
in the acpi tables
fuck
how to make millions:
- get thousands of acpi table dumps somehow
- extract all ms keys
- sell on cdkeys or smthin
- profit ???
possibly not legal
also some linux repo has a bunch of acpi table dumps
from 100s of computers
I don't think it works for keys that are linked to microsoft accounts
mine is also, but I meant that I don't think it can be used if its linked
@zenith crescent whats the acpica error for that pc?
[ 0.621519] ACPI BIOS Error (bug): Could not resolve symbol [\_SB.CHRG], AE_NOT_FOUND (20230628/psargs-330)
[ 0.621545] ACPI Error: Aborting method \PNOT due to previous error (AE_NOT_FOUND) (20230628/psparse-529)
[ 0.621563] ACPI Error: Aborting method \_SB.PCI0.LPCB.EC0._REG due to previous error (AE_NOT_FOUND) (20230628/psparse-529)
i also get acpi errors
with my laptop
using acpica
idk if its related but
is smthing
gobless ```
[ 1.086734] ACPI Error: AE_NOT_FOUND, While resolving a named reference package element - _PR_.P000 (20230628/dspkginit-438)
there is a suspiciously named \_SB_.PLTF.P000 though :^)
i think acpica throws an error on my hardware too?
but i cant remember
and i cant get into my debian install because i have mismatched kernel and nvidia modules 
Yeah undefined references in some of these is a classic
Of firmware dev brain damage
I'll do that once I test managarm on my test PCs
Thanks!
Thanks
Why does so much stuff around acpi during system initialization fail on some pcs? For example, on linux according to dmesg, it complains about symbols that aren’t resolvable (note: acpi bios error (bug)), complains about invalid values like thermal threshold (here it notes: Firmware Bug), sometimes it fails to parse AML opcodes because they seem to be invalid, duplicate or non existent, …
Is this really just to blame on awful firmware (devs)
Yeah

Those are basically untested code paths for the most part and none of them are critical
Since aml is just a loosely typed language you can compile completely broken code
Similar to python
And the error won't uncover itself until that code runs
its kinda weird if there are errors in the top level namespace tho, like in one of the test blobs there is an out of bounds createqwordfield and then it just stops the namespace load there
but ig because its very much at the end it doesn't really cause that much problems
yeah that makes sense
||just put that burden on kernel devs||
Which blob?
Thats because NT just ignores the bounds until the field is accessed
So on nt thats not an error
Yeah
can aml ask to load more aml? or is that not how it works
notebook_avell_high_performance_c75_c75_rtx_muv-g1750_rtx_muv_b4cc55e338b5.aml line 54359
It can load arbitary buffers as aml
So yes
fun!
If kernel says it supports it aml just loads extra crap dynamically
Probably not a problem in uACPI since load aborts dont abort initialization entirely, but I check bounds at creation time as well
Which is technically not nt compatible
is it possible that uacpi is trying to free a null address, or is it more a vmm problem?
free(null) is legal c
Should i just ignore that? Because my vmm is shitting itself when uacpi frees that
yes
Yes, all the time

I thought I had a comment there
Maybe not
Btw @stable topaz I saw u have some beginnings of rust bindings, would be really nice to upstream that eventually if you get that done
looking at their crate, it's probably a better idea to use something like bindgen to automatically generate these bindings instead of manually writing them
eliminates the chance of you accidentally getting something wrong and is much faster to update, then you could write a proper rust wrapper around that
i wanted to do it as a poc for my os, but i can do it the right way so i can upstream it
@fiery turtle btw since you mentioned that you could add zig support, would you like to have a zig wrapper in-tree? or do you want something similar to uacpi.cmake/meson.build to collect source files so something else can do the wrapping?
either way i'll look into wrapping the C api so it's more ziggy
i can maintain it out-of-tree with the addition of an in-tree build.zig that will do the source file meme so you don't have to deal with maintaining zig code
In tree is probably better so that we can verify that it doesn't go out of date?
If u mean like the bindings
well so there is basically 2 ways to consume uacpi from zig right now:
- translate-c: compiler generates raw api bindings, not very nice to use from zig code
- a proper, hand written wrapper: it uses the compiler generated bindings to provide a more user friendy interface, so wrapping raw pointers and making it all feel like proper zig code
the first one you won't really have to do anything, as it's done by the compiler, ideally you would only provide a build.zig file similar to uacpi.cmake/meson.build so users can easily add the source files to the compilation unit, ideally in tree so you can update it so downstream users dont have to worry about updating the source list manually
the second one is a bit more work, in addition to maintaining the source list you would also need to worry about the standard library changes/compiler changes (keep in mind zig isn't 1.0 lol)
it actually is kinda useful
Well that one definitely sounds nicer, but yeah I dont know who would maintain it in case of compiler changes etc, because I know nothing about zig
yeah thats why i suggested out of tree since then i could maintain it
but if you want it in tree we can arrange that
You could maintain in tree as well tho but if out of tree works better than sure thats fine as well!
i do think in tree would be better, just because of the added benefit of you being able to sync small changes between build systems
Yeah, and we could also add a GitHub actions ci check that it builds and stuff
yep absolutely
i'm thinking of somehow providing a ziggy way of handling kernel api
that actually sounds rather hard because of the callouts
my idea currently is to provide default kernel api that returns everything as unimplemented and having the user export an instance of an API struct from the root package
you can export symbols comptime, can't you
so all you need is @import("root").uacpi_hooks and if comptime (has feature) export()
yeah of course you can, just need a bit of asm :^)
or import memes
i was thinking of providing the kernel api exports myself and just calling the user provided functions from them
makes for a better compile time error when a new kernel api gets added
instead of a linker error you get a missing field or something
well yeah
wait does uacpi use weak symbols?
nope
also i want the callbacks to accept my zigified wrappers where needed
i dont think there is any api that actually accepts a node or whatever
but i do want to wrap around that as well
im currently trying to figure out how the module args work so i dont need to export two modules, one regular uacpi and one reduced hw
ideally the user can specify that somehow
also printf and some string.h functions... idk what to do about those either lol
wait uacpi needs printf?
yeah
what the actual fuck
also memset and friends
but i think maybe i can get zig to link in compiler-rt for that?
idk
they have to be provided anyway
nope
export fn strlen(s: [*]const c_char) callconv(.C) usize {
export fn strcmp(s1: [*]const c_char, s2: [*]const c_char) callconv(.C) i32 {
export fn strnlen(s: [*]const c_char, maxlen: usize) callconv(.C) usize {
export fn strncmp(s1: [*]const c_char, s2: [*]const c_char, n: usize) callconv(.C) i32 {
yeah those no
imo uacpi should just not depend on these things like what are they even used for
like memcpy/set/cmp is fine
but the other ones why
because most kernels should have them anyway, idk
not really
slightly annoying for ~C(++)
zig ones won't
and C++ ones might not either
idk i like writing c++ that uses as few null terminated strings as possible
also lol strcmp and strncmp have one use each
memmove has more tbf
all in one function
and strlen and strnlen have two references each
also not snprintf
i mean every time i implemented printf i also made an snprintf
and also vsnprintf
all the other ones are just built on top of that one
that of course assumes you implement printf
which again isn't necessarily the case
even in C kernels
and honestly for this level of use just implement your own "append int to buffer" func
its like 5 lines of code
Logging is built around printf, tons of aml conversion stuff needs snprintf
It wasn't built with zig in mind
Its a c library
But yeah shipping own printf would be nice
If its replaceable especially
nanoprintf is nice, and it's 0bsd
actually i realized i can make zig fetch nanoprintf for me and it doesnt look like it'll be too bad
Yeah thats the first thing I recommend to people that complain
for logging, fair enough
but all the aml conversion stuff only needs numbers afaict
also it's not about that, it's about like
it's a pretty weird and rather annoying assumption to make
source/interpreter.c: repr_len = uacpi_snprintf(
source/interpreter.c- int_buf, sizeof(int_buf),
source/interpreter.c- is_hex ? "%"UACPI_PRIX64 : "%"UACPI_PRIu64,
--
source/interpreter.c: repr_len = uacpi_snprintf(
source/interpreter.c- int_buf, sizeof(int_buf),
source/interpreter.c- is_hex ? "0x%02X" : "%d",
--
source/interpreter.c: size = uacpi_snprintf(int_buf, sizeof(int_buf), "%"UACPI_PRIx64,
source/interpreter.c- arg1->integer);
source/interpreter.c- if (size < 0)
--
source/utilities.c: uacpi_snprintf(
source/utilities.c- id_string->value, CLS_REPR_SIZE, "%02X%02X%02X",
source/utilities.c- class_codes[0], class_codes[1], class_codes[2]
--
source/utilities.c: size = uacpi_snprintf(UACPI_NULL, 0, "%"UACPI_PRIu64, obj->integer) + 1;
source/utilities.c- }
source/utilities.c-
--
source/utilities.c: uacpi_snprintf(
source/utilities.c- id_string->value, id_string->size, "%"UACPI_PRIu64, obj->integer
source/utilities.c- );
what assumption
no one assumes it exists
its a requirement that you implement it if you dont have one
at least for now
since its a C library (or at least was built as a C library initially) its pretty fair to assume a printf would already exist
since there are people using other languages it makes sense to try an require as little as possible
thats why going forward id like to ship own printf by default with an option to override it
that would be amazing if uacpi could just ship with nanoprintf or something by default, and if you have your own printf then you can define something that makes uacpi not compile nanoprintf
oh yeah those too
ideally the stdlib.h header goes away with more atomic overrides if the client wishes to do so
and then you would do like #define uacpi_override_strncmp etc
in that you don't assume a compiler or like standard header
but then you also pull in an osdep for strcmp which you use literally once
right, i dont see anything contradictory here
it's weird
what would be the not weird thing?
just implement your own strcmp for the literal one call site?
and then ill add usage 2
then usage 3
then move it to osdep
?
or keep using my impl?
or just don't move it to an osdep?
it's not like it's something that talks to hardware
or is os-specific in any way
its signficant enough to have an optimized implementation in something like linux
why would i force my crappy implementation
its 3 lines of code, just write it yourself
same goes for snprintf and other helpers
also snprintf is like
thats why i said ideally i ship my own but add an option to override it
you want precise outputs
it just wasnt the focus of the library at the early stages of development
fair enough yeah
I agree
relying on that to produce consistent output between kernels is probably not ideal
i already did that for strtoull btw, initially it was a requirement as well
right now there's an internal more cut down version
also what i didnt like about shipping own printf is like logging helpers get transformed into either
- write one char at a time
- write a string
to do the latter you have to have the buffer somewhere
so that either has to be preallocated (so must be lock guarded), stored on the stack (so waste stack space), or dynamically allocated (slow af)
yeah that's more understandable
that will have to be tunable as well i guess
so that kernels with builtin printf get the printf log callbacks
others just get one of those two
i have an on-stack buffer too
wtf is that lmao
the on-stack is the most common approach
how did i type a 0x7f
you could also go char[64] and flush in segments
oh yeah
oh god i have cursed idea
using recursion to allocate multiple stack segments
ok ok _alloca(snprintf) for msvc
what the fuck
thats
still not standard
and also that has a much slower slow path
the recursive approach is at least standard lmao
anyway fixed size buffer should do the trick probably
128 bytes is unlikely to cause a stack overflow
and if your kernel doesnt have a printf it probably uses something other than C and at that point already consumes tons of stack space anyway
you can just guarantee that you cant overflow
nah
other languages can be efficient too
how?
yeah thats just because its a shitty language :^)
uacpi_kernel_stack_space_left() 
void append(char* bufstart, int* buflen, char c) {
if (*buflen == 128) (*buflen)--;
bufstart[(*buflen)++] = c;
}
or alternatively
if (bufidx + segment_len < buflen) memcpy() /* fast path */ else /* slow path */
well so like if you are doing append not one character at a time
but in larger segments
you can take the fast path if it cant overflow
and otherwise take the (probably not inlined if you really care about that) slow path
frigg 
(I'm trolling at this point)
lai has a small printf impl (written by yours truly) you could maybe take :^)
This is what I call peak NT compatibility:
--- a/include/uacpi/types.h
+++ b/include/uacpi/types.h
@@ -96,6 +96,7 @@ typedef struct uacpi_buffer_field {
uacpi_size bit_index;
uacpi_u32 bit_length;
uacpi_bool force_buffer;
+ uacpi_bool out_of_bounds;
} uacpi_buffer_field;
typedef struct uacpi_buffer_index {
diff --git a/source/interpreter.c b/source/interpreter.c
index 7b08ca6..f532ade 100644
--- a/source/interpreter.c
+++ b/source/interpreter.c
@@ -3817,12 +3817,12 @@ static uacpi_status handle_create_buffer_field(struct execution_context *ctx)
if (uacpi_unlikely((field->bit_index + field->bit_length) >
src_buf->size * 8)) {
- uacpi_error(
+ uacpi_warn(
"Invalid buffer field: bits [%zu..%zu], buffer size is %zu bytes\n",
field->bit_index, field->bit_index + field->bit_length,
src_buf->size
);
- return UACPI_STATUS_AML_OUT_OF_BOUNDS_INDEX;
+ field->out_of_bounds = UACPI_TRUE;
}
field->backing = src_buf;
@@ -4211,6 +4211,8 @@ static uacpi_status handle_inc_dec(struct execution_context *ctx)
if (uacpi_unlikely_error(ret))
return ret;
} else {
+ if (uacpi_unlikely(src->buffer_field.out_of_bounds))
+ return UACPI_STATUS_AML_OUT_OF_BOUNDS_INDEX;
uacpi_read_buffer_field(&src->buffer_field, &dst->integer);
}
break;
Well I currently use uACPI directly using Zig's @cImport, though a proper binding would be really nice
yep thats part of my plan for an in tree wrapper
it’ll be a lot of wrapping though
im also figuring out the proper way to do everything
I merged all of the fixes, and API constness + got rid of bitfields in public api
also pointer detection so riscv should work now
@left orbit you should probably stop using that PR branch now
i havent merge the global lock stuff yet because there's a lot of controversial choices there that i will need to think about
i mainly wanted it for the bitfield stuff so thank you for that :^)
i'm actually thinking of writing my own zig wrapper too, though i haven't wrote any code for it yet
well i’m just starting out so it’ll be a while until there is something to use, but i hope it won’t be too long
maybe you could join efforts?
Maybe we should create a list of who works on which API wrapper to prevent multiple redundant projects
im all for it if people are willing to maintain those, I can fix it up myself even as long as its not insanely complicated to compile
(if its stored in the main tree somehow)
/home/czapek/source/uacpi-zig/example/zig-cache/o/5d8157b26ae4e1098fb65e53e66d4d88/cimport.h:1:10: error: 'string.h' file not found
#include <string.h>
^```
uhhhhh
what the Heck zig
i'm not even building freestanding or anything? lmao
just a "standard" target
oh i need to tell zig to link in the C library if i want the headers...
on one hand that is smart, but on the other hand fuck zig
i guess i'm gonna have to provide some standard headers for uacpi
well i did that while using uacpi on my zig os
i think im gonna yoink https://github.com/mintsuki/freestanding-headers
it doesn't have inttypes.h though
ok i got the missing headers, when im back from the store i'll implement the missing libc functions, provide a dummy kernel api so it links and put it on github so we can start working on this (if someone wants to contribute)
Nice
hmm uacpi is calling uacpi_kernel_alloc with size=11 but freeing with size=12 
[ 0.011000] [CPU0] debug(acpi): allocation 11 bytes at 0xFFFFA0000021DAD0
[ 0.013000] [CPU0] debug(acpi): allocation 88 bytes at 0xFFFFA0000040B600
[ 0.015000] [CPU0] debug(acpi): freeing 12 bytes at 0xFFFFA0000021DAD0
[ 0.020000] [CPU0] err(gpa): Allocation size 11 bytes does not match free size 12. Allocation: Free:
[ 0.022000] [CPU0] debug(acpi): allocation 16 bytes at 0xFFFFA0000021DAE0```
[ 0.028000] [CPU0] err(debug): 0xFFFFFFFF800C21B3: uacpi_kernel_free at /usr/local/zig/lib/std/mem/Allocator.zig:98
[ 0.028000] [CPU0] err(debug): 0xFFFFFFFF8001D02D: uacpi_free_dynamic_string at kernel/./uacpi/source/utilities.c:1208
[ 0.028000] [CPU0] err(debug): 0xFFFFFFFF8005B615: uacpi_free_absolute_path at kernel/./uacpi/source/namespace.c:550```
oh my god its my shitty str(n)len i think
YUP!
my bad
works perfectly fine now if i don't return the wrong length...
Yeah I have tests for verifying sizes
is it normal on qemu that uacpi sometimes gives me this warning and error:
warn unsupported GAS access size 128
error unable to create FADT GPE block 0: unimplemented
it sometimes doesn't happen and i don't know why
nope not normal
you're probably returning an incorrectly mapped pointer
or corrupting the memory
This is how ACPICA solves the need for PRIu64 macros:
/*
* printf() format helper. This macro is a workaround for the difficulties
* with emitting 64-bit integers and 64-bit pointers with the same code
* for both 32-bit and 64-bit hosts.
*/
#define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i), ACPI_LODWORD(i)
idk man lol
whatever I guess, this simplifies my printf implementation
ill do this too
Also I'm deleting the platform/stdlib.h header in favor of platform/libc.h
this is all its going to contain
no more nanoprintf or random header imports needed
ill try to solve the popcount issue as well
@loud ice
and also @left orbit
neat
now to implement all of those..
okay did everything but printf
noticably slower but whatever
now printf
i'll also make the printf-style-kernel-log optional
something like UACPI_PLAIN_LOGGING
if thats enabled it will just pass a string to the log calback
and vlog callback will disappear
or actually maybe the default should be reversed
#ifndef UACPI_FORMATTED_LOGGING
void uacpi_kernel_log(enum uacpi_log_level, const uacpi_char*);
#else
UACPI_PRINTF_DECL(2, 3)
void uacpi_kernel_log(enum uacpi_log_level, const uacpi_char*, ...);
void uacpi_kernel_vlog(enum uacpi_log_level, const uacpi_char*, uacpi_va_list);
#endif
how the fuck do u emulate PRIu64 with two integers...
i dont think u can even
oh wait, i think precision of 0 works
yay printf("%.0X%.0X\n", (unsigned)(val >> 32), (unsigned)val); does what i want
importing mem{cpy,set,cmp} should probably be the default
but the rest no
100%
I have complete implementations of all of them chilling here if you need them: https://github.com/badgeteam/BadgerOS/blob/main/kernel/src/badgelib/badge_strings.c
It even does multi-word copy optimizations
Yeah probably, ill let the user decide tho
I cant make it default because I have to assume a specific header, at which point you have to make an override file so it’s even more annoying
Or I can assume default signature but that's just dirty
Is your os riscv only?
Thats interesting
Currently yes
I made an effort to still separare CPU-specific code into it's own folder so it may be ported at a later date.
But the target chip is RISC-V and of course so will be the OS.
Why that chip specifically?
TL;DR: Espressif sponsors us (as in Badge.team) and they give us the new ESP chips in exchange for us making them part of the official electronic event badge for a camp with ~3000 attendees.
https://why2025.org/ is the next camp
Oh cool
Very
You actually get paid for your os
Oh
oh wow
So yeah if you have spare time for OSDEV and want something valuable on your CV, hit me up :P
Im sorry I tried reading this but I dont understand what this event is about
What are electronic event badges
dont ask stupid questions like "why"
This camp is the next one in a series of quadrennial hacker camps in the Netherlands. Since 2017, the event has official "badges" made by, fittingly, Badge.team. These badges can show your name, but also run apps.
The apps can be games, they can be a real GPS map, they can be a talks schedule, whatever you want really.
let me get you a picture, hang on
Ported printf from hyper and adapted for uACPI
Seems to work great
now uACPI no longer depends on a single function from libc besides kernel_api.h by default
should greately simplify interop with other languages
and just overall make porting less annoying
This should also greately simplify language interop
im also considering making log level a static prefix behind a define
so that there isnt any extra annoying work to append it
i actually like that it's passed in because i can forward it to zig's standard logging
im curious why does zig standard logging need uacpi log level?
the integer values can probably be cast directly to those of the zig standard library and mean the same thing
what oberrow said, except i do the mapping explicitly since i map UACPI_LOG_TRACE (or whatever the log level is called) to the debug log level, but i basically just call the equivalent log function for each uacpi log level
const message = buffer[0..length];
switch (level) {
C.UACPI_LOG_DEBUG, C.UACPI_LOG_TRACE => logger.debug("{s}", .{message}),
C.UACPI_LOG_INFO => logger.info("{s}", .{message}),
C.UACPI_LOG_WARN => logger.warn("{s}", .{message}),
C.UACPI_LOG_ERROR => logger.err("{s}", .{message}),
else => unreachable,
}```
basically what i do
oh i see
but u could also do for example #define UACPI_LOG_TRACE_PREFIX "\x1
and then switch (buffer[0])
(had i actually implemented that)
thats how linux does log levels lmao
that kinda reduces reg usage and stuff ya know
i suppose yeah
but yeah idk
how though? you still need to preserve the arg registers if you have something else in them
even if the function doesn't take that many args
not really critical though imho, you are calling into a kernel api that you have no control over so i don't think that micro-optimization will make a difference
yeah
it makes sense in a more tightly integrated system like linux where they control everything
another thing is this makes the string sort of atomic, as in it already contains the level prefix, u can just memcpy it into the log buffer for example
or log it in one shot
e.g i've seen people do
print(log_level_str);
print(msg)
like i know this is terrible if you have SMP
just have the print function accept multiple things lol
or explicitly take a print lock at the start and then release it after you have done printing everything
anyway ill keep the log_level thing for now, we'll see if the need arises later on
or buffer up all the things and only take the lock for the print path
i used to just print("%s %s", log_level_str, msg); lol
you could always make it a compile time switch :^)
but i feel like that'd be silly
see this is what im talking about lol
what it was already preformatted with that
maybe
i mean on one hand it's nice to let the user pick what they really want
but i can see how that could get annoying one you start adding more things
more and more things to configure
and more and more code to maintain all those alternate code paths in uacpi itself
even if they are trivial like in the log level case
#ifdef UACPI_LOG_WITH_LEVEL
...
#else
...
#endif```
you need another CI variant to make sure nothing breaks and all that
not that good of a solution
I mean it could likely just be made a macro that is switched at compile-time, then the other code wouldn't have to care about it
but yeah its probably not a good idea, idk
oh that is true actually
wdym
yeah i can see this leading to a combinatorial explosion
which im slowly approaching
Ran uACPI against a giant AML blob with --namespace-enumerate with MSVC printf vs my printf
looks like exactly the same output which is amazing
pointer addresses are different but thats kinda expected lol
anyway this should be good to merge now
there's some sysctl you could set to turn off aslr :^)
not on windows but yeah
ime it doesn't freak out but it doesn't always break into the debugger when asan trips on something
mainly when asan in the child exits with an abort instead of a segfault
but maybe that was an ubuntu 22 bug where asan entropy caused the app to segfault every now and again
i wonder if I should delete all the helpers i added to mangarm that only uacpi uses
it has a bunch of useless libc crap now
might be a good idea
the libc headers need a general cleanup as well
because they export symbols that dont exist
for some of them
ill do it on next upstream sync then
👍
my hacked together crappy printf will also go away finally lmao
the one with frigg callbacks
link with /DYNAMICBASE:NO but i dont know if these pointers will help since those are heap addresses
that will just disable load base randomization
merged!
no more dependencies besides kernel_api.h
should be very very easy to port now
based
Thank you!
very nice
and I see the platform-specific stuff in platform/compiler.h got replaced too 😄
The pointer size thing? Yeah
@hasty plinth uhhh
i think this might be leaking memory
np!
Tbh I just assumed uacpi needed lots of memory when I saw the memory usage go up 😅
lol
What's up with that?
BTW, typo: const npk_monotomic_time uptime = npk_get_monotomic_time(); it's supposed to be monotonic
it's one tone
not one tome
Haha cheers, that's probably one spelling mistake that's been propagated everywhere via lsp. Woops.
Probably just writing code too late at night
what's lsp?
i mean like
is it uacpi leaking? or northport
what was going on
Nah it's my kernel
ah
I allocated once, and if that succeeded I zeroed the memory. Then returned memory from a new allocation.
oh LOL
Yeah lol
tbh i wish i had more motivation because i'm stuck on some seemingly trivial boilerplate
Language server protocol, I quite heavily use the completion suggestions
I wanna do a lot of stuff just that I'm not at that stage yet
Thats frustrating
What are you stuck with right now
seemingly trivial boilerplate, right now I need to add a system owned object handle table to my process struct, and then I need to create the IO manager
I don't want to create something like unix, I want to create something akin to NT, basically a fundamentally asynchronous I/O system
I understand a lot of what makes it tick but I also don't understand a lot
(kinda) acpi related question: is there any acpi power state that can put the cpu in a lower power mode than the cpus min mhz?
iirc S2 puts the cpu in idle state, so on a cpu with min mhz = 800 it puts it to 800 mhz
well ones that dont turn it off completely
now i'm having a problem where my whole laptop becomes INSANELY unresponsive when its plugged in
and its fine if not plugged in
S2 can also completely power off the cpu
Don't all sleep states but S0 make it so the cpu doesn't run
when not plugged in it idles at 800mhz and tops at however many ghz my cpu can run at and when plugged in it idles at 200mhz and tops at 800
anything
is frequency scaling affected by acpi
well it's controlled by acpi
i think my ac is broken
ok it is, when plugged in linux reports charging state at a rate of 0?
that can probably be done via advanced p/cstate management
aka not directly related to acpi but somewhat
so it could be that linux is going ahead and saying: well you're plugged in, but not getting any decent voltage, so fuck yourself and live with an 800 mhz cpu?
iirc linux calls _OSC on the cpu object, which tells aml it supports advanced power mangament
which loads new objects
yeah
yes
fun
check if windows also does this
yeah im afraid hw issue then
if you have proprietary chipset drivers installed as well
ive never had that problem so i'm quite convinced it's to blame on my power adapter or something similar
yeah that could be the issue
anyways, laptop gonna be gone in a few minutes since I have pretty much no battery charge left
im so close to "finishing" uacpi (at least a stable 1.0), but have been a bit lazy to do anything lately
spent the weekend playing minecraft

will the APIs also become stable after 1.0?
yup
very helpful, i will have to upgrade and see what i've missed out on
im a fan of stable api myself so i hate to break it even now
even though the readme explicitly mentions that its unstable right now
it's still young and at least there actually is a 1.0 in sight
but sometimes its better to break than to live with crappy api
yeah definitely
im aiming for june/july 1.0
then i can finally go back to other projects after a year long detour
i wonder if its worth wasting my time to make everything numa aware from the start
Thanks
People were unironically referring to me by that handle so I thought I should stop there
cant wait to be called "thread 210425 panic"
hello thread 210425 panic
Operation not permitted

sudo tkill 210425

apology for bad english
where were u wen thread 210425 die
okay so... where was i
cleaning up my global lock PR
by default uACPI will use void* as thread id
this should hopefully cover 99.9% of users, if not override it ofc
this is the general idea
Aaand look at that!
Reading from a Lock'ed AML field
The PR will need a bit more cleanup and some real hw tests ofc
but looks like it works
made a simple test case as well
this acquires the global lock a ton of times, one of them being by a locked field write
well looks like it works in managarm as well
at least on qemu
for whatever reason reading from hpet needs the global lock
also pretty convenient
i should add uACPI to Vinix like next month
sounds like something fun to do on the side
well it has a c2v thing but it's not quite a bindings generator
at least i think
i would have to see what @ancient sable has to say about that
it does have a bindings generator
i'm actually working on integrating into v
so that you can just #include "foo.h" and call C.fns(3,4,5) right away
without declaring the functions
for now you do have to declare them, but you can use v translate -wrapper library.h
ah that's good to know
i think i actually used that before, just completely forgot about it
that sounds pretty awesome
yeah it's super useful and it's been improved a lot
it can handle entire sokol library for example
nice then
I specifically simplified some headers too
So that bindings are easier to make
Like there are no user facing bitfields for example
Zig just doesn't support that
okay well global lock seems to work on real hardware
although i didnt see any contention on it unfortunately, at least from briefly looking at the logs (no way to view them after as managarm dies after boot because driver bugs)
doesnt zig support arbitrary bit-width ints?
they do, but probably @cInclude is just broken
translate-c doesn't understand bitfields
yes, but not bitfields
variable bit-width ints != bitfields
wouldn't packed + bit-width int make a bitfield basically?
bitfields are also very unstable between platforms so
i wouldnt rely on zig's ability to translate them correctly
i dont think packed structs are compatible with extern structs
so yeah, translate-c just cant produce it
no
Designing the API for advanced _OSI configuration
this is mostly for very advanced kernels but should be implemented nonetheless
wouldn't it make sense for the uacpi_{un,}register_interface to take a uacpi_interface instead of a const char *? it seems that they are somewhat standardized and you already have an enum of them
aren’t these functions used to register new interfaces? I don’t see how it would make sense to register already existing interfaces
Yup
These are basically for registering new custom interfaces, e.g Darwin
The enum above is standard interfaces like Windows versions
This can be an arbitrary string
ahh i see
anyway this is a draft and the name uacpi_interface was misleading
i renamed to uacpi_vendor_interface, which is what it is
the idea is certain quirk handling code needs to know the latest windows version AML queried support for
because different windows versions need different workarounds
example:
also in hindsight uacpi_kernel_acquire_mutex returning a bool is the most retarded decision ive made
ill change that to uacpi_status
At what point should it be allowed to fail tho?
it might oom or fail for other reasons
otherwise im forced to do this shit everywhere
if (uacpi_unlikely(!uacpi_kernel_acquire_mutex(mtx, 0xFFFF)))
return UACPI_STATUS_INTERNAL_ERROR;
so i lose the chance to propagate callee errors
also this allows to propagate timeout in a uniform fashion
UACPI_STATUS_TIMEOUT is a thing
Hmm I guess
...aaand this PR merge marks the end of missing ACPI features
everything else thats left is either utility api or locking
I'm so gonna have fun integrating uACPI in a few months, once I finish my other two projects
The long awaited Marca return to osdev
Yes, currently "researching" different methods of rendering multiple swapchains through vulkan in a way that results in good performance at all times.
Which is kinda difficult when DWM is like "Oh I see you want to present this window, well lemme just spend 600 us doing nothing for no reason"
And then once I'm done with that I'll spend time writing a HTTP socket system for at least 1.1 and 2, can't really be bothered to implement QUIC xD
And once I'm done with that I can complete the secret manager, and once that's done I'll move back to osdev :>
So I'm expecting I'll get back to osdev around august, september ish
Made a test case for _OSI
For whatever reason even added compatibility for ACPICA
the first command in the terminal is this test fed to ACPICA
the second is uACPI test runner
acpica is identified by AnotherTestString?
Just merged the interfaces PR + simplified the initialization structure
❯ cloc --vcs=git .
134 text files.
134 unique files.
60 files ignored.
github.com/AlDanial/cloc v 1.90 T=2.19 s (34.7 files/s, 13586.8 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
C 19 3207 810 14741
C/C++ Header 44 831 1074 4536
C++ 4 379 493 2421
Python 3 207 30 561
Markdown 1 59 0 184
CMake 3 23 14 109
YAML 1 10 5 56
Meson 1 2 0 23
-------------------------------------------------------------------------------
SUM: 76 4718 2426 22631
-------------------------------------------------------------------------------
This is where it currently stands
I dont expect it to grow much more
Pretty much 95% of the features & helper API you could possible need is done
What's left is general thread safety, maybe a few misc api features im still considering
I have just realized I dont have any call stack depth limits... Should probably limit it to like 256
Done!
silly question, is the depth configurable?
first
"Great minds think alike"
absolutely!
and idiots never differ 😉

i know there would have to be this one aml blob that does some polling recursively
so it must be configurable
void delay(size_t millis)
{
if (millis == 0)
return;
Sleep(1);
delay(millis - 1);
}

lol
cplusplus users in 2013 at its finest
lol ACPICA doesnt pass this test
uACPI can resume blob execution even after a fatal failure by unwinding back
acpica cannot here
What about microsoft's one?
i would have to pull up my kernel debugger for this...
I would almost assume they probably can handle it
but my guess is it has no recursion limit at all and would hang
yeah probably
fuck, lets test i guess
its going...
the debugger is not feeling well
looks like my theory was correct
but lets see
what should I call the status code?
i dont like this too much
but maybe its fine
Rather funky...
Maybe they just have a very large depth limit?
let me try without the debugger
because it just takes 10 yers
what i've learned with NT interpreter is that all they do is very very simple
so i wouldnt be surprised
(if theres no limit at all)
why would firmware have an infinite unbounded recursion wtf
they already have infinite unbounded loops all over the place
so this wouldnt be new
waiting on some register to change for example
with RECURSION??
you would use a while loop ofc but its impossible to predict what comes in their corrupted minds
rather than a while loop
also
aml is patched by bios at boot all the time
if it patches aml incorrectly it could produce an infinite recursion loop
its just too easy to fuck this up
With people advocating code like this, obviously it can very well happen
still spinning...
Sounds like only uACPI handles it then 
qemu memory usage growing by 200kb every few seconds
i gave it 4g so this will take years
acpica also handles it, but as a fatal abort
So the nt one just grows the stack when it reaches the stack limit?
i mean u have to be retarded to run aml recursively
it grows the internal call stack "array" or list or whatever
the actual interpreter runs on a normal fixed kernel stack
Very inefficient so yeah can agree
Makes sense
ACPICA is generally shit at this
Things just have to work
VLA?
NT interpreter is pretty good i think, no recursions there
C Variable Length Arrays
oh like alloca
Ye
yeah
Just without alloca
consuming an unpredictable amont of stack space
The compiler can generate whatever it wants to do the sub rsp
uACPI does it via a "vector"-like thing
with inline fixed storage
so like first 4 function calls don't allocate
after that each new frame is an allocation
Hmm, do you immediately free it when you exit the frame too?
Cuz that'd be kinda inefficient
Ah ok, so like if you enter a hundred frames, it will keep the memory forever?
yeah, until the very last function exits
its all stored in the "execution_context" struct
which is a few pages big
for most aml no dynamic allocations besides inline storage in execution context is needed
for more insane aml some dynamic memory is allocated on demand
its like a vector with two parts, inline storage and dynamic storage
Fixing some of the retarded uacpi_warn usages where it should clearly be uacpi_error, e.g.
Going to rewrite everything in tables.c
Its the sloppiest garbage i have in the entire code base
i did refactor it a bit in the past but its not on par with the rest of the project
no tracking of duplicate tables, no api to hook table installs, no override
I'm also not sure whether its worth to have an overcomplicated refcount per table and have it unmaped when the last reference is removed
like ACPICA does
tables are relatively tiny and the biggest ones like DSDTs must be mapped at all times
One thing uACPI is way better than ACPICA at is project structure
ACPICA has literally all public api dumped into one header, its impossible to tell whats what
and it has publically exported global variables that you're supposed to update directly
its also impossible to tell which api u need to implement, which is mandatory, which is not
like this is hell to port
You can really tell it's custom made for linux, and everything else is an afterthought
it's a wonder it still exists as a formally independent project
echoes of DRM here
that was an independent project maintained in its own repository, then one day linux unilaterally decided to import the upstream code into the linux kernel monorepo and discontinue contributing back
Pretty much
i mean acpica is also inlined into linuxx
that was the death of portable DRM
Its maintained by one person that doesn't know much about the project too
they have a script that automatically puts the Linux code style on it, reports say
Its used for upstream sync, but nowadays most changes go directly into Linux bypassing acpica
https://github.com/acpica/acpica/tree/master/source/tools/acpisrc i believe this is the conversion tool
And it calls that yeah
i wonder why they can't just use the ACPICA style
the loud TYPE_NAMES!! is offputting but it's not unbearable
I mean, Linux MM has a ton of pascal case macros
And you can find inconsistent code styles everywhere in vendor code in the kernel
Most likely they decided to be nice and make it match
Yeah I found that pretty weird lol
wait till you struct task_struct
just in case you were in any doubt what kind of type that is
I think its a struct but I'm not sure, maybe we should rename it to struct structure_task_struct
i think it might be a struct
but maybe its also a task
what if it were a union
nah its probably a union
my github action runs randomly get canceled??
anyone else seen that?
and that only happens on ubuntu for whatever reason
yeah it can happen i think
like canceled by whom lmao
interesting, but I've never seen that before
and i did like at least a few hundred runs
maybe just luck
afaik it's qos stuff, ci instances for free accs run on idle cpu time
so if there's a lot of paid gh work the thing can get preempted indefinitvely
pay microsoft moneies
that makes sense
inb4 it's all for bing ai queries :^)
BAN -> DISALLOW?
is that better?
deny?
deny sounds cool
allow/deny makes it clearer imo
true
what if accept/drop/replace_(phys/virt)
interesting
I think drop would fit better
I don’t know how this disposition table thing works but drop kinda implies that some attribute or whatever gets, well, dropped
But depending on how this thingy works there is nothing actually being dropped
So deny would make more sense
I associate drop with networking too much, so in my mind ignore might sound better
accept/reject?
Okay i finally rewrote all of it, it's now much more advanced and thread safe
Added an ability to override tables dynamically + install/uninstall/load public api
The table subsystem was the weakest link, notw it no longer is
i need to split this up into commits and do some testing ofc because a ton of things have been changed
Don't u just love it when clion randomly decides that an entire function is unreachable code
its both unreachable and within a recursive call chain
Clion can do really weird things sometimes
Which I don't understand
Like I have had cases where it was omega smart and actually did find some weird recursive chains or checks that always fail
But sometimes it's stupid and just thinks "ah yes, this check is totally never going to pass"
Yup can confirm I've seen both
Mostly the latter
But as long as it sometimes finds bugs im fine with it
i should try this thing out
Yes definitely do, its very good
They give out free licenses for open source projects
You can apply and get one
I just bought a license with student discount 
Could've got one for free for tomatos probably
I don't have it worked on enough to have it consistent
Get back to work then 😡
Tbh this kinda makes me write a kernel that uses acpi for all the drivers
All the ability to load arbitrary buffers gives a lot of power
yeah it is pretty cool stuff
finally, portable drivers!

Y e s
Tbh for legacy drivers with bank registers and index registers it's even a pretty decent
But with modern drivers where everything is just mmio it's kinda easier to just use native code
Oh yeah that's one problem, can acpi even get a pointer to a buffer
yeah
How
Depending what you mean exactly
You need to give hardware a pointer to a buffer
Now excluding pre allocated buffers that the firmware can allocate, does acpi on its own has the ability to allocate a buffer and get a pointer to it
hmm let me think
technically there isn't any way to extract an address of an object, but you can totally design an interface to do that
with a native call for example
or even like a Notify(obj, ADDRESS_OF)
if you agree on a value for ADDRESS_OF
or just make a method that will resolve to a native call that will return the address of a buffer passed into the function
there's already _OSI for calling into the os
you can totally reuse a similar thing
so yeah, totally possible
provided you add a few more os-defined functions
similar to NodeJS
yeah, it would need some extensions
@fiery turtle shouldn't these be info->flags & UACPI_NS_NODE_INFO_HAS_HID and info->flags & UACPI_NS_NODE_INFO_HAS_CID
Yeah this is pre bitflags API
Outdated stuff
Thanks for pointing out
I saw that u rebased to latest master, very nice
always pleasant to see commits with more code removed than added
added optional compile-time mutex tracing
i think i'll also add tracing for every single method returning a uacpi_status
so close
i would star it but i already have long ago :p
Same^
much appreciated ❤️
Now...when uAPM? 
lol
i think apm is realtively tiny(?) compared to acpi
the only problem is u need a bios call helper to drop down to real mode
I might fiddle with it someday if I ever try running anything on one of my old laptops
i have an apm enable switch in bios for my 2019 pc motherboard
lmao
its off by defautl but i mean lol
You're welcome :P
Ima star
the TODO list grows along with my laziness
although i'm almost done with p.3
I constantly produce huge PRs then proceed to stall
because they appear to generally work but still need review and additional testing
Story of my life
Lol
I wonder if I should make uacpi_object an opaque struct like i did for uacpi_namespace_node
a lot of internal shit is leaked via the public types.h header which is something i dont like too much
I consider such structuring to be a massive W
the amount of people who rely on internals no matter what you say to prevent them from doing it is surprising
Add a deprecation warning to all internal types so their builds will be spammed?
just make the structs opaque instead 
But yeah I know what you're talking about - I have a graphics library and wish I hadn't exposed internal types :P
Because it happens slightly too often that people try to use those (let alone change them) and get stuff they weren't expecting
yeah i know its the way forward, kind of scared of the amount of refactoring this would introduce tho
uACPI test runner would've been 10 times more advanced if C++ had anything like python argparse
its so fucking annoying that c++ has nothing to assist in argument parsing
getopt
its way way less advanced than argparse but yeah
maybe not in freestanding C++ but how about std::stringstream
that's just a string stream though, isn't it? no args parsing
i was being slightly facetious with getopt
it parses a string
but what's it that pytson's argsparse does so well?
what more would you want
i thought it just streamed one
in what way does it parse strings?
you can read from it as if you read from iostream
that's just streaming
if you have formatted data separated by spaces you can read it directly into its type
example:
def main() -> int:
parser = argparse.ArgumentParser(description="Run uACPI tests")
parser.add_argument("--asl-compiler",
help="Compiler to use to build test cases",
default="iasl")
parser.add_argument("--acpi-extractor",
help="ACPI extractor utility to use for ACPI dumps",
default="acpixtract")
parser.add_argument("--test-dir",
default=test_relpath("test-cases"),
help="The directory to run tests from, defaults to "
"'test-cases' in the same directory")
parser.add_argument("--test-runner",
help="The test runner binary to invoke")
parser.add_argument("--binary-directory",
default=test_relpath("bin"),
help="The directory to store intermediate files in, "
"created & deleted automatically. Defaults to "
"'bin' in the same directory")
parser.add_argument("--bitness", default=64, choices=[32, 64], type=int,
help="uACPI build bitness")
parser.add_argument("--large", action="store_true",
help="Run the large test suite as well")
default, choices, type
help
like cpp stringstream ss("42 something 4.0"); int x; string y; float z; ss >>x >>y >>z;
i can refer to the options as args.<name> etc
wow that's pretty cool
while getopt is C I guess you can just use that if nothing else
getopt_long a bit lacking then in conveniences compared to this
yea..
i'm surprised they havne't added something to c++ template library for this
and this also supports unnamed arguments, short arguments, all that stuff
just done for you automagically
they've sure as hell added everything else in the world to it
i know right
Why would they
hence why im mad
Ok they added regexes, fair enough
that stack overflows and is a piece of crap
like msvc regex is known for just obliterating the stack
its unusable
i doubt glibc one is different
Fair point
I actually had to use boost regex at one point but it was due to performance, and not stack problems
performance too yeah
boost as bloated as it is at least has those implemented decently
it has a proper arg parser too iirc
Oh no no I don't use the entirety of boost
Just the regex and base64 parts
I deleted the rest because they weren't necessary and I wasn't using them
i doubt anyone is using the entirety of boost
they would end up with a few gb worth of code

