1 import Base 2 import bend-osdev-word64@0.1.0.0/word64.bend as W 3 import bend-osdev-bytes@0.1.0.0/bytes.bend as B 4 import ./error.bend as E 5 import ./checksum.bend as C 6 import ./header.bend as H 7 import ./rsdp.bend as P 8 import ./rsdt.bend as S 9 import ./fadt.bend as F 10 import ./gas.bend as G 11 import ./madt.bend as M 12 import ./hpet.bend as Hp 13 import ./mcfg.bend as Mc 14 import ./slit.bend as Sl 15 import ./dsdt.bend as D 16 import ./registry.bend as R 17 import ./acpi.bend as A 18 import ./aml_pkglength.bend as K 19 import ./aml_name.bend as N 20 import ./aml_term.bend as T 21 import ./aml_value.bend as V 22 import ./aml_host.bend as Hs 23 import ./aml_interp.bend as I 24 import ./aml.bend as Am 25 import ./aml_resource.bend as Rs 26 import ./aml_device.bend as Dv 27 import ./example.bend as X 28 29 def 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 64 def loaded(l: A.AcpiLoaded) -> 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 71 def loadeds(ls: List<&2, A.AcpiLoaded>) -> List<&2, String>: 72 match ls: 73 case Nil{}: 74 Nil{} 75 case Con{h, t}: 76 Con{loaded(h), loadeds(t)} 77 78 def tables(r: Result<&2, &2, E.AcpiError, A.AcpiTableSet>) -> 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 87 def 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 102 def 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 109 def 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 116 def 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 123 def 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 130 def 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 137 def 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 144 def mu(m: Maybe<&2, U32>) -> String: 145 match m: 146 case Some{a}: 147 U32.show(a) 148 case None{}: 149 "none" 150 151 def 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 158 def 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 165 def 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 172 def 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 180 def 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 185 def boot(r: Result<&2, &2, E.AcpiError, Am.AmlSystem>) -> Am.AmlSystem: 186 match r: 187 case Done{s}: 188 s 189 case Fail{e}: 190 Am.Aml.mem_system(True{}) 191 192 def sys() -> Am.AmlSystem: 193 boot(Am.Aml.boot(~Hs.AmlMemHost, ~Hs.AmlMemHost.io, I.AmlOptions.default(), X.AcpiExample.host(), [X.AcpiExample.dsdt(), X.AcpiExample.ssdt()], 100000n)) 194 195 def 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 202 def ev(+s: Am.AmlSystem, 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 206 def 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 215 def 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 222 def devs(+s: Am.AmlSystem, 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 229 def 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 236 def 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 243 def 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 250 def 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 257 def 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 264 def note(+s: Am.AmlSystem, p: String) -> String: 265 String.join(notes(Am.AmlOutcome.notes(Hs.AmlMemHost, Am.Aml.eval_mem(s, p, Nil{}, 1000n))), "; ") 266 267 def log(+s: Am.AmlSystem, 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 271 def 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 277 def 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: 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