check.bend

bend-osdev-acpi@0.1.1.0 · 339 lines · 33 definitions

1import Base
2import bend-osdev-word64@0.1.1.0/word64.bend as W
3import bend-osdev-bytes@0.1.1.0/bytes.bend as B
4import bend-osdev-acpi@0.1.1.0/error.bend as E
5import bend-osdev-acpi@0.1.1.0/checksum.bend as C
6import bend-osdev-acpi@0.1.1.0/header.bend as H
7import bend-osdev-acpi@0.1.1.0/rsdp.bend as P
8import bend-osdev-acpi@0.1.1.0/rsdt.bend as S
9import bend-osdev-acpi@0.1.1.0/fadt.bend as F
10import bend-osdev-acpi@0.1.1.0/gas.bend as G
11import bend-osdev-acpi@0.1.1.0/madt.bend as M
12import bend-osdev-acpi@0.1.1.0/hpet.bend as Hp
13import bend-osdev-acpi@0.1.1.0/mcfg.bend as Mc
14import bend-osdev-acpi@0.1.1.0/slit.bend as Sl
15import bend-osdev-acpi@0.1.1.0/dsdt.bend as D
16import bend-osdev-acpi@0.1.1.0/registry.bend as R
17import bend-osdev-acpi@0.1.1.0/acpi.bend as A
18import bend-osdev-acpi@0.1.1.0/aml_pkglength.bend as K
19import bend-osdev-acpi@0.1.1.0/aml_name.bend as N
20import bend-osdev-acpi@0.1.1.0/aml_term.bend as T
21import bend-osdev-acpi@0.1.1.0/aml_value.bend as V
22import bend-osdev-acpi@0.1.1.0/aml_host.bend as Hs
23import bend-osdev-acpi@0.1.1.0/aml_interp.bend as I
24import bend-osdev-acpi@0.1.1.0/aml.bend as Am
25import bend-osdev-acpi@0.1.1.0/aml_resource.bend as Rs
26import bend-osdev-acpi@0.1.1.0/aml_device.bend as Dv
27import bend-osdev-acpi@0.1.1.0/example.bend as X
28
29def err(e: E.AcpiError) -> String:
30  match e:
31    case E.AcpiTooShort{n, g}:
32      "too short " ++ Nat.show(n) ++ " " ++ Nat.show(g)
33    case E.AcpiBadSignature{s}:
34      "bad signature " ++ B.Octets.to_string(s)
35    case E.AcpiBadLength{l}:
36      "bad length " ++ U32.show(l)
37    case E.AcpiBadChecksum{s}:
38      "bad checksum " ++ U32.show(s)
39    case E.AcpiRsdpBadChecksum{s}:
40      "bad RSDP checksum " ++ U32.show(s)
41    case E.AcpiNotMapped{a}:
42      "not mapped " ++ W.W64.show_hex(a)
43    case E.AcpiAmlUndefined{p}:
44      "undefined " ++ p
45    case E.AcpiAmlStepLimit{}:
46      "step limit"
47    case E.AcpiAmlBadOpcode{c}:
48      "bad opcode " ++ U32.show(c)
49    case E.AcpiAmlBadOperand{c}:
50      "bad operand " ++ U32.show(c)
51    case E.AcpiAmlBadType{s}:
52      "bad type " ++ s
53    case E.AcpiAmlDuplicate{p}:
54      "duplicate " ++ p
55    case E.AcpiAmlUnsupported{s}:
56      "unsupported " ++ s
57    case E.AcpiAmlTruncated{}:
58      "truncated"
59    case E.AcpiAmlRange{}:
60      "range"
61    case _:
62      "error"
63
64def loaded(l: A.AcpiLoaded<R.AcpiNoExt>) -> String:
65  match l:
66    case A.AcpiLoaded{a, Done{t}}:
67      W.W64.show_hex(a) ++ " " ++ R.AcpiTable.name(~R.AcpiNoExt, t)
68    case A.AcpiLoaded{a, Fail{e}}:
69      W.W64.show_hex(a) ++ " " ++ err(e)
70
71def loadeds(ls: List<&2, A.AcpiLoaded<R.AcpiNoExt>>) -> List<&2, String>:
72  match ls:
73    case Nil{}:
74      Nil{}
75    case Con{h, t}:
76      Con{loaded(h), loadeds(t)}
77
78def tables(r: Result<&2, &2, E.AcpiError, A.AcpiTableSet<R.AcpiNoExt>>) -> String:
79  match r:
80    case Done{A.AcpiTableSet{rp, root, ts, Some{Done{f}}}}:
81      String.join(loadeds(ts), ", ") ++ "; FACS ok"
82    case Done{A.AcpiTableSet{rp, root, ts, f}}:
83      String.join(loadeds(ts), ", ") ++ "; no FACS"
84    case Fail{e}:
85      err(e)
86
87def madt.e(e: M.AcpiMadtEntry) -> String:
88  match e:
89    case M.AcpiMadtLapic{u, a, f}:
90      "lapic " ++ U32.show(a)
91    case M.AcpiMadtIoApic{i, a, g}:
92      "ioapic " ++ U32.show(i) ++ " at " ++ U32.show(a)
93    case M.AcpiMadtIso{b, s, g, f}:
94      "irq " ++ U32.show(s) ++ "->" ++ U32.show(g) ++ "/" ++ U32.show(f)
95    case M.AcpiMadtLapicNmi{u, f, l}:
96      "nmi lint" ++ U32.show(l)
97    case M.AcpiMadtX2apic{x, f, u}:
98      "x2apic " ++ U32.show(x)
99    case _:
100      "other"
101
102def madt.es(es: List<&2, M.AcpiMadtEntry>) -> List<&2, String>:
103  match es:
104    case Nil{}:
105      Nil{}
106    case Con{h, t}:
107      Con{madt.e(h), madt.es(t)}
108
109def madt(r: Result<&2, &2, E.AcpiError, M.AcpiMadt>) -> String:
110  match r:
111    case Done{+m}:
112      W.W64.show_hex(M.AcpiMadt.lapic_address(m)) ++ ": " ++ String.join(madt.es(M.AcpiMadt.entries(m)), ", ")
113    case Fail{e}:
114      err(e)
115
116def fadt(r: Result<&2, &2, E.AcpiError, F.AcpiFadt>) -> String:
117  match r:
118    case Done{+f}:
119      "dsdt " ++ W.W64.show_hex(F.AcpiFadt.dsdt_address(f)) ++ " pm1a_evt " ++ G.AcpiGas.show(F.AcpiFadt.block(f, F.AcpiFadtPm1aEvt{})) ++ " pm1b_cnt " ++ G.AcpiGas.show(F.AcpiFadt.block(f, F.AcpiFadtPm1bCnt{})) ++ " reduced " ++ Bool.show(F.AcpiFadt.hw_reduced(f))
120    case Fail{e}:
121      err(e)
122
123def hpet(r: Result<&2, &2, E.AcpiError, Hp.AcpiHpet>) -> String:
124  match r:
125    case Done{+h}:
126      "vendor " ++ U32.show(Hp.AcpiHpet.vendor_id(h)) ++ " comparators " ++ U32.show(Hp.AcpiHpet.comparators(h)) ++ " 64-bit " ++ Bool.show(Hp.AcpiHpet.counter_64(h))
127    case Fail{e}:
128      err(e)
129
130def mw(m: Maybe<&2, W.W64>) -> String:
131  match m:
132    case Some{a}:
133      W.W64.show_hex(a)
134    case None{}:
135      "none"
136
137def mcfg(r: Result<&2, &2, E.AcpiError, Mc.AcpiMcfg>) -> String:
138  match r:
139    case Done{+m}:
140      mw(Mc.AcpiMcfg.ecam_address(m, 0, 0, 31, 0, 96)) ++ " " ++ mw(Mc.AcpiMcfg.ecam_address(m, 1, 0, 0, 0, 0))
141    case Fail{e}:
142      err(e)
143
144def mu(m: Maybe<&2, U32>) -> String:
145  match m:
146    case Some{a}:
147      U32.show(a)
148    case None{}:
149      "none"
150
151def slit(r: Result<&2, &2, E.AcpiError, Sl.AcpiSlit>) -> String:
152  match r:
153    case Done{+s}:
154      mu(Sl.AcpiSlit.distance(s, 0n, 1n)) ++ " " ++ mu(Sl.AcpiSlit.distance(s, 1n, 1n)) ++ " " ++ mu(Sl.AcpiSlit.distance(s, 2n, 0n))
155    case Fail{e}:
156      err(e)
157
158def sdt(r: Result<&2, &2, E.AcpiError, B.Octets>) -> String:
159  match r:
160    case Done{o}:
161      "ok " ++ Nat.show(B.Octets.len(o))
162    case Fail{e}:
163      err(e)
164
165def rsdp(r: Result<&2, &2, E.AcpiError, P.AcpiRsdp>) -> String:
166  match r:
167    case Done{+p}:
168      "revision " ++ U32.show(P.AcpiRsdp.revision(p)) ++ " xsdt " ++ W.W64.show_hex(P.AcpiRsdp.xsdt_address(p))
169    case Fail{e}:
170      err(e)
171
172def mn(m: Maybe<&2, Nat>) -> String:
173  match m:
174    case Some{n}:
175      Nat.show(n)
176    case None{}:
177      "none"
178
179# a byte of o changed
180def poke(+o: B.Octets, +i: Nat, +b: U32) -> B.Octets:
181  B.Octets.concat([B.Octets.take(i, o), B.Octets.of_list([b]), B.Octets.drop(1n+i, o)])
182
183# AML
184
185def boot(r: Result<&2, &2, E.AcpiError, Am.AmlSystem<Hs.AmlMemHost>>) -> Am.AmlSystem<Hs.AmlMemHost>:
186  match r:
187    case Done{s}:
188      s
189    case Fail{e}:
190      Am.Aml.mem_system(True{})
191
192def sys() -> Am.AmlSystem<Hs.AmlMemHost>:
193  boot(Am.Aml.boot(~Hs.AmlMemHost, ~Hs.AmlMemHost.io, I.AmlOptions.default(), X.AcpiExample.host(), [X.AcpiExample.dsdt(), X.AcpiExample.ssdt()], 100000n))
194
195def val(r: Result<&2, &2, E.AcpiError, V.AmlValue>) -> String:
196  match r:
197    case Done{v}:
198      V.AmlValue.show(v)
199    case Fail{e}:
200      err(e)
201
202def ev(+s: Am.AmlSystem<Hs.AmlMemHost>, p: String, args: List<&2, V.AmlValue>, n: Nat) -> String:
203  +o = Am.Aml.eval_mem(s, p, args, n)
204  val(Am.AmlOutcome.result(Hs.AmlMemHost, o)) ++ " in " ++ Nat.show(Am.AmlOutcome.steps(Hs.AmlMemHost, o)) ++ " steps"
205
206def hid(m: Maybe<&2, Result<&2, &2, E.AcpiError, String>>) -> String:
207  match m:
208    case None{}:
209      "-"
210    case Some{Done{s}}:
211      s
212    case Some{Fail{e}}:
213      err(e)
214
215def sta(r: Result<&2, &2, E.AcpiError, W.W64>) -> String:
216  match r:
217    case Done{x}:
218      V.AmlValue.show_int(x)
219    case Fail{e}:
220      err(e)
221
222def devs(+s: Am.AmlSystem<Hs.AmlMemHost>, ps: List<&2, String>) -> List<&2, String>:
223  match ps:
224    case Nil{}:
225      Nil{}
226    case Con{+p, t}:
227      Con{p ++ " " ++ hid(Dv.AmlDevice.hid(~Hs.AmlMemHost, ~Hs.AmlMemHost.io, s, p, 1000n)) ++ " " ++ sta(Dv.AmlDevice.status(~Hs.AmlMemHost, ~Hs.AmlMemHost.io, s, p, 1000n)), devs(s, t)}
228
229def res.list(xs: List<&2, Rs.AmlResource>) -> List<&2, String>:
230  match xs:
231    case Nil{}:
232      Nil{}
233    case Con{h, t}:
234      Con{Rs.AmlResource.show(h), res.list(t)}
235
236def crs(r: Result<&2, &2, E.AcpiError, List<&2, Rs.AmlResource>>) -> String:
237  match r:
238    case Done{xs}:
239      String.join(res.list(xs), "; ")
240    case Fail{e}:
241      err(e)
242
243def prt.list(xs: List<&2, Dv.AmlPrtEntry>) -> List<&2, String>:
244  match xs:
245    case Nil{}:
246      Nil{}
247    case Con{Dv.AmlPrtEntry{a, p, s, i}, t}:
248      Con{V.AmlValue.show_int(a) ++ " pin " ++ U32.show(p) ++ " " ++ s ++ " " ++ U32.show(i), prt.list(t)}
249
250def prt(r: Result<&2, &2, E.AcpiError, List<&2, Dv.AmlPrtEntry>>) -> String:
251  match r:
252    case Done{xs}:
253      String.join(prt.list(xs), "; ")
254    case Fail{e}:
255      err(e)
256
257def notes(xs: List<&2, I.AmlNote>) -> List<&2, String>:
258  match xs:
259    case Nil{}:
260      Nil{}
261    case Con{I.AmlNote{p, v}, t}:
262      Con{"Notify(" ++ p ++ ", " ++ V.AmlValue.show_int(v) ++ ")", notes(t)}
263
264def note(+s: Am.AmlSystem<Hs.AmlMemHost>, p: String) -> String:
265  String.join(notes(Am.AmlOutcome.notes(Hs.AmlMemHost, Am.Aml.eval_mem(s, p, Nil{}, 1000n))), "; ")
266
267def log(+s: Am.AmlSystem<Hs.AmlMemHost>, p: String) -> String:
268  Hs.AmlMemHost.show_log(Am.AmlOutcome.host(Hs.AmlMemHost, Am.Aml.eval_mem(s, p, Nil{}, 1000n)))
269
270# a 32-bit definition block: integers are 32 bits wide
271def narrow() -> String:
272  +s = Am.Aml.mem_system(False{})
273  +lo = Am.Aml.load_mem(s, T.AmlT.encode([T.AmlT.method("ONES", 0n, False{}, [T.AmlT.ret(T.AmlT.add(T.AmlT.ones(), T.AmlT.one(), T.AmlT.none()))]), T.AmlT.method("NOT_", 0n, False{}, [T.AmlT.ret(T.AmlT.not(T.AmlT.zero(), T.AmlT.none()))])]), 1000n)
274  +s2 = Am.AmlSystem.after(Hs.AmlMemHost, s, lo)
275  ev(s2, "\\ONES", Nil{}, 100n) ++ ", " ++ ev(s2, "\\NOT_", Nil{}, 100n)
276
277def main() -> IO(Unit):
278  +mem = X.AcpiExample.memory()
279  +s = sys()
280  +madt_o = M.AcpiMadt.build(X.AcpiExample.madt())
281  +rsdp_o = P.AcpiRsdp.build(X.AcpiExample.rsdp())
282  do IO<Unit>:
283    IO.print("rsdp at " ++ mn(P.AcpiRsdp.find(B.Octets.append(B.Octets.zeros(16n), rsdp_o))))
284    IO.print(rsdp(P.AcpiRsdp.parse(rsdp_o)))
285    IO.print(rsdp(P.AcpiRsdp.parse(poke(rsdp_o, 10n, 0))))
286    IO.print(tables(A.AcpiTables.load(~A.AcpiMemImage, ~A.AcpiMemImage.read, mem, X.AcpiExample.rsdp_address())))
287    IO.print(tables(A.AcpiTables.load_with(~A.AcpiMemImage, ~A.AcpiMemImage.read, ~R.AcpiNoExt, ~R.AcpiNoExt.parse, A.AcpiLoadOptions{False{}, R.AcpiRegistry.empty()}, mem, X.AcpiExample.rsdp_address())))
288    IO.print(madt(M.AcpiMadt.parse(madt_o)))
289    IO.print(sdt(H.AcpiSdt.check(madt_o)))
290    IO.print(sdt(H.AcpiSdt.check(poke(madt_o, 40n, 7))))
291    IO.print(sdt(H.AcpiSdt.check(B.Octets.take(30n, madt_o))))
292    IO.print(fadt(F.AcpiFadt.parse(F.AcpiFadt.build(X.AcpiExample.fadt()))))
293    IO.print(hpet(Hp.AcpiHpet.parse(Hp.AcpiHpet.build(X.AcpiExample.hpet()))))
294    IO.print(mcfg(Mc.AcpiMcfg.parse(Mc.AcpiMcfg.build(X.AcpiExample.mcfg()))))
295    IO.print(slit(Sl.AcpiSlit.parse(Sl.AcpiSlit.build(X.AcpiExample.slit()))))
296    IO.print(B.Octets.hex(K.AmlPkgLength.encode(63)) ++ " " ++ B.Octets.hex(K.AmlPkgLength.encode(64)) ++ " " ++ B.Octets.hex(K.AmlPkgLength.encode(4095)) ++ " " ++ B.Octets.hex(K.AmlPkgLength.encode(4096)) ++ " " ++ B.Octets.hex(K.AmlPkgLength.encode(268435455)))
297    IO.print(B.Octets.hex(N.AmlName.encode(N.AmlName.of_text("\\_SB.PCI0.LPCB"))) ++ " " ++ B.Octets.hex(N.AmlName.encode(N.AmlName.of_text("^^_STA"))))
298    IO.print(B.Octets.hex(T.AmlT.encode1(T.AmlT.name("_HID", T.AmlT.eisaid("PNP0A03")))) ++ " " ++ Dv.AmlEisaId.text(T.AmlT.eisaid_value("PNP0C0F")))
299    IO.print(String.join(devs(s, Dv.AmlDevice.list(Am.AmlSystem.ns(Hs.AmlMemHost, s))), ", "))
300    IO.print(crs(Dv.AmlDevice.crs(~Hs.AmlMemHost, ~Hs.AmlMemHost.io, s, "\\_SB_.PCI0", 1000n)))
301    IO.print(crs(Dv.AmlDevice.crs(~Hs.AmlMemHost, ~Hs.AmlMemHost.io, s, "\\_SB_.LNKA", 1000n)))
302    IO.print(log(s, "\\_SB_.LNKA._CRS"))
303    IO.print(prt(Dv.AmlDevice.prt(~Hs.AmlMemHost, ~Hs.AmlMemHost.io, s, "\\_SB_.PCI0", 1000n)))
304    IO.print(ev(s, "\\_TZ_.TZ00._TMP", Nil{}, 1000n))
305    IO.print(ev(s, "\\_SB_.SUM_", [V.AmlInt{W.W64.from_u32(100)}], 100000n))
306    IO.print(ev(s, "\\_SB_.OSYS", Nil{}, 1000n))
307    IO.print(note(s, "\\_SB_.PCI0.LPCB.EC0_._Q01"))
308    IO.print(ev(s, "\\_SB_.SPIN", Nil{}, 1000n))
309    IO.print(ev(s, "\\_SB_.NONE", Nil{}, 1000n))
310    IO.print(narrow())
311
312#|rsdp at 16
313#|revision 2 xsdt 0000000000100000
314#|bad RSDP checksum 187
315#|0000000000100200 FACP, 0000000000100500 APIC, 0000000000100600 HPET, 0000000000100680 MCFG, 0000000000100700 SRAT, 0000000000100800 SLIT, 0000000000100880 BGRT, 0000000000100900 SSDT, 0000000000100c00 DSDT; FACS ok
316#|0000000000100200 FACP, 0000000000100500 APIC, 0000000000100600 HPET, 0000000000100680 MCFG, 0000000000100700 SRAT, 0000000000100800 SLIT, 0000000000100880 BGRT, 0000000000100900 SSDT; no FACS
317#|00000000fee00000: lapic 0, lapic 1, ioapic 2 at 4273995776, irq 0->2/0, irq 9->9/13, nmi lint1, x2apic 256
318#|ok 114
319#|bad checksum 6
320#|bad length 114
321#|dsdt 0000000000100c00 pm1a_evt {1 32 0 0 0000000000000600} pm1b_cnt {1 16 0 0 0000000000000000} reduced False
322#|vendor 32902 comparators 3 64-bit True
323#|00000000e00f8060 none
324#|21 10 none
325#|3f 4004 4fff 800001 cfffffff
326#|5c2f035f53425f504349304c504342 5e5e5f535441
327#|085f4849440c41d00a03 PNP0C0F
328#|\_SB_ - 0xf, \_SB_.CPU0 ACPI0007 0xf, \_SB_.LNKA PNP0C0F 0xb, \_SB_.PCI0 PNP0A08 0xf, \_SB_.PCI0.GFX0 - 0xf, \_SB_.PCI0.LPCB - 0xf, \_SB_.PCI0.LPCB.EC0_ PNP0C09 0xf, \_SB_.PWRB PNP0C0C 0xf
329#|addr16 type 2 0000000000000000-00000000000000ff len 0000000000000100; io 3320-3320 align 1 len 8; addr16 type 1 0000000000000000-0000000000000cf7 len 0000000000000cf8; addr32 type 0 0000000080000000-00000000febfffff len 000000007ec00000
330#|irq mask 2048 flags 24
331#|read 2:0000001f00000060/8
332#|0x1ffff pin 0 \_SB_.LNKA 0; 0x1ffff pin 1  17; 0x1effff pin 0  16
333#|0xbd8 in 15 steps
334#|0x13ba in 2145 steps
335#|0x7df in 26 steps
336#|Notify(\_TZ_.TZ00, 0x80)
337#|step limit in 1000 steps
338#|undefined \_SB_.NONE in 0 steps
339#|0x0 in 9 steps, 0xffffffff in 7 steps