#uACPI - a portable and easy-to-integrate ACPI implementation
1 messages · Page 46 of 1
broken firmware

then the kernel map function should just fail if you're trying to map 64 bit addr on 32 bit kernel
when you said "usually in acpi", youi mean... firmware devs do that?
sorry im a bit slow
this still feels incredibly wrong
What about new machines?
but like, how does firmware work with physical addresses >4G?
never seen acpi > 4g
but its possible in theory
Like my PCs don't have CSM and freely map stuff like framebuffer at 512GB
thats not acpi tho
thats just a bar yeah
ill still change that logic to return an error i think tbh
i dont like that
still, at some point the systems might start doing that
then who's at fault, really?
on some other arches like aarch64 it wouldn't be that weird to have stuff above 4gb
why are you trying to run a kernel that doesnt do pae on such a machine
my m1 macbook doesn't have any usable memory below 4GB
though yeah you don't run a 32-bit kernel there lol
Like everyone is 64 bit, if you're writing 32 bit kernel without PAE in 2025 and run it on 64 bit machines, it's self inflicted
yeah well nobody is doing that
yeah but thats aarch64, and 32-bit arm doesnt have acpi at all
this is for people who write 32-bit kernels for machines that do not have pae and therefore they don't bother supporting it
it's not intended to run on 64 bit machines
or even 32 bit machines with pae
It doesn't mean that uACPI can't be a 32 bit binary 


then dont build uacpi without 64 bit phys addr support
(this is very weird)
its up to you
Yeah, even that makes no sense
Arm has no compat mode afaik?
Or how does that work?
it does
uacpi will truncate addresses to 32 bits if the physical address size is 32 bits
there's thumb mode
Like can you just take a random 32 bit kernel and boot it on 64 bit CPU?
not the kernel
arm has optional support for 32-bit support at either exception level
my memory is so fuzzy i dont remember shit about arm
Like it's not x86 where you can run DOS on 2025 PCs
thumb is not a different execution mode
oh is thumb just a smaller instruction set or something
my bad, as i said idk shit about arm 
well it kinda is a mode that you change to by branching but not like completely different afaik
basically on aarch64 there may be 32 bit support but only for userland for example
and not the kernel
microkernels
But it's identical regarding system behavior
yes
is thumb even useful
It's just a different instruction encoding
32-bit drivers with 64-bit kernel would be very very cursed lmfao
I think there needs to be some mainstream microkernel to keep architectures in check
hasn't pmos done that for testing
just let 32-bit userspace on 64-bit kernels die 
Like that's how I ported it to i686
I've gotten all userspace (so all drivers basically) compiled for 32 bits working with 64 bit kernel in compat mode, then knowing that ported the kernel
It seems weird that uacpi assumes that the physical address size is 32 bit on 32 bit machines though
it checks if pointer size is 4 and the define is defined
so unless you define it you will get 64 bit physical addresses on 32 bit builds
There can be lots of scenarios where physical address size != virtual address size
It's kinda maybe useful for simple drivers, like what are the benefits of i8042 or ns16550 or a bunch of other stuff being 64 bit binaries
Shouldn't this be the default?
And not even simple ones
not needing multilib stuff to be installed
what are the benefits of them not being 64 bit?
64 bit is generally better
you have more registers
if you mix your userspace to be partially 32 bit and partially 64 bit you'll have to build all the libraries twice
you dontp ass arguments onthe stack
not having two separate binaries
?
why would you have two separate binaries either way
one for a 64 bit and one for 32 bit userspace
Like just reusing the i686 binaries and not having to rebuild them for x86_64
Yeah, I guess it's mostly pointless
that only really applies if you always build all platforms
But it works, you can mix 32 and 64 bit drivers
idk how big of an impact more gprs + not passing arguments on the stack has
as in performance
but it feels like it should have at least some impact
probably a decent amount considering 32-bit x86 has a very tiny amount of regs
and thats one reason to favor native 64 bit binaries
Also if you mix in emulation, you could potentially extend that to running drivers written for other architectures
yeah like 5-6 gprs
iirc on pmos 32 bit uacpi had about the same perf as 64 bit uacpi somehow?
might be misremembering
ehhh ebp can be used as a gpr
I can compare it again this evening
the only reason to reserve it is backtracing
like, compiler generated
and for that you have dwarf
at least i havent seen that yet
on x86-64 it does by default
you're blind
i believe they did change this on gcc 14
to revert to -fno-omit-frame-pointer as default
I remember fiting with GCC for it to not use fp as gpr
The Return of the Frame Pointers
I'm assuming it does the same on x86
Did they accept that DWARF stack traces are often broken af? 
read that
I had libunwind in my kernel, and couldn't figure out how to get stack traces from it
actually idk if gcc 14 defaults to it or not, i can't tell properly via godbolt and i'm lazy to determine it
maybe godbolt passes -fno-omit... by default
Like someone only compiles a driver for x86 and doesn't give you the source code, and you can just run it on any arch
x86-64 clang running with -m32 -O3 (and no other options) uses ebp as a gpr
what the fuck lol
i have never seen that tbh
maybe it does default to -fomit-frame-pointer
but on ia32 you have very little registers
6 with ebp
at least the frames themself aren't generated so I assume it'd also use it as a gp
oh yeah i forgot that you need to pass -O2
it tells you all the compiler options used if you click on the checkmark next to compiler name
It might also only do that in leaf functions
nah it was just me forgetting to pass optimisation flags
with the code i'm testing it with it gets used in a non leaf function
so yeah besides my stupidity gcc14 and clang19 still default to it
and it is quite easy to generate code that uses bp as gpr
you basically need to use -fno-omit-frame-pointer for os level profiling though
since DWARF decoding is way to slow
to run e.g. in NMIs
you can just parse it to a better format
you can do that but it's a lot of work
idk why didn't they make dwarf into something more like seh tbh, though ig it has limitations with what you can express in it but its much simpler (at least I think, though I haven't really done dwarf unwinding so I can't speak for sure about that)
because DWARF was designed for debugging, not for unwinding
why didn't they invent a new format for unwinding then 
¯_(ツ)_/¯
they did, eh_frame is very slightly different from dwarf iirc
they just weren't very creative
DWARF instructions can do arbitrary computation to recover register values etc
there's no way to make it fast in the general case
that's also overkill for unwinding
and yet half the local variables show up as optimized out :^)
yea
1: its not UB for uacpi to return whatever garbage status code
2: UacpiError should probably be Status for consistency with the C API. also, from_raw should be impls of From<i32> for Status. also, to_string should be called as_str (as not to because you aren't doing an expensive conversion, and str not string because you aren't making a String). also, you should impl Display for Status
3: you need to run rustfmt over it all btw
4: also not UB in LogLevel
5: you should newtype PhysAddr rather than using a type alias. also, physical addresses are 64 bit even on 32 bit platforms (at least in reality).
6: DataView is just &mut [T], no? (or &[UnsafeCell<T>])
7: i'd avoid using a generic "some handle" type.
8: also not ub to have an invalid ObjectType.
9: why is OBJECT_TYPE_MAX_VALUE public
10: ObjectTypeBits makes no sense, that's not how rust enums work.
11: personally i'd call Object::get_type something like Object::object_type or something, but that's preference
12: Object::to_string should be type_name, probably. or just not exist at all, or as get_type().as_str()
13: Object::assign_string should prooobably take a &str
14: Object::assign_buffer should also probably take a &[u8], not a &mut [u8]. also, the transmute here is unsound
15: also, why do you have UacpiDataView, UacpiDataViewMut and DataView? 3 types to do one thing lol. plus std slices (which don't have defined layout but that pretty much doesn't matter here)
16: RegionOp also has the weird Ub panic message
17: AddressSpace has a grammatically incorrect panic message, plus to_string.
really? what about JITting the dwarf code 
thats fast in every case except the jit case
i.e. the case where the user is a jit
because then they have to make a lot of calls to this dwarf jit meme

