kernel/acpi/aml/parser/
display.rs

1use core::fmt;
2
3use crate::acpi::aml::display::{AmlDisplayer, HexHolder};
4
5use super::{
6    AccessAttrib, AccessType, AmlCode, AmlTerm, Buffer, FieldConnection, FieldDef, FieldElement,
7    FieldUpdateRule, IndexFieldDef, IntegerData, MethodObj, PackageElement, PowerResource,
8    PredicateBlock, ProcessorDeprecated, RegionObj, RegionSpace, ScopeObj, ScopeType, Target,
9    TermArg, UnresolvedDataObject,
10};
11
12fn display_target_assign<F>(
13    f: &mut fmt::Formatter<'_>,
14    target: &Target,
15    value_fmt: F,
16) -> fmt::Result
17where
18    F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
19{
20    if !matches!(target, Target::None) {
21        fmt::Display::fmt(target, f)?;
22        f.write_str(" = ")?;
23    }
24
25    value_fmt(f)
26}
27
28impl fmt::Display for RegionSpace {
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        match self {
31            Self::Other(x) => write!(f, "0x{x:02X}"),
32            _ => write!(f, "{self:?}"),
33        }
34    }
35}
36
37impl fmt::Display for RegionObj {
38    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39        AmlDisplayer::start(f, "OperationRegion")
40            .paren_arg(|f| f.write_str(&self.name))
41            .paren_arg(|f| write!(f, "{:?}", self.region_space))
42            .paren_arg(|f| write!(f, "{}", self.region_offset))
43            .paren_arg(|f| write!(f, "{}", self.region_length))
44            .finish()
45    }
46}
47
48impl fmt::Display for FieldDef {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        let mut d = AmlDisplayer::start(f, "Field");
51        d.paren_arg(|f| f.write_str(&self.name))
52            .paren_arg(|f| write!(f, "{}", self.access_type))
53            .paren_arg(|f| write!(f, "{}", if self.need_lock { "Lock" } else { "NoLock" }))
54            .paren_arg(|f| write!(f, "{}", self.update_rule))
55            .finish_paren_arg()
56            .set_list(true);
57
58        for field in &self.fields {
59            d.body_field(|f| field.fmt(f));
60        }
61
62        d.at_least_empty_body().finish()
63    }
64}
65
66impl fmt::Display for IndexFieldDef {
67    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68        let mut d = AmlDisplayer::start(f, "IndexField");
69        d.paren_arg(|f| f.write_str(&self.index_name))
70            .paren_arg(|f| f.write_str(&self.name))
71            .paren_arg(|f| write!(f, "{}", self.access_type))
72            .paren_arg(|f| write!(f, "{}", if self.need_lock { "Lock" } else { "NoLock" }))
73            .paren_arg(|f| write!(f, "{}", self.update_rule))
74            .finish_paren_arg()
75            .set_list(true);
76
77        for field in &self.fields {
78            d.body_field(|f| field.fmt(f));
79        }
80
81        d.at_least_empty_body().finish()
82    }
83}
84
85impl fmt::Display for ScopeObj {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        let ty = match self.ty {
88            ScopeType::Device => "Device",
89            ScopeType::Scope => "Scope",
90        };
91        let mut d = AmlDisplayer::start(f, ty);
92        d.paren_arg(|f| f.write_str(&self.name)).finish_paren_arg();
93        for term in &self.term_list {
94            d.body_field(|f| term.fmt(f));
95        }
96
97        d.at_least_empty_body().finish()
98    }
99}
100
101impl fmt::Display for MethodObj {
102    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103        let mut d = AmlDisplayer::start(f, "Method");
104        d.paren_arg(|f| f.write_str(&self.name))
105            .paren_arg(|f| write!(f, "{}", self.num_args))
106            .paren_arg(|f| {
107                f.write_str(if self.is_serialized {
108                    "Serialized"
109                } else {
110                    "NotSerialized"
111                })
112            });
113        if self.sync_level != 0 {
114            d.paren_arg(|f: &mut fmt::Formatter| write!(f, "0x{:02X}", self.sync_level));
115        }
116
117        d.finish_paren_arg();
118
119        for term in &self.term_list {
120            d.body_field(|f| term.fmt(f));
121        }
122
123        d.at_least_empty_body().finish()
124    }
125}
126
127impl fmt::Display for ProcessorDeprecated {
128    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129        let mut d = AmlDisplayer::start(f, "Processor");
130        d.paren_arg(|f| f.write_str(&self.name))
131            .paren_arg(|f| write!(f, "0x{:02X}", self.unk1))
132            .paren_arg(|f| write!(f, "0x{:08X}", self.unk2))
133            .paren_arg(|f| write!(f, "0x{:02X}", self.unk3))
134            .finish_paren_arg();
135
136        for term in &self.term_list {
137            d.body_field(|f| term.fmt(f));
138        }
139
140        d.at_least_empty_body().finish()
141    }
142}
143
144impl fmt::Display for PowerResource {
145    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146        let mut d = AmlDisplayer::start(f, "PowerResource");
147        d.paren_arg(|f| f.write_str(&self.name))
148            .paren_arg(|f| write!(f, "0x{:02X}", self.system_level))
149            .paren_arg(|f| write!(f, "0x{:04X}", self.resource_order))
150            .finish_paren_arg();
151
152        for term in &self.term_list {
153            d.body_field(|f| term.fmt(f));
154        }
155
156        d.at_least_empty_body().finish()
157    }
158}
159
160impl fmt::Display for PredicateBlock {
161    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162        let mut d = AmlDisplayer::start(f, "");
163        d.paren_arg(|f| self.predicate.fmt(f));
164
165        for term in &self.term_list {
166            d.body_field(|f| term.fmt(f));
167        }
168
169        d.at_least_empty_body().finish()
170    }
171}
172
173impl fmt::Display for Buffer {
174    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175        let mut d = AmlDisplayer::start(f, "Buffer");
176        d.paren_arg(|f| self.size.fmt(f))
177            .finish_paren_arg()
178            .set_list(true);
179
180        for element in self.data.iter() {
181            d.body_field(|f| write!(f, "0x{element:02X}"));
182        }
183
184        d.at_least_empty_body().finish()
185    }
186}
187
188impl fmt::Display for AccessType {
189    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190        write!(f, "{self:?}")?;
191        f.write_str("Acc")
192    }
193}
194
195impl fmt::Display for AccessAttrib {
196    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197        match self {
198            AccessAttrib::ByteValue(v) => write!(f, "0x{v:02X}"),
199            AccessAttrib::Bytes(v) => write!(f, "AttribBytes ({v})"),
200            AccessAttrib::RawBytes(v) => write!(f, "AttribRawBytes ({v})"),
201            AccessAttrib::RawProcessBytes(v) => write!(f, "AttribRawProcessBytes ({v})"),
202            AccessAttrib::Quick => f.write_str("AttribQuick"),
203            AccessAttrib::SendRecv => f.write_str("AttribSendReceive"),
204            AccessAttrib::Byte => f.write_str("AttribByte"),
205            AccessAttrib::Word => f.write_str("AttribWord"),
206            AccessAttrib::Block => f.write_str("AttribBlock"),
207            AccessAttrib::ProcessCall => f.write_str("AttribProcessCall"),
208            AccessAttrib::BlockProcessCall => f.write_str("AttribBlockProcessCall"),
209        }
210    }
211}
212
213impl fmt::Display for FieldUpdateRule {
214    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215        write!(f, "{self:?}")
216    }
217}
218
219impl fmt::Display for FieldConnection {
220    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
221        match self {
222            FieldConnection::Buffer(buffer) => buffer.fmt(f),
223            FieldConnection::Name(name) => f.write_str(name),
224        }
225    }
226}
227
228impl fmt::Display for FieldElement {
229    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
230        match self {
231            FieldElement::Offset(offset) => write!(f, "Offset (0x{offset:02X})"),
232            FieldElement::Named(name, len) => {
233                write!(
234                    f,
235                    "{}, {}{}",
236                    name,
237                    if f.alternate() { "  " } else { "" },
238                    len
239                )
240            }
241            FieldElement::Access(access_type, access_attrib) => write!(
242                f,
243                "AccessAs {}({access_type}, {access_attrib})",
244                if f.alternate() { " " } else { "" },
245            ),
246            FieldElement::Connection(connection) => write!(f, "{connection}"),
247        }
248    }
249}
250
251impl fmt::Display for TermArg {
252    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
253        match self {
254            TermArg::Expression(term) => term.fmt(f),
255            TermArg::DataObject(dataobj) => dataobj.fmt(f),
256            TermArg::Arg(arg) => write!(f, "Arg{arg:x}"),
257            TermArg::Local(local) => write!(f, "Local{local:x}"),
258            TermArg::Name(name) => f.write_str(name),
259        }
260    }
261}
262
263impl fmt::Display for Target {
264    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265        match self {
266            Target::None => write!(f, "None"),
267            Target::Arg(arg) => write!(f, "Arg{arg:x}"),
268            Target::Local(local) => write!(f, "Local{local:x}"),
269            Target::Name(name) => f.write_str(name),
270            Target::Debug => f.write_str("Debug"),
271            Target::DerefOf(term_arg) => AmlDisplayer::start(f, "DerefOf")
272                .paren_arg(|f| term_arg.fmt(f))
273                .finish(),
274            Target::RefOf(target) => AmlDisplayer::start(f, "RefOf")
275                .paren_arg(|f| target.fmt(f))
276                .finish(),
277            Target::Index(term_arg1, term_arg2, target) => {
278                display_target_assign(f, target.as_ref(), |f| {
279                    term_arg1.fmt(f)?;
280                    f.write_str("[")?;
281                    term_arg2.fmt(f)?;
282                    f.write_str("]")
283                })
284            }
285        }
286    }
287}
288
289impl fmt::Display for UnresolvedDataObject {
290    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
291        match self {
292            UnresolvedDataObject::Integer(int) => int.fmt(f),
293            UnresolvedDataObject::Buffer(buffer) => buffer.fmt(f),
294            UnresolvedDataObject::ResourceTemplate(template) => template.fmt(f),
295            UnresolvedDataObject::Package(size, elements) => {
296                let mut d = AmlDisplayer::start(f, "Package");
297                d.paren_arg(|f| write!(f, "0x{size:02X}"))
298                    .finish_paren_arg()
299                    .set_list(true);
300
301                for element in elements {
302                    d.body_field(|f| element.fmt(f));
303                }
304
305                d.at_least_empty_body().finish()
306            }
307            UnresolvedDataObject::VarPackage(size, elements) => {
308                let mut d = AmlDisplayer::start(f, "Package");
309                d.paren_arg(|f| size.fmt(f))
310                    .finish_paren_arg()
311                    .set_list(true);
312
313                for element in elements {
314                    d.body_field(|f| element.fmt(f));
315                }
316
317                d.at_least_empty_body().finish()
318            }
319            UnresolvedDataObject::String(str) => {
320                write!(f, "\"{}\"", str.replace('\n', "\\n"))
321            }
322            UnresolvedDataObject::EisaId(eisa_id) => write!(f, "EisaId ({eisa_id:?})"),
323        }
324    }
325}
326
327impl fmt::Display for IntegerData {
328    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
329        match self {
330            IntegerData::ConstZero => write!(f, "Zero"),
331            IntegerData::ConstOne => write!(f, "One"),
332            IntegerData::ConstOnes => write!(f, "0xFFFFFFFFFFFFFFFF"),
333            IntegerData::ByteConst(data) => write!(f, "0x{data:02X}"),
334            IntegerData::WordConst(data) => write!(f, "0x{data:04X}"),
335            IntegerData::DWordConst(data) => write!(f, "0x{data:08X}"),
336            IntegerData::QWordConst(data) => write!(f, "0x{data:016X}"),
337        }
338    }
339}
340
341impl<D: fmt::Display> fmt::Display for PackageElement<D> {
342    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
343        match self {
344            PackageElement::DataObject(dataobj) => dataobj.fmt(f),
345            PackageElement::Name(name) => f.write_str(name),
346        }
347    }
348}
349
350impl fmt::Display for AmlTerm {
351    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
352        fn display_func_like(
353            f: &mut fmt::Formatter<'_>,
354            name: &str,
355            elements: &[&dyn fmt::Display],
356        ) -> fmt::Result {
357            let mut d = AmlDisplayer::start(f, name);
358
359            for element in elements {
360                d.paren_arg(|f| element.fmt(f));
361            }
362
363            d.finish()
364        }
365
366        fn display_binary_op(
367            f: &mut fmt::Formatter<'_>,
368            op: &str,
369            left: &dyn fmt::Display,
370            right: &dyn fmt::Display,
371        ) -> fmt::Result {
372            f.write_str("(")?;
373            left.fmt(f)?;
374            f.write_str(" ")?;
375            f.write_str(op)?;
376            f.write_str(" ")?;
377            right.fmt(f)?;
378            f.write_str(")")
379        }
380
381        match self {
382            AmlTerm::Scope(scope) => scope.fmt(f),
383            AmlTerm::Region(region) => region.fmt(f),
384            AmlTerm::Field(field) => field.fmt(f),
385            AmlTerm::IndexField(field) => field.fmt(f),
386            AmlTerm::Device(scope) => scope.fmt(f),
387            AmlTerm::Processor(processor) => processor.fmt(f),
388            AmlTerm::PowerResource(resource) => resource.fmt(f),
389            AmlTerm::Method(method) => method.fmt(f),
390            AmlTerm::NameObj(name, object) => AmlDisplayer::start(f, "Name")
391                .paren_arg(|f| write!(f, "{name}"))
392                .paren_arg(|f| object.fmt(f))
393                .finish(),
394            AmlTerm::Alias(source, alias) => display_func_like(f, "Alias", &[source, alias]),
395            AmlTerm::ToHexString(term_arg, target) => {
396                display_func_like(f, "ToHexString", &[term_arg, target])
397            }
398            AmlTerm::ToBuffer(term_arg, target) => {
399                display_func_like(f, "ToBuffer", &[term_arg, target])
400            }
401            AmlTerm::ToDecimalString(term_arg, target) => {
402                display_func_like(f, "ToDecimalString", &[term_arg, target])
403            }
404            AmlTerm::ToInteger(term_arg, target) => {
405                display_func_like(f, "ToInteger", &[term_arg, target])
406            }
407            AmlTerm::Mid(term1, term2, term3, target) => {
408                display_func_like(f, "Mid", &[term1, term2, term3, target])
409            }
410            AmlTerm::Add(term1, term2, target) => {
411                display_target_assign(f, target, |f| display_binary_op(f, "+", term1, term2))
412            }
413            AmlTerm::Concat(term1, term2, target) => {
414                display_func_like(f, "Concatenate", &[term1, term2, target])
415            }
416            AmlTerm::Subtract(term1, term2, target) => {
417                display_target_assign(f, target, |f| display_binary_op(f, "-", term1, term2))
418            }
419            AmlTerm::Multiply(term1, term2, target) => {
420                display_target_assign(f, target, |f| display_binary_op(f, "*", term1, term2))
421            }
422            AmlTerm::Divide(term1, term2, reminder, target) => {
423                if matches!(reminder.as_ref(), Target::None) {
424                    display_target_assign(f, target, |f| display_binary_op(f, "/", term1, term2))
425                } else {
426                    display_func_like(f, "Divide", &[term1, term2, reminder, target])
427                }
428            }
429            AmlTerm::ShiftLeft(term1, term2, target) => {
430                display_target_assign(f, target, |f| display_binary_op(f, "<<", term1, term2))
431            }
432            AmlTerm::ShiftRight(term1, term2, target) => {
433                display_target_assign(f, target, |f| display_binary_op(f, ">>", term1, term2))
434            }
435            AmlTerm::And(term1, term2, target) => {
436                display_target_assign(f, target, |f| display_binary_op(f, "&", term1, term2))
437            }
438            AmlTerm::Nand(term1, term2, target) => {
439                display_target_assign(f, target, |f| display_binary_op(f, "~&", term1, term2))
440            }
441            AmlTerm::Or(term1, term2, target) => {
442                display_target_assign(f, target, |f| display_binary_op(f, "|", term1, term2))
443            }
444            AmlTerm::Nor(term1, term2, target) => {
445                display_target_assign(f, target, |f| display_binary_op(f, "~|", term1, term2))
446            }
447            AmlTerm::Xor(term1, term2, target) => {
448                display_target_assign(f, target, |f| display_binary_op(f, "^", term1, term2))
449            }
450            AmlTerm::Not(term, target) => {
451                display_target_assign(f, target, |f| write!(f, "~{term}"))
452            }
453            AmlTerm::SizeOf(target) => display_func_like(f, "SizeOf", &[target]),
454            AmlTerm::Store(term_arg, target) => {
455                target.fmt(f)?;
456                f.write_str(" = ")?;
457                term_arg.fmt(f)
458            }
459            AmlTerm::RefOf(obj) => display_func_like(f, "RefOf", &[obj]),
460            AmlTerm::Increment(target) => {
461                target.fmt(f)?;
462                f.write_str("++")
463            }
464            AmlTerm::Decrement(target) => {
465                target.fmt(f)?;
466                f.write_str("--")
467            }
468            AmlTerm::While(predicate_block) => {
469                f.write_str("While")?;
470                predicate_block.fmt(f)
471            }
472            AmlTerm::If(predicate_block) => {
473                f.write_str("If")?;
474                predicate_block.fmt(f)
475            }
476            AmlTerm::Else(terms) => {
477                f.write_str("Else ")?;
478                let mut d = AmlDisplayer::start(f, "");
479                for term in terms {
480                    d.body_field(|f| term.fmt(f));
481                }
482
483                d.at_least_empty_body().finish()
484            }
485            AmlTerm::Noop => f.write_str("Noop"),
486            AmlTerm::Return(term) => {
487                f.write_str("Return (")?;
488                term.fmt(f)?;
489                f.write_str(")")
490            }
491            AmlTerm::Break => f.write_str("Break"),
492            AmlTerm::LAnd(term1, term2) => display_binary_op(f, "&&", term1, term2),
493            AmlTerm::LOr(term1, term2) => display_binary_op(f, "||", term1, term2),
494            AmlTerm::LNot(term) => {
495                write!(f, "!{term}")
496            }
497            AmlTerm::LNotEqual(term1, term2) => display_binary_op(f, "!=", term1, term2),
498            AmlTerm::LLessEqual(term1, term2) => display_binary_op(f, "<=", term1, term2),
499            AmlTerm::LGreaterEqual(term1, term2) => display_binary_op(f, ">=", term1, term2),
500            AmlTerm::LEqual(term1, term2) => display_binary_op(f, "==", term1, term2),
501            AmlTerm::LGreater(term1, term2) => display_binary_op(f, ">", term1, term2),
502            AmlTerm::LLess(term1, term2) => display_binary_op(f, "<", term1, term2),
503            AmlTerm::FindSetLeftBit(term, target) => {
504                display_func_like(f, "FindSetLeftBit", &[term, target])
505            }
506            AmlTerm::FindSetRightBit(term, target) => {
507                display_func_like(f, "FindSetRightBit", &[term, target])
508            }
509            AmlTerm::DerefOf(term_arg) => display_func_like(f, "DerefOf", &[term_arg]),
510            AmlTerm::ConcatRes(term1, term2, target) => {
511                display_func_like(f, "ConcatenateResTemplate", &[term1, term2, target])
512            }
513            AmlTerm::Mod(term1, term2, target) => {
514                display_target_assign(f, target, |f| display_binary_op(f, "%", term1, term2))
515            }
516            AmlTerm::Notify(target, term_arg) => {
517                display_func_like(f, "Notify", &[target, term_arg])
518            }
519            AmlTerm::Index(term1, term2, target) => display_target_assign(f, target, |f| {
520                term1.fmt(f)?;
521                write!(f, "[")?;
522                term2.fmt(f)?;
523                write!(f, "]")
524            }),
525            AmlTerm::Mutex(name, num) => {
526                write!(f, "Mutex({name}, 0x{num:02X})")
527            }
528            AmlTerm::Event(name) => display_func_like(f, "Event", &[name]),
529            AmlTerm::CondRefOf(src, dest) => display_func_like(f, "CondRefOf", &[src, dest]),
530            AmlTerm::CreateFieldOp(src, bit_index, num_bits, field_name) => {
531                display_func_like(f, "CreateFieldOp", &[src, bit_index, num_bits, field_name])
532            }
533            AmlTerm::Acquire(target, num) => {
534                // TODO: display number in hex, using maybe custom struct
535                display_func_like(f, "Acquire", &[target, &HexHolder(num)])
536            }
537            AmlTerm::Signal(target) => display_func_like(f, "Signal", &[target]),
538            AmlTerm::Wait(target, term) => display_func_like(f, "Wait", &[target, term]),
539            AmlTerm::Reset(target) => display_func_like(f, "Reset", &[target]),
540            AmlTerm::Release(target) => display_func_like(f, "Release", &[target]),
541            AmlTerm::Stall(term_arg) => display_func_like(f, "Stall", &[term_arg]),
542            AmlTerm::Sleep(term_arg) => display_func_like(f, "Sleep", &[term_arg]),
543            AmlTerm::CreateDWordField(term1, term2, name) => {
544                display_func_like(f, "CreateDWordField", &[term1, term2, name])
545            }
546            AmlTerm::CreateWordField(term1, term2, name) => {
547                display_func_like(f, "CreateWordField", &[term1, term2, name])
548            }
549            AmlTerm::CreateByteField(term1, term2, name) => {
550                display_func_like(f, "CreateByteField", &[term1, term2, name])
551            }
552            AmlTerm::CreateBitField(term1, term2, name) => {
553                display_func_like(f, "CreateBitField", &[term1, term2, name])
554            }
555            AmlTerm::CreateQWordField(term1, term2, name) => {
556                display_func_like(f, "CreateQWordField", &[term1, term2, name])
557            }
558            AmlTerm::MethodCall(name, args) => {
559                let mut d = AmlDisplayer::start(f, name);
560
561                for arg in args {
562                    d.paren_arg(|f| arg.fmt(f));
563                }
564
565                d.finish()
566            }
567            AmlTerm::ObjectType(obj) => display_func_like(f, "ObjectType", &[obj]),
568        }
569    }
570}
571
572impl fmt::Display for AmlCode {
573    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
574        for (i, term) in self.term_list.iter().enumerate() {
575            term.fmt(f)?;
576
577            if i < self.term_list.len() - 1 {
578                if f.alternate() {
579                    writeln!(f)?;
580                } else {
581                    write!(f, "; ")?;
582                }
583            }
584        }
585        Ok(())
586    }
587}