check.bend
bend-osdev-acpi@0.1.0.0 · 339 lines · 0 definitions
1import Base
2import bend-osdev-word64@0.1.0.0/word64.bend as W
3import bend-osdev-bytes@0.1.0.0/bytes.bend as B
4import bend-osdev-acpi@0.1.0.0/error.bend as E
5import bend-osdev-acpi@0.1.0.0/checksum.bend as C
6import bend-osdev-acpi@0.1.0.0/header.bend as H
7import bend-osdev-acpi@0.1.0.0/rsdp.bend as P
8import bend-osdev-acpi@0.1.0.0/rsdt.bend as S
9import bend-osdev-acpi@0.1.0.0/fadt.bend as F
10import bend-osdev-acpi@0.1.0.0/gas.bend as G
11import bend-osdev-acpi@0.1.0.0/madt.bend as M
12import bend-osdev-acpi@0.1.0.0/hpet.bend as Hp
13import bend-osdev-acpi@0.1.0.0/mcfg.bend as Mc
14import bend-osdev-acpi@0.1.0.0/slit.bend as Sl
15import bend-osdev-acpi@0.1.0.0/dsdt.bend as D
16import bend-osdev-acpi@0.1.0.0/registry.bend as R
17import bend-osdev-acpi@0.1.0.0/acpi.bend as A
18import bend-osdev-acpi@0.1.0.0/aml_pkglength.bend as K
19import bend-osdev-acpi@0.1.0.0/aml_name.bend as N
20import bend-osdev-acpi@0.1.0.0/aml_term.bend as T
21import bend-osdev-acpi@0.1.0.0/aml_value.bend as V
22import bend-osdev-acpi@0.1.0.0/aml_host.bend as Hs
23import bend-osdev-acpi@0.1.0.0/aml_interp.bend as I
24import bend-osdev-acpi@0.1.0.0/aml.bend as Am
25import bend-osdev-acpi@0.1.0.0/aml_resource.bend as Rs
26import bend-osdev-acpi@0.1.0.0/aml_device.bend as Dv
27import bend-osdev-acpi@0.1.0.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