6: nope, its ptr + length
7: started to differentiate it when encountering it
9: not marked as internal in the enum in types.h
10: how else should i do it?
13: wont work rust strings are utf-8
14: yes can be &[u8], how else would it work?
15: where do you see 3 types, there are only the first two?
found the third dataview
6: yes but i mean, you could use a slice instead of it in the api
9: yes but that doesn't mean you need to expose it, it's mostly useful for C users i think
10: use the bitflags crate, and also don't expose types until you have functions that need them
13: well what other non-utf8 8 bit encoding is there lol (also, there is a CStr type in std, but thats a bit different)
14: i mean right now you have &mut [u8]
15: in the code... lol
6: Dataview is not public and i cant just pass a slice to uacpi without giving it a length
13: ?????? if i pass a uft-8 encoded string to uacpi which expects ascii encoding how do you think that will work?
14: i mean the unsoundness; transmute is safe there, how else would that work
31:
69:
ascii is compatible with utf-8 for what you would be passing to uacpi
yea but only for ascii characters
yes its missing pub
can't you take normal rust slices for the public api and convert to data view internally?
thats what i am doing
ah
6: a rust slice literally has a length in it lol
14: its not safe lol
the layout of a slice is not guaranteed
what if they want to put it the other way around?
also why would they guarantee it
rust has very very loose layout requirements in general, so i think it makes sense
transmute is safe there:
#[repr(C)]
struct UacpiDataView<T> {
ptr: *const T,
lenth: usize
}
pub fn assign_buffer(&self, value: &[u8]) -> Result<(), UacpiError> {
let uacpi_slice = UacpiDataView::<u8>{ ptr: value.as_ptr(), lenth: value.len() };
UacpiError::from_raw(
unsafe { uacpi_sys::uacpi_object_assign_buffer(self.0, transmute(uacpi_slice))}
)
}
no it is not
yes
for repr(Rust) structs yes
hm
#[repr(C)]
Returns a raw pointer to the slice's buffer.
a bunch of stuff is left still afaict
also dont call it UacpiError lol, just call it Status
no it doesnt
status implies it can be good and bad, and in their case its always bad
pub fn get_integer(&self) -> Result<u64,UacpiError> {
let mut value: u64 = 0;
let mut ptr: *mut u64 = &mut value;
UacpiError::from_raw( unsafe { uacpi_sys::uacpi_object_get_integer(self.0, ptr) } )?;
Ok(value)
}
yeah
for example
i dont need to give the user a status when i can just give them the wanted value
which means it was a success
rust status equivalent is basicly Result<(),Error>
i agree, i think this is cleaner
its also still not undefined behavior
or use a macro?
what would be the advantage over just Result?
pitust cant read x2 
what is this emoji lol
good post
I found it in the zig server lmao
that UacpiError::from_raw( unsafe { uacpi_sys::uacpi_object_get_integer(self.0, ptr) } )?; is diabolical
i dont know what else to do but please fix it
let status = unsafe { uacpi_sys::uacpi_object_get_integer(self.0, ptr) };
UacpiError::from_raw(status).map(|_| value)
this might be better to avoid the ? and constructing an Ok manually at the end
also instead of assigning &mut value to a local ptr you can just pass it directly to the uacpi_sys function
pub fn get_integer(&self) -> Result<u64, UacpiError> {
let mut value: u64 = 0;
Status::evaluate_uacpi_status(unsafe { uacpi_sys::uacpi_object_get_integer(self.0, &mut value) })?;
Ok(value)
}
i like "?"
the line is unsure
@fiery turtle
uacpi_object *uacpi_object_create_string(uacpi_data_view);
uacpi_object *uacpi_object_create_cstring(const uacpi_char*);
what exactly is their difference?
and how does const uacpi_char* work? does it just copy a single char?
imo Result::map is much cleaner but whatever
also evaluate_uacpi_status????
brother stop cooking ☠️
i'd implement TryFrom<c_int> if i were you
then give me a better name for turn "i32 into Result<(),UacpiError>"
.
except do Result<Error,()>
also pls drop uacpi from names
it's utterly pointless
uacpi::do_uacpi_thing
example?
uhh ok, so first example is the obvious evaluate_uacpi_status
what other status would there be
UacpiError too
if someone wants it to be UacpiError they can use uacpi::Error as UacpiError but like
evaluate_uacpi_status is internal
UacpiError because AllocError is also used in uacpi-rs
ok well i am just saying what you can change based on my experience with other rust projects
zig doesnt guarantee slice layout either for the same basic reasons
nor are plain structs and unions well-defined in layout
in zig we have a keyword for "match c behavior for this" instead of the repr thing but the idea there is the same
(and we have a keyword for bitfield things too but thats besides the point)
oh also new zig stable version came out so i should probably pin imaginarium and zuacpi to that tbh
hacker@raptor:~/.local/zls$ zig build -Doptimize=ReleaseSafe
[7/10] steps
└─ [6] zig build-exe zls ReleaseSafe native
└─ LLVM Emit Object```
🙏
ok epic i'm officially on 0.14
🎉
selfhosted backend fails tragically with soft_float 😭
/home/hacker/.local/zig-linux-x86_64-0.14.0/lib/ubsan_rt.zig:83:5: error: failed to select fpext f128 f64 |(none)| xmm0
fn getFloat(value: Value) f128 {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/hacker/.local/zig-linux-x86_64-0.14.0/lib/std/fmt.zig:84:5: error: emit MIR failed: InvalidInstruction (Zig compiler bug)
pub fn format(
~~~~^~
error: error(x86_64_encoder): no encoding found for: none movups xmm0 m128 none none```
lmao
i will stick to llvm for now
cstring is for cstrings, aka null terminated char sequences
data view doesnt have to be null terminated
what does uacpi store internally?
aka which one is the preferred way of providing strings
reordering them inside a struct makes sense
the view of course
uacpi_object *uacpi_object_create_cstring(const uacpi_char *str)
{
return uacpi_object_create_string((uacpi_data_view) {
.const_text = str,
.length = uacpi_strlen(str) + 1,
});
}
this is literally the impl

