rust-osdev / acpi

Rust library for parsing ACPI tables and interpreting AML
Apache License 2.0
202 stars 65 forks source link

AML: Support method invocation in arithmetic expression #137

Open rw-vanc opened 1 year ago

rw-vanc commented 1 year ago

On HP-dq3xxx, I get the error IncompatibleValueConversion in as_integer. The ASL/AML is: OperationRegion (MCHR, SystemMemory, (GMHB () + 0x6100), 0x0100) 5B 80 4D 43 48 52 00 72 47 4D 48 42 0B 00 61 00

Here's the code for GMHB:

Method (GMHB, 0, Serialized)
        {
            If ((MH_B == Zero))
            {
                MH_B = (^MC.MHBR << 0x0F)
            }
            Return (MH_B) /* \_SB_.PC00.MH_B */
        }
rw-vanc commented 1 year ago

Can I invoke a method in as_integer? How do I do this? Any help would be appreciated.

IsaacWoods commented 1 year ago

Can I invoke a method in as_integer? How do I do this? Any help would be appreciated.

Hm, this shouldn't be required. That field is a term_arg, which when it's parsed should attempt to invoke the method and do the arithmetic before you ever get to as_integer. I'll look into what's going on when I get the chance.

Thanks for the report!

rw-vanc commented 1 year ago

I'm now blocked by this. I'm going to try to figure it out on my own, but if you have some suggestions, let me know. My current best guess is that this is a method with no arguments, so maybe it's not correctly reading it as a method invocation.

rw-vanc commented 1 year ago

Backtrace:

[TRACE]                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       <-- DefShiftLeft
[WARN] operand Field { region: AmlHandle(1862), flags: FieldFlags(3), offset: 591, length: 17 }, shift_count Integer(15), target Name(AmlName([Segment("MH_B")]))
[ERROR] as_integer failed to convert Method { flags: MethodFlags(0), code: AML([a4, 42, 4e, 30, 30]) } to Integer
thread 'main' panicked at 'failed to convert', aml/src/value.rs:304:17
stack backtrace:
   0: rust_begin_unwind
             at /rustc/8ce3204af9463db3192ea1eb31c45c2f6d4b5ae6/library/std/src/panicking.rs:556:5
   1: core::panicking::panic_fmt
             at /rustc/8ce3204af9463db3192ea1eb31c45c2f6d4b5ae6/library/core/src/panicking.rs:142:14
   2: core::panicking::panic
             at /rustc/8ce3204af9463db3192ea1eb31c45c2f6d4b5ae6/library/core/src/panicking.rs:48:5
   3: aml::value::AmlValue::as_integer
             at ./aml/src/value.rs:304:17
   4: aml::AmlContext::read_region
             at ./aml/src/lib.rs:447:40
   5: aml::value::AmlValue::read_field
             at ./aml/src/value.rs:448:17
   6: aml::value::AmlValue::as_integer
             at ./aml/src/value.rs:299:39
   7: aml::expression::def_shift_left::{{closure}}
             at ./aml/src/expression.rs:634:54
   8: <aml::parser::MapWithContext<P,F,R,A> as aml::parser::Parser<A>>::parse
             at ./aml/src/parser.rs:371:55
   9: aml::expression::expression_opcode::{{closure}}
             at ./aml/src/parser.rs:479:37
  10: <F as aml::parser::Parser<R>>::parse
             at ./aml/src/parser.rs:99:9
  11: aml::parser::comment_scope::{{closure}}
             at ./aml/src/parser.rs:267:44
rw-vanc commented 1 year ago

It looks like the code to evaluate _BBN is not correct (lib.rs, 446). I will look into it some more.

Method (_BBN, 0, NotSerialized)  // _BBN: BIOS Bus Number
            {
                Return (BN00 ())
            }
IsaacWoods commented 1 year ago

Ah yeah the issue with _BBN and friends makes a lot more sense, and is an error on my part. All of the PCI objects in that method are encoded as objects in QEMU but can be methods according to the spec - at places like here and here, we should be invoking them as if they are always methods (invoke_method gracefully handles them being plain objects so that's fine), and then calling as_integer on the result I think

rw-vanc commented 1 year ago

It's not as easy as it sounds lol. invoke_method requires context to be mutable, which creates borrow problems all over the place. I'll let you know how it goes. Edit: I just had to clone a few AmlValues in various random places.