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 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}