yea it is what it is
the selfhosted backend (-fno-llvm) is really meant for regular userspace programming
pretty sure it's not tested for custom targets with custom cpu features
makes sense
yeah
i dont remember how much if any inline asm the selfhosted backend supports tbh
one neat thing in 0.14 is the llvm bitcode emitter got moved into std from the compiler
the WHAT
FROM WHAT
zig emits llvm bitcode/ir/whatever it is directly instead of binding to libllvm
because libllvm is UNGODLY SLOW
i did NOT KNOW it was in the STANDARD LIBRARY
and the builder struct used to do that is now in std
thats very new change
OH INTO
some other language/project called Roc decided to write their compiler in zig so the zig people moved the stuff into std for them to use
that is also new to 0.14 from 0.13
not as new to master tho
you can even @import zon files now but they need explicit types atm
thats pretty cool
oh and apparently zig's memcpy got sped up a bunch this release too
src/main.zig:7:19: error: '@import' of ZON must have a known result type
ah yeah
that is nice though
fuck why cant it embed svg
damnit discord
guess ill screenshot
ubsan_rt coming to zig-built c code now too
allocator separated remap and resize functions now
i saw a bunch of ubsan symbols last time i disassembled my kernel binary
i was a bit confused but that's nice
i think its wired into the zig panic handler too but im not 100% sure there
@splat working for arrays is so nice
if i was writing compilers id be way more into the labeled switch stuff
yo pog
Allocator.remap is probably one of the bigger changes for osdev tbh
nooooooooooo
(its resize allowing relocation. returns null if the resize with relocation would be the same as doing a new alloc plus a copy)
is that continue label a goto ?
restricted but basically.
label has to be on a switch that youre in
that's nice
quite a handy syntax
the benefit is codegen
the labeled switch continue thing has much better codegen than the loop emulation. compiler sped up by like 15% or something like that from it
13% for the tokenizer thats what it was
i wonder how much of the std uses Allocator.remap
(it can generate unconditional branches and jump table stuff instead of forcing loop semantics)
array list uses it a bunch
damn nice
and realloc calls it
yeah i was searching through myself
thats up to the allocator implementation
its a new thing in the vtable
yeah but on linux for example
mremap
Maybe they'll finally add SSO one day
til thats a thing
SSO for non-owning memory view?
yeah
ah ok
u probably need a very large allocation for it to be able to remap?
fn resize(
_: *anyopaque,
buf: []u8,
alignment: mem.Alignment,
new_len: usize,
return_address: usize,
) bool {
_ = alignment;
_ = return_address;
if (new_len <= buf.len) {
return true;
}
if (CAllocator.supports_malloc_size) {
const full_len = alignedAllocSize(buf.ptr);
if (new_len <= full_len) {
return true;
}
}
return false;
}```

remap is allowed to leave in place
just not required to like resize
its mainly a page allocator thing i think
yeah
.resize must keep the same address
(the idea is you can keep the same physical page for the bottom chunk but change to a diff region of virtual memory if needed)
.remap is like realloc
and .resize is like "oh can you fit it in the same slab?" or something
yeah
or is there free space after in virtual memory to expand the virtual allocation
stuff like that
whereas remap is can you get new virtual memory block but keep the physical memory
and then realloc is i dont care how i just need bigger block
array list calls remap directly instead of realloc because it can save copying the unused capacity which realloc would do
if it has to realloc that is
I've wrapped int into a struct in my bindings for syscalls
makes sense
For strings
@fiery turtle do i have to check for null ptr and similar if its non failible or non error operation?
hm? where
anything that returns a pointer may return NULL to signal out-of-memory
thats not done via status?
why use a status in this case?
it's a common convention in C
same reason kernel_alloc doesnt return a status
"the billion dollar mistake"
was it OOM related?
I wonder if there are going to be any issues if I call uacpi_initialize when initially loading the driver uacpi is in and not enabling the sci in uacpi_kernel_install_interrupt?
probably not as long as you enable it later before namespace_load
the billion dollar mistake?
yea
no, its about the mere existance of null
well rust has null as well
eh
only because its needed for interoperability
it has Option<T>
i mean it would panic instead of segfaulting, same outcome
which you need to handle explicitly
well only one of the two can be exploitable
:^)
and its very hard to forget an option unwrap
true but i was referecing the billion dollar mistake thing
it boils down to null ptr exceptions
the fact that you can miss null very easily
also status has UACPI_STATUS_OUT_OF_MEMORY so thats the source of my confusion
yes but it has use cases for functions that OOM and may fail for other reasons
if it's either the pointer or OOM its very redundant to use a status
see the crowd strike? incident, wouldnt have happend if c used option<> or similar instead of null
the reason for that was that I were thinking that it would be easier that way as then I could store the sci number in a global in there and then later on the kernel can send IRP_MN_QUERY_RESOURCES that the driver can provide the sci irq to, then the kernel allocates a vector and sends IRP_MN_START_DEVICE with the vector + trigger mode so the driver can call IoConnectInterruptEx and do all the namespace load/init/whatever other stuff
kinda abusing the query resources irp because its not meant to be handled by a function driver itself but I don't have any generic platform device that the acpi driver device could be a child of lol
was that null related?
sure
i dont think so
i think it was just some bad code pushed to prod
so lack of QA/testing
i have no idea what the bad code was but even if it was a case of a missing null check you can't really pin the fault on that, there is so much more that should have been done to prevent that like code review, test suites, internal testing (like on their own systems, idk what that is called)
it was null related
the final error was a null ptr exception that crashed the kernel
but ultimately it would have been prevented by testing and some level of control :^)
which they implemented after that incident
according to some shit i read online they were just pushing updates to this one component straight to customers
but like, where code review? no way just some random engineer was allowed to push updates on their own
I mean, patching opcodes incorrectly would result a null ptr exception in any language :^)
it wasnt caused by patched binaries, it was caused by not sufficiently validating input parameters in combination with a invalid config file beeing read
@fiery turtle if a function returns a ptr and a status, can the ptr be null even with status_ok?
probably depends on the function
I would assume it can't be null unless null makes sense in a success situation
^
is this a yes or no?
"it can't be null unless null makes sense in a success situation"
the iterator api?
Yes

my zig bindings turn that back into null
because that should be a success condition not an error
and i still think it should just return ok with null for the end-of-list condition tbh
I mean it even has an example usage in the header
IMO thats kinda confusing
Like you have to have two checks in code
fn recurse(drv: *Driver, parent: *Device, alloc: std.mem.Allocator, node: *ns.NamespaceNode) !void {
var iter: ?*ns.NamespaceNode = null;
while (try ns.node_next_typed(node, &iter, .{
.device = true,
.processor = true
})) |n| {
const dev = try descend(drv, parent, alloc, n);
try recurse(drv, dev, alloc, n);
}
}
returning null for end of list is the normal pattern for iterators in zig also
because you can while(optional)
Yes but lol
replying to this
This pattern isnt possible in C
yeah for c this makes sense
its just annoying having to turn it back to the zig pattern lol
But fair enough
and that relies on not_found never coming up for reasons other than end of list also
which i dont think can happen
but that is a risk of ambiguity
For that api it cant, its pretty simple
yeah
I think it can do either invalid argument, not found, or ok
Or well, unless your mutex_acquire can fail 
lol
Which I hope it cant
one would hope
BTW for the sake of that api, whats the difference between an error and a null, do u handle them differently?
i think mine can technically fail with OutOfMemory
I think most code would just not be able to do anything
try x is equivalent to x catch |err| return err
Ah right
so the while(try thing()) |item| returns errors immediately and loops until the return is null
Like if that errors out you probably have bigger problems, like having nulls where u dont expect them etc
in this case the error return is like 80% to have it get propogated out to the root error handler to be logged lmao
Makes sense for most unexpected errors
something like
node_t *item;
status_t status;
while(true) {
status = thing(&item);
if(status != STATUS_OK)
return status;
if(!thing)
break;
// ...
}```
Ye
*not exactly return status since you have stuff like defer and errdefer which have to run before returning
Probably more like goto error_return
ok sorry that looked retarded

yeah exactly
im not sure if the defer/errdefer gets duplicated at the spot or if its an unconditional jump to the defer/errdefer blocks actually
Probably depends
It should have some internal score for whether to duplicate cleanup
thats a codegen thing that i do not worry about if i can help it lmao
which convention, the one you used or the more ziggy one?
ah yeah
i think for C this is more common, like it didnt even occur to me to maybe return OK for the last NULL when designing it
i think that's fine too tbh
you have one thing less to check
(status + iter vs just status)
basically the tradeoff is if you want to do error checking you must check for the exact status, which is in theory more possible to cause a false negative
for example if your kernel_acquire_mutex for whatever reason returns status_not_found
Not a good reference :^)
finally got around to this
this looks trivial, but i had to refactor the entire test harness to factor xsdt building out into reusable helpers, between the full and barebones runner
i also made it so it takes an std::variant of either a path to dsdt/ssdt or an existing blob
the test itself is not finished but at least its very simple
static void test_basic_operation()
{
static uint8_t dsdt[] = {
0x53, 0x53, 0x44, 0x54, 0x35, 0x00, 0x00, 0x00,
0x01, 0xa1, 0x75, 0x54, 0x45, 0x53, 0x54, 0x00,
0x4f, 0x56, 0x45, 0x52, 0x52, 0x49, 0x44, 0x45,
0xf0, 0xf0, 0xf0, 0xf0, 0x49, 0x4e, 0x54, 0x4c,
0x25, 0x09, 0x20, 0x20, 0x08, 0x56, 0x41, 0x4c,
0x5f, 0x0d, 0x54, 0x65, 0x73, 0x74, 0x52, 0x75,
0x6e, 0x6e, 0x65, 0x72, 0x00
};
acpi_rsdp rsdp{};
auto *xsdt = make_xsdt(rsdp, std::span(dsdt), {});
auto cleanup = ScopeGuard(
[&xsdt] {
uacpi_state_reset();
delete_xsdt(*xsdt, 0);
}
);
g_rsdp = reinterpret_cast<uacpi_phys_addr>(&rsdp);
static uint8_t early_table_buf[4096];
auto st = uacpi_setup_early_table_access(
early_table_buf, sizeof(early_table_buf)
);
ensure_ok_status(st);
}

btw i will make the uacpi-rs api overly cautious and when you take a look i may can make it less cautious/strict
Wdym by that
like checking for null on every returned ptr
can i assume that all returned ptr are aligned?
Id be more cautious about user input tbh
Yes..
rust types system handles that
Hm okay then
like good luck trying to force a null ptr from rust to uacpi without causing ub in rust
Well thats good
its possible but it requires unsafe and needs to be somewhat deliberately done
debug asserts or prod asserts as well?
oh alr
More ACPICA/NT incompact and crashes lol: https://github.com/uACPI/uACPI/issues/120
Gotta love untested code paths in my firmware
well, it's probably only untested with one of {ACPICA, NT}
probably with both, because this codepath is only taken on invalid parameter
only these two
I would offer one, but then I realized the only Macs I have are PowerPC (iBook G3 600MHz, PowerMac G5 DP 2.0GHz PCI-X) 
I have a MacBook which I could dump perhaps
(I have 8 PCs which I can dump/upload to GitHub I guess)
that would be cool
yeah those have the forth code and not acpi lol
the forth code????
i hope there is no private data in Mac ACPI tables, but i will share it later
from my iMac from late 2013
i doubt there's anything private in there lol
indeed
wild
only time I've personally encountered forth before was for a minecraft mod that used it that ceased to exist like ten something years ago
I also have core 2 duo Mac
But what I didn't get was that I needed some ID to upload stuff?
Like for each dump
@fiery turtle did you write this cleanly yourself and can i replace the nyu-efi headers with it https://github.com/UltraOS/Hyper/blob/master/loader/include/uefi/structures.h
(the gnu-efi headers are a licensing hell)
aren't headers uncopyrightable
idk, they have a copyright in gnu-efi
is there exactly one way to write them to make them give the same API?
if so, they are not copyrightable afaik
I did
Sure go ahead
could you add PXE_BASE_CODE_PROTOCOL?
diff --git a/inc/efi.h b/inc/efi.h
index a70d9d7..046336e 100644
--- a/inc/efi.h
+++ b/inc/efi.h
@@ -1,6 +1,10 @@
-#pragma once
+#ifndef EFI_H_INCLUDED
+#define EFI_H_INCLUDED
-#include "common/types.h"
+#include <stdint.h>
+#include <stddef.h>
+
+typedef intptr_t ssize_t;
#define IN
#define OUT
@@ -10,7 +14,7 @@
#define TRUE 1
#define FALSE 0
-typedef u8 BOOLEAN;
+typedef uint8_t BOOLEAN;
typedef ssize_t INTN;
typedef size_t UINTN;
@@ -25,7 +29,7 @@ typedef int64_t INT64;
typedef uint64_t UINT64;
typedef char CHAR8;
-typedef u16 CHAR16;
+typedef uint16_t CHAR16;
typedef void VOID;
@@ -60,6 +64,9 @@ typedef struct {
#define EFI_DISK_IO_PROTOCOL_GUID \
{ 0xCE345171, 0xBA0B, 0x11D2, { 0x8E, 0x4F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } }
+#define EFI_PXE_BASE_CODE_PROTOCOL_GUID \
+ { 0x03C4E603, 0xAC28, 0x11D3, { 0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } }
+
#define EFI_SUCCESS 0
#define EFI_WARN_UNKNOWN_GLYPH 1
@@ -994,6 +1001,13 @@ EFI_STATUS
IN EFI_BLOCK_IO_PROTOCOL *This
);
+#define EFI_BLOCK_IO_PROTOCOL_REVISION 0x00010000
+#define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001
+#define EFI_BLOCK_IO_PROTOCOL_REVISION3 ((2<<16) | 31)
+#define EFI_BLOCK_IO_INTERFACE_REVISION EFI_BLOCK_IO_PROTOCOL_REVISION
+#define EFI_BLOCK_IO_INTERFACE_REVISION2 EFI_BLOCK_IO_PROTOCOL_REVISION2
+#define EFI_BLOCK_IO_INTERFACE_REVISION3 EFI_BLOCK_IO_PROTOCOL_REVISION3
+
typedef struct _EFI_BLOCK_IO_PROTOCOL {
UINT64 Revision;
EFI_BLOCK_IO_MEDIA *Media;
@@ -1030,3 +1044,5 @@ typedef struct _EFI_DISK_IO_PROTOCOL {
EFI_DISK_READ ReadDisk;
EFI_DISK_WRITE WriteDisk;
} EFI_DISK_IO_PROTOCOL;
+
+#endif```
this is what i did so far to get it to move on in compiling
Sure I can add some stuff, this mostly only has what I use inside of hyper
that's fine, i mean
i would appreciate a license unencumbered nyu-efi
with this header
but as long as it can compile Limine i am good
Np
i am not sure if PXE is the only thing missing btw
if you wanna test it, you can clone Limine as is, then in the nyu-efi subdir, inside inc/efi/, delete everything except the elf* files
then replace inc/efi.h with this
Btw cant u just add extra stuff to the header yourself?
Its not like youre gonna submodule it
You can also make a pr if you want it done faster 
Lol
take your time
Sure, ill get around to it this week hopefully
just make sure Limine builds with it as described above, idc about it being complete, if you then wanna complete it in your own time, that's appreciated of course
Ye
does uacpi provide me any facilities for checking IAPC_BOOT_ARCH conveniently, or do I parse the FADT myself
I am trying to check for PS2 presence
you can get a pointer to the FADT easily
and i think theres a header with the struct defined
and by easily i mean theres even a literal function uacpi_table_fadt
and yeah i was right theres a header with the struct
acpi.h has an fadt struct and tables.h has uacpi_status uacpi_table_fadt(fadt**)
@fiery turtle btw do not worry about it, we don't need it anymore
youll need to get the bit out of iapc_boot_arch though
aight
oh, would dumping ACPI tables from any PC help with your project at all?
because i have tons of PCs
ok so when was the first version of the spec to have the fadt field for rtc century field offset in it
because i can kinda get not updating it
but still
i am reading the version from 2022
so like....
are there any functions to conveniently get the ACPI version without having to parse myself the RSDP
p..please?
Currently its exposed as get_aml_bitness lol
Aka 32 means 1, 64 means >= 2
How did you solve it?
Yeah ofc, if you pr them it into the acpidumps repo
Why do u care btw
what u think of as acpi version is not really acpi version tbh, realistically the latest supported acpi specification version is the fadt revision
ACPI version between 1 or 2 changes what fields I can use of the FADT
thats wrong
only fadt version tells you what fields you can use
(well barring bogus revisions set by some firmware, but uacpi fixes that up for u)
Aight
its better to just check the namespace, that field is bogus even on qemu i440fx
yeah no os actually checks this flag, so u shouldnt either tbh
do this if you're cool: https://wiki.osdev.org/UACPI#Treat_ACPI_Namespace_as_a_Bus
its not bogus if you check it against revision :)
no like, bogus as in, since nothing really checks it firmware will often either randomly not set it, or set it for no reason
I dont know ive tested it around on all my systems and its properly done in all of em
actually linux does check for it
Elixir Cross Referencer - source code of Linux v6.13.6: arch/x86/kernel/acpi/boot.c
although the flag that it sets is not used by anyone
still lol, this flag is for noobs that dont have aml
sorry I guess it was my bad to use the fields of the FADT for what they say to be used expecting it to be fine
indeed
you can leave it for now, it's fine
but later on you will need to use the namespace even for ps2k
no I mean ill implement it sure
to parse it's resources and carve them out of the available pio range etc, or change the irq u use if it's overriden
I also do need an EC driver for this x86 mac ive been adding support for
also stuff like synaptics touchpads are exposed as ps2 mouse _CID but special _HID etc
yeah macs use ec extensively
whether it's mandatory, only one way to find out
oh I mean it is, it fails otherwise to do certain stuffs
makes sense
Alright! Will do
much appreciated
I have like 10 laptops or more + my gaming laptop
No problem!
we kinda just sorted out the licensing mess of nyu-efi (inherited from gnu-efi)
yeah but how
by figuring out what is what and removing what is problematic
ah
are the pcie ranges that are discoverable via the table also discoverable via aml?
I think it's either through MCFG or via _CBA, but not both at the same time
iirc qemu had both
both would be great as from my current view it would make acpi oriented bus/device discovery easier if only the aml objects have to be traversed and not a additional specific check of a table
I would assume it's supposed to be like ECDT
Where you use it for the initialization of the namespace, but after enumeration it may expect more
?
my desktop doesnt have _CBA but does have MCFG
_CBT
FreeBSD searches MCFG and then CBA, as part of bus init (?)
Idk when they do it exactly
Like you have to get PCI bridges from AML
But then it's an if
(and that's what I do as well)
i know you like it
anyone actually know what setting the acpi interrupt mode (pic, apic, sapic) actually does?
the \_PIC method that is
Changes what _PRT returns, on some boards reprograms the controller as well
Yes, on Intel boards it writes to chipset registers to rewire IRQs
You can look up the PCH docs, these registers are documented
In https://www.intel.com/content/www/us/en/content-details/680836/intel-600-series-and-intel-700-series-chipset-family-platform-controller-hub-pch-datasheet-volume-2-of-2.html (this is the Alder lake chipset but it's similar for other Intel chipsets)
PIRQA = first PCI legacy IRQ etc
Random observation, it looks like loongarch also uses EC?
who knows
uacpi best operating system
this
yes but its not self sufficient and relies on astral to work 
lol
@fiery turtle btw is there any support in uacpi for wiring GPE block devices (ACPI0006) into the uacpi gpe stuff?
or would an os need to make their own infrastructure for those
they aren't used by anything
oh cool, love a thing thats fully defined in the spec and never used lmao
stupid spec lmao
yeah, see uacpi_install_gpe_block
although as qwinci said, they dont exist
linux PR for it bitrotted a long time ago
astral relies on me to work, thus we can deduce that uacpi relies on me to work
I demand a paypal of 200 dollars
I mean, the real question is if windows supports them :^)
Like how the thread director pr for Linux bitrotted
But it exists on windows
Maybe, no blobs with it that I've seen tho

@fiery turtle is this known?
[2/107] Building C object kernel/system/acpi/CMakeFiles/uacpi.dir/uacpi/source/notify.c.obj
FAILED: kernel/system/acpi/CMakeFiles/uacpi.dir/uacpi/source/notify.c.obj
/var/bootstrap-menix/build/tools/host-gcc/bin/x86_64-menix-mlibc-gcc -DMENIX_ARCH=\"x86_64\" -DMENIX_RELEASE=\"0.0.1\" -DMENIX_VERSION="\"Thu Mar 13 13:14:57 UTC 2025\"" -DUACPI_OVERRIDE_LIBC -I/menix/include -Imenix/include/klibc -Imenix/kernel/arch/x86_64/include -Imenix/kernel/system/acpi/uacpi/include -Os -DNDEBUG -std=gnu2x -mgeneral-regs-only -mno-red-zone -ffreestanding -fno-stack-protector -fno-omit-frame-pointer -Wall -Werror -mcmodel=kernel -fno-lto -fno-PIC -fno-PIE -MD -MT kernel/system/acpi/CMakeFiles/uacpi.dir/uacpi/source/notify.c.obj -MF kernel/system/acpi/CMakeFiles/uacpi.dir/uacpi/source/notify.c.obj.d -o kernel/system/acpi/CMakeFiles/uacpi.dir/uacpi/source/notify.c.obj -c /var/bootstrap-menix/src/sources/menix/kernel/system/acpi/uacpi/source/notify.c
In file included from uacpi/include/uacpi/internal/dynamic_array.h:4,
from uacpi/include/uacpi/internal/context.h:6,
from uacpi/include/uacpi/internal/log.h:4,
from uacpi/source/notify.c:4:
uacpi/source/notify.c: In function ‘uacpi_uninstall_notify_handler’:
uacpi/include/uacpi/internal/stdlib.h:95:28: error: ‘containing’ may be used uninitialized [-Werror=maybe-uninitialized]
95 | #define uacpi_free(mem, _) uacpi_kernel_free(mem)
| ^~~~~~~~~~~~~~~~~~~~~~
uacpi/source/notify.c:248:9: note: in expansion of macro ‘uacpi_free’
248 | uacpi_free(containing, sizeof(*containing));
| ^~~~~~~~~~
uacpi/source/notify.c:194:34: note: ‘containing’ was declared here
194 | uacpi_device_notify_handler *containing, *prev_handler;
| ^~~~~~~~~~
cc1: all warnings being treated as errors
(only happens with -Os)
another gcc retardness
some warnings only pop up at certain optimization levels
completely bogus
ill try to repro and fix locally
alright fixed
I also finally merged UACPI_BAREBONES_MODE
👍
Cc @flat badge
cc @rustic compass
Btw, an acpi interpreter in zig: https://github.com/zaalang/zaos/blob/main/system/libs/acpi/parser.zaa
or wait, thats not zig, it's a custom lang
though idk how complete it is, the author said it will always be a toy
yeah
Yeah I saw that from the issue he opened
Took me a good second to figure what language I was looking at
rust aml parser!?!
https://github.com/rust-osdev/acpi/tree/main/aml/src
Rust library for parsing ACPI tables and interpreting AML - rust-osdev/acpi
they've got a few tests as well but it seems like most of them are synthetic ones
this one is known, i've talked to the guy who made it
it's lacking a lot of opcodes and is recursive
yeah probs don't use the version that is main
I'm currently rewriting the interpreter but it's a ways off being ready yet
oh a bunch of progress isn't yet pushed to that either lol
yeah well I think, would be interested in ur feedback once it's more complete
it's definitely a lot better than the prev version
which wasn't hard
it's vaguely based on the same mechanism as uACPI I think, but without the micro-op thing
damn, thats p cool
re the synthetic tests, idk what infy thinks about having dumps committed but I thought it was on shaky ground re EULAs etc
so I test against real AML locally but idk about having them in the repo
well the repo that i forked (with all the aml dumps) has existed since forever
and no problems with it so far
and a bunch of people have PRed their local hw
btw you can try running against the uACPI test suite as well, as long as u have a userspace runner with the same semantics, aka accept a path and expected result of evaluating MAIN()
One of the reasons my interpreter will always be a toy is that I hate implementing specs.
They always make me to do things I don't like.
For instance, I wrote the parser with fine grain namespace locking in mind, only to later discover that the spec states aml cannot be pre-empted and only certain functions are blessed as blocking.
I just know that if I implement proper multi-threading, firmware the world over would break in subtle and non-obvious ways.
True
tbh if i had the time and energy id be working on a zig port rather than zig bindings for uacpi (or more likely a zig-idiomatic acpi lib inspired by uacpi impl stuff)
but zig c integration is good and acpi is complex and i suck at writing parsers and uacpi is good so bindings it is lol
basically this
just wait until uacpi is fully finished and transpile the code :^)
lmao
the "zig" aml interpreter library
I am on the fence myself if I want to do C# binding or a port to C#, luckily I am lightyears away from getting to that point 
good luck
yeah
but you can let Zig compile C code anyway
i do have decent experience with c# native binding/marshalling stuff if you ever need help/advice there btw
thats how zuacpi works now
just adds the c stuff to the build and then has externs to bind
the problem is that I would need to implement that native binding/marshling support 
the name 
and given I don't really plan on having too many native libraries I am not sure if its worth it
i think a native c# aml library would be much nicer to work with tho
it would be for sure
like, I plan on having ACPI as the basis of the driver subsystem, which is the main reason I really want it as a port
i mean same but im using zig so the interop support is good
Its basically finished, probably only bug fixes and mayyybe a few new utilities every now and again from now on
Sooo 
You could base it on that experimental c# kernel
Which has its own aml parser
singularity?
or cosmos ☠️
singularity is licensed under some bullshit msft research license
so i don't think it's viable for ripping off if you want to avoid licensing issues
but idk how their license works
im just spewing bullshit as usual 
Ah right
Since c# is managed you can probably afford a recursive aml interpreter
Which is 10 times easier
iirc cosmos only supports like very specific dsdts
stuff must be a function that does this and that
so it's not a proper aml parser + interpreter
yeah lmao
Which I would definitely not run on my hardware
Like you will have a partially alive laptop which might not boot until a hard power cycle
If you dont have a detachable battery it might be a long time
Id say the strcmp method should work on a lot of desktops and maybe 30% of laptops with non critical side effects
If I end up doing it in pure C# it would def be a 1:1 port of uacpi
I ain't spending a single brain cell thinking about it
Would just make it use nice C# apis obviously
I mean, msvc can compile normal C++ to dotnet
💀
It's just not compatible with verification, since it does a ton of unsafe stuff
I mean, uacpi can compile with msvc
So it's probably close enough
I wonder how difficult it would be to compile uacpi under C++ mode
i expect a bunch of shit to break honestly
A few void casts and also the address of literal struct thing from C
Tbh I have no idea what's the C state of msvc
But what I remember is it was some random mix of C89 and C99 :^)
i think it does C17 lol
I didnt encounter any problems with it except macros
Yeah I think in recent years they improved it alot
And yes I set C17 in my cmake iirc
But yeah it's still missing a lot I think
Oh also it forces _s functions down your throat by default
that's msvcrt mostly
Like I would be fine using them but no other compiler supports them
Are you planning to work on Ultra kernel soon?
im getting uacpi to pagefault when turning off on a raptor lake (S5 sleep)
namely on io.c:942 to a ridiculously large address, like, well past any kind of memory
Arrow Lake
close
too many lakes
Dump + try a different os as well
I want to
Also try like managarm or something
They gave me the dump in dms dw
Also this is just a generic memory read function, so it page faults on an address you gave it
Aka something returned out of kernel memory map helpers
If you could trace where it came from thatd be cool
aight, ill let you know
Nice
It would literally be worse than anything you did and doing atm lmfao
Make a hel API compatible Rust kernel 
brain rot
that said i really need a uacpi test kernel that should be required for a bug report so i dont have to debug other peoples stuff 
i told you so...
pls use Limine lol
i'd be fine with you using Hyper but i wouldn't want to have you debug 2 things at once
at the end it's your choice though
it can support both yeah
just use Ironclad, put the live iso in a usb, boot it, do dmesg to see the output, done. And what doesnt work, I get to fix, we both win
it seems to be a bug in how Ironclad handles memory mapping actually, because the requests to poweroff are initialized from userland, ill let you know if I fix it at the end, but it does seem to be an Ironclad issue
if I had a dime every time etc etc 
I dont ping you because I think you are the issue, I ping you because you know where to start debugging
ah ok
"I get X" -> "okay look at Y"
right
@fiery turtle why could uacpi_prepare_for_sleep_state for S5 loop forever in mint's firmeware?
loop where?
it's not possible for it to loop forever as aml loops are bounded to 30 seconds by default
I just call the function and it never returns
I dont know if it is because I didnt wait 30 secs to 1 minute, I will leave it poweroff for a bit
u could set log level to trace
how does one do that
uacpi_context_set_log_level
thank you kind infy ill report findings as soon as I can
np
Ill do so later, mint went to take a nap on the room with the computer I was testing on, and I dont want to wake mint up
the computer has some crazy RGB, it does light up the whole room
I am from 🇪🇸 SPAIN 🇪🇸, naps are my national pride
yeah
el siesta
I do speak spanish italian and english, I am learning simplified chinese, when I find strength to drag myself thru the cheese greater of it
damn
I used to speak french and a lil bit of german, but I stopped learning those
🐐
i speak german, english, french and the tiniest bit of dutch
sneaked in the room and put a blanket on the PC, it basically goes as normal until it reaches a SleepOp (0x5822), it invokes the handler with a pOP: INVOKE_HANDLER (0x15), and dead, it stays there
I speak russian, spanish, english, catalan, and I technically learned french in school
catalan? thats so cool, family?
yeah so your uacpi_kernel_sleep hangs
what? crazy
No 
ill give it a look, thanks for the pointer
I've gotten a degree with clases taught in it
INVOKE_HANDLER means it jumps into a C handler for that opcode
which is this one in this case https://github.com/uACPI/uACPI/blob/156da869393e2deff93a4cba30792c447db46899/source/interpreter.c#L3148
which just does uacpi_kernel_sleep(time);
thats so cool, do you keep up with it online after the classes finished? or do you have catalan speaking circles
I see, cool
Wait, ironclad uses microkernel?
requests to poweroff come from userspace even on linux
yeah, this aspect is not really microkernely
I live in Barcelona so I guess
But idk it's kinda maybe not very good
ohh I thought you were russian, thats neat
I usually speak Spanish
I am Russian, but I moved to Spain when I was about 14
good choice, that way you get a bit of sun and the siestas
barcelona is such a great city too
i've lived in canada for two years, but sadly no french lol
what for, studies? family?
yeah, uni
neat
I was in BC, and no one speaks french there pretty much
mint was there as well, said it was a great place, do you share the experience?
yeah it's pretty cool, but expensive af
yeah thats the thing that sucks the most about canada
things are very expensive, especially rent
there are cheaper areas
but they are in places that are cold af
like most of canada lmfao
yeah probably you can find some prime real state in the middle of the northern territories 
yeah
but bc weather is very nice
it barely gets to negatives
basically similar to seattle weather
a lot of rains and stuff tho
rain's good, I much rather have 300 days raining than 300 days not raining
local man has to study orc, I pity you
I know french, English and a bit of Spanish but I'd like to learn another language
I just dunno what
I'm gonna take a mandarin class next semester tho
after fixing the sleep it works @fiery turtle
yah
you were completely fault free and unburdened by failure, but it was me the faulty one, with the routines and scenarios never called by anything but this firmware
why is everyone doing loongarch64 now?
