1 # bend-osdev-acpi, show.bend: tables, errors and AML values as one line of 2 # text each, for logs and for the differential test (ref/gen.py writes the 3 # same text from its own reader). Numbers are decimal, 64-bit values 16 hex 4 # digits, byte strings hex. 5 import Base 6 import bend-osdev-word64@0.1.1.1/word64.bend as W 7 import bend-osdev-bytes@0.1.1.1/bytes.bend as B 8 import ./error.bend as E 9 import ./header.bend as H 10 import ./gas.bend as G 11 import ./rsdp.bend as P 12 import ./rsdt.bend as S 13 import ./madt.bend as M 14 import ./fadt.bend as F 15 import ./facs.bend as FS 16 import ./hpet.bend as Hp 17 import ./mcfg.bend as Mc 18 import ./srat.bend as Sr 19 import ./slit.bend as Sl 20 import ./bgrt.bend as Bg 21 import ./dsdt.bend as D 22 import ./registry.bend as R 23 24 def sh.u(+v: U32) -> String: 25 U32.show(v) 26 27 def sh.n(+v: Nat) -> String: 28 Nat.show(v) 29 30 def sh.w(+v: W.W64) -> String: 31 W.W64.show_hex(v) 32 33 def sh.x(o: B.Octets) -> String: 34 B.Octets.hex(o) 35 36 def sh.list(xs: List<&2, String>, sep: String) -> String: 37 String.join(xs, sep) 38 39 def AcpiShow.error(e: E.AcpiError) -> String: 40 match e: 41 case E.AcpiTooShort{n, g}: 42 "TooShort " ++ sh.n(n) ++ " " ++ sh.n(g) 43 case E.AcpiBadSignature{s}: 44 "BadSignature " ++ sh.x(s) 45 case E.AcpiBadLength{l}: 46 "BadLength " ++ sh.u(l) 47 case E.AcpiBadChecksum{s}: 48 "BadChecksum " ++ sh.u(s) 49 case E.AcpiRsdpBadChecksum{s}: 50 "RsdpBadChecksum " ++ sh.u(s) 51 case E.AcpiRsdpBadExtChecksum{s}: 52 "RsdpBadExtChecksum " ++ sh.u(s) 53 case E.AcpiBadRevision{r}: 54 "BadRevision " ++ sh.u(r) 55 case E.AcpiBadEntry{o, k}: 56 "BadEntry " ++ sh.n(o) ++ " " ++ sh.u(k) 57 case E.AcpiBadSize{n}: 58 "BadSize " ++ sh.n(n) 59 case E.AcpiNotMapped{a}: 60 "NotMapped " ++ sh.w(a) 61 case E.AcpiTableMissing{s}: 62 "TableMissing " ++ sh.x(s) 63 case E.AcpiAmlTruncated{}: 64 "AmlTruncated" 65 case E.AcpiAmlBadOpcode{c}: 66 "AmlBadOpcode " ++ sh.u(c) 67 case E.AcpiAmlBadPkgLength{}: 68 "AmlBadPkgLength" 69 case E.AcpiAmlBadName{}: 70 "AmlBadName" 71 case E.AcpiAmlUndefined{p}: 72 "AmlUndefined " ++ p 73 case E.AcpiAmlDuplicate{p}: 74 "AmlDuplicate " ++ p 75 case E.AcpiAmlBadOperand{c}: 76 "AmlBadOperand " ++ sh.u(c) 77 case E.AcpiAmlBadType{s}: 78 "AmlBadType" 79 case E.AcpiAmlRange{}: 80 "AmlRange" 81 case E.AcpiAmlDivZero{}: 82 "AmlDivZero" 83 case E.AcpiAmlBadControl{}: 84 "AmlBadControl" 85 case E.AcpiAmlFatal{t, c, a}: 86 "AmlFatal " ++ sh.u(t) ++ " " ++ sh.u(c) ++ " " ++ sh.w(a) 87 case E.AcpiAmlUnsupported{s}: 88 "AmlUnsupported " ++ s 89 case E.AcpiAmlStepLimit{}: 90 "AmlStepLimit" 91 case E.AcpiAmlHost{c}: 92 "AmlHost " ++ sh.u(c) 93 94 def AcpiShow.header(h: H.AcpiHeader) -> String: 95 match h: 96 case H.AcpiHeader{s, l, r, c, o, t, orv, ci, cr}: 97 sh.x(s) ++ " " ++ sh.u(l) ++ " " ++ sh.u(r) ++ " " ++ sh.u(c) ++ " " ++ sh.x(o) ++ " " ++ sh.x(t) ++ " " ++ sh.u(orv) ++ " " ++ sh.x(ci) ++ " " ++ sh.u(cr) 98 99 def AcpiShow.gas(g: G.AcpiGas) -> String: 100 G.AcpiGas.show(g) 101 102 def sh.rsdp.ext(m: Maybe<&2, P.AcpiRsdpExt>) -> String: 103 match m: 104 case None{}: 105 "none" 106 case Some{P.AcpiRsdpExt{l, x}}: 107 sh.u(l) ++ " " ++ sh.w(x) 108 109 def AcpiShow.rsdp(r: P.AcpiRsdp) -> String: 110 match r: 111 case P.AcpiRsdp{o, v, a, x}: 112 "RSDP " ++ sh.x(o) ++ " " ++ sh.u(v) ++ " " ++ sh.u(a) ++ " " ++ sh.rsdp.ext(x) 113 114 def sh.ws(xs: List<&2, W.W64>) -> List<&2, String>: 115 match xs: 116 case Nil{}: 117 Nil{} 118 case Con{h, t}: 119 Con{sh.w(h), sh.ws(t)} 120 121 def AcpiShow.sdt_list(t: S.AcpiSdtList) -> String: 122 match t: 123 case S.AcpiSdtList{h, es}: 124 "SDT [" ++ sh.list(sh.ws(es), ",") ++ "]" 125 126 def AcpiShow.madt_entry(e: M.AcpiMadtEntry) -> String: 127 match e: 128 case M.AcpiMadtLapic{u, a, f}: 129 "lapic " ++ sh.u(u) ++ " " ++ sh.u(a) ++ " " ++ sh.u(f) 130 case M.AcpiMadtIoApic{i, a, g}: 131 "ioapic " ++ sh.u(i) ++ " " ++ sh.u(a) ++ " " ++ sh.u(g) 132 case M.AcpiMadtIso{b, s, g, f}: 133 "iso " ++ sh.u(b) ++ " " ++ sh.u(s) ++ " " ++ sh.u(g) ++ " " ++ sh.u(f) 134 case M.AcpiMadtNmiSource{f, g}: 135 "nmisrc " ++ sh.u(f) ++ " " ++ sh.u(g) 136 case M.AcpiMadtLapicNmi{u, f, l}: 137 "lapicnmi " ++ sh.u(u) ++ " " ++ sh.u(f) ++ " " ++ sh.u(l) 138 case M.AcpiMadtLapicOverride{a}: 139 "override " ++ sh.w(a) 140 case M.AcpiMadtX2apic{x, f, u}: 141 "x2apic " ++ sh.u(x) ++ " " ++ sh.u(f) ++ " " ++ sh.u(u) 142 case M.AcpiMadtX2apicNmi{f, u, l}: 143 "x2nmi " ++ sh.u(f) ++ " " ++ sh.u(u) ++ " " ++ sh.u(l) 144 case M.AcpiMadtGicc{ci, u, f, pv, pg, vg, M.AcpiGiccAddrs{pk, b, gv, gh, gr}, mp, ec, sp, tr}: 145 "gicc " ++ sh.u(ci) ++ " " ++ sh.u(u) ++ " " ++ sh.u(f) ++ " " ++ sh.u(pv) ++ " " ++ sh.u(pg) ++ " " ++ sh.u(vg) ++ " " ++ sh.w(pk) ++ " " ++ sh.w(b) ++ " " ++ sh.w(gv) ++ " " ++ sh.w(gh) ++ " " ++ sh.w(gr) ++ " " ++ sh.w(mp) ++ " " ++ sh.u(ec) ++ " " ++ sh.u(sp) ++ " " ++ sh.u(tr) 146 case M.AcpiMadtGicd{i, b, v}: 147 "gicd " ++ sh.u(i) ++ " " ++ sh.w(b) ++ " " ++ sh.u(v) 148 case M.AcpiMadtGicMsi{i, b, f, c, s}: 149 "gicmsi " ++ sh.u(i) ++ " " ++ sh.w(b) ++ " " ++ sh.u(f) ++ " " ++ sh.u(c) ++ " " ++ sh.u(s) 150 case M.AcpiMadtGicr{b, l}: 151 "gicr " ++ sh.w(b) ++ " " ++ sh.u(l) 152 case M.AcpiMadtGicIts{i, b}: 153 "gicits " ++ sh.u(i) ++ " " ++ sh.w(b) 154 case M.AcpiMadtWakeup{v, m}: 155 "wakeup " ++ sh.u(v) ++ " " ++ sh.w(m) 156 case M.AcpiMadtOther{k, d}: 157 "other " ++ sh.u(k) ++ " " ++ sh.x(d) 158 159 def sh.madt.es(es: List<&2, M.AcpiMadtEntry>) -> List<&2, String>: 160 match es: 161 case Nil{}: 162 Nil{} 163 case Con{h, t}: 164 Con{AcpiShow.madt_entry(h), sh.madt.es(t)} 165 166 def AcpiShow.madt(m: M.AcpiMadt) -> String: 167 match m: 168 case M.AcpiMadt{h, a, f, es}: 169 "MADT " ++ sh.u(a) ++ " " ++ sh.u(f) ++ " [" ++ sh.list(sh.madt.es(es), "; ") ++ "]" 170 171 def sh.fadt.core(c: F.AcpiFadtCore) -> String: 172 match c: 173 case F.AcpiFadtCore{fc, d, im, pp, sci, smi, en, dis, s4, ps, F.AcpiFadtBlocks{e1a, e1b, c1a, c1b, c2, tm, g0, g1}, F.AcpiFadtLens{le, lc, l2, lt, lg0, lg1, gb}, cst, p2, p3, fs, fst, doff, dw, da, ma, ce, ia, fl}: 174 sh.list([sh.u(fc), sh.u(d), sh.u(im), sh.u(pp), sh.u(sci), sh.u(smi), sh.u(en), sh.u(dis), sh.u(s4), sh.u(ps), sh.u(e1a), sh.u(e1b), sh.u(c1a), sh.u(c1b), sh.u(c2), sh.u(tm), sh.u(g0), sh.u(g1), sh.u(le), sh.u(lc), sh.u(l2), sh.u(lt), sh.u(lg0), sh.u(lg1), sh.u(gb), sh.u(cst), sh.u(p2), sh.u(p3), sh.u(fs), sh.u(fst), sh.u(doff), sh.u(dw), sh.u(da), sh.u(ma), sh.u(ce), sh.u(ia), sh.u(fl)], ",") 175 176 def sh.fadt.ext(m: Maybe<&2, F.AcpiFadtExt>) -> String: 177 match m: 178 case None{}: 179 "none" 180 case Some{F.AcpiFadtExt{rr, rv, ab, mv, xfc, xd, F.AcpiFadtX{e1a, e1b, c1a, c1b, c2, tm, g0, g1}}}: 181 sh.list([AcpiShow.gas(rr), sh.u(rv), sh.u(ab), sh.u(mv), sh.w(xfc), sh.w(xd), AcpiShow.gas(e1a), AcpiShow.gas(e1b), AcpiShow.gas(c1a), AcpiShow.gas(c1b), AcpiShow.gas(c2), AcpiShow.gas(tm), AcpiShow.gas(g0), AcpiShow.gas(g1)], ",") 182 183 def sh.fadt.sleep(m: Maybe<&2, F.AcpiFadtSleep>) -> String: 184 match m: 185 case None{}: 186 "none" 187 case Some{F.AcpiFadtSleep{c, s}}: 188 AcpiShow.gas(c) ++ "," ++ AcpiShow.gas(s) 189 190 def sh.fadt.hyp(m: Maybe<&2, W.W64>) -> String: 191 match m: 192 case None{}: 193 "none" 194 case Some{v}: 195 sh.w(v) 196 197 def AcpiShow.fadt(+f: F.AcpiFadt) -> String: 198 match f: 199 case F.AcpiFadt{h, c, x, s, v}: 200 "FADT " ++ sh.fadt.core(c) ++ " ext " ++ sh.fadt.ext(x) ++ " sleep " ++ sh.fadt.sleep(s) ++ " hyp " ++ sh.fadt.hyp(v) ++ " dsdt " ++ sh.w(F.AcpiFadt.dsdt_address(f)) ++ " facs " ++ sh.w(F.AcpiFadt.facs_address(f)) ++ " pm1a " ++ AcpiShow.gas(F.AcpiFadt.block(f, F.AcpiFadtPm1aEvt{})) 201 202 def AcpiShow.facs(f: FS.AcpiFacs) -> String: 203 match f: 204 case FS.AcpiFacs{l, hs, wv, gl, fl, xw, v, of}: 205 "FACS " ++ sh.list([sh.u(l), sh.u(hs), sh.u(wv), sh.u(gl), sh.u(fl), sh.w(xw), sh.u(v), sh.u(of)], " ") 206 207 def AcpiShow.hpet(t: Hp.AcpiHpet) -> String: 208 match t: 209 case Hp.AcpiHpet{h, id, g, n, m, p}: 210 "HPET " ++ sh.u(id) ++ " " ++ AcpiShow.gas(g) ++ " " ++ sh.u(n) ++ " " ++ sh.u(m) ++ " " ++ sh.u(p) 211 212 def sh.mcfg.es(es: List<&2, Mc.AcpiMcfgEntry>) -> List<&2, String>: 213 match es: 214 case Nil{}: 215 Nil{} 216 case Con{Mc.AcpiMcfgEntry{b, s, lo, hi}, t}: 217 Con{sh.w(b) ++ " " ++ sh.u(s) ++ " " ++ sh.u(lo) ++ " " ++ sh.u(hi), sh.mcfg.es(t)} 218 219 def AcpiShow.mcfg(m: Mc.AcpiMcfg) -> String: 220 match m: 221 case Mc.AcpiMcfg{h, es}: 222 "MCFG [" ++ sh.list(sh.mcfg.es(es), "; ") ++ "]" 223 224 def AcpiShow.srat_entry(e: Sr.AcpiSratEntry) -> String: 225 match e: 226 case Sr.AcpiSratLapic{d, a, f, s, c}: 227 "lapic " ++ sh.u(d) ++ " " ++ sh.u(a) ++ " " ++ sh.u(f) ++ " " ++ sh.u(s) ++ " " ++ sh.u(c) 228 case Sr.AcpiSratMemory{d, b, l, f}: 229 "mem " ++ sh.u(d) ++ " " ++ sh.w(b) ++ " " ++ sh.w(l) ++ " " ++ sh.u(f) 230 case Sr.AcpiSratX2apic{d, x, f, c}: 231 "x2apic " ++ sh.u(d) ++ " " ++ sh.u(x) ++ " " ++ sh.u(f) ++ " " ++ sh.u(c) 232 case Sr.AcpiSratGicc{d, u, f, c}: 233 "gicc " ++ sh.u(d) ++ " " ++ sh.u(u) ++ " " ++ sh.u(f) ++ " " ++ sh.u(c) 234 case Sr.AcpiSratGicIts{d, i}: 235 "its " ++ sh.u(d) ++ " " ++ sh.u(i) 236 case Sr.AcpiSratGeneric{k, ht, d, hd, f}: 237 "gen " ++ sh.u(k) ++ " " ++ sh.u(ht) ++ " " ++ sh.u(d) ++ " " ++ sh.x(hd) ++ " " ++ sh.u(f) 238 case Sr.AcpiSratOther{k, d}: 239 "other " ++ sh.u(k) ++ " " ++ sh.x(d) 240 241 def sh.srat.es(es: List<&2, Sr.AcpiSratEntry>) -> List<&2, String>: 242 match es: 243 case Nil{}: 244 Nil{} 245 case Con{h, t}: 246 Con{AcpiShow.srat_entry(h), sh.srat.es(t)} 247 248 def AcpiShow.srat(s: Sr.AcpiSrat) -> String: 249 match s: 250 case Sr.AcpiSrat{h, es}: 251 "SRAT [" ++ sh.list(sh.srat.es(es), "; ") ++ "]" 252 253 def AcpiShow.slit(s: Sl.AcpiSlit) -> String: 254 match s: 255 case Sl.AcpiSlit{h, n, m}: 256 "SLIT " ++ sh.n(n) ++ " " ++ sh.x(m) 257 258 def AcpiShow.bgrt(t: Bg.AcpiBgrt) -> String: 259 match t: 260 case Bg.AcpiBgrt{h, v, st, it, a, x, y}: 261 "BGRT " ++ sh.u(v) ++ " " ++ sh.u(st) ++ " " ++ sh.u(it) ++ " " ++ sh.w(a) ++ " " ++ sh.u(x) ++ " " ++ sh.u(y) 262 263 def AcpiShow.aml(t: D.AcpiAml) -> String: 264 match t: 265 case D.AcpiAml{h, a}: 266 "AML " ++ sh.n(B.Octets.len(a)) 267 268 # a table read through a registry: its header, then its parser's dump 269 def AcpiShow.table(~X: Data, t: R.AcpiTable) -> String: 270 match t: 271 case R.AcpiTRsdt{a}: 272 AcpiShow.sdt_list(a) 273 case R.AcpiTXsdt{a}: 274 AcpiShow.sdt_list(a) 275 case R.AcpiTMadt{a}: 276 AcpiShow.madt(a) 277 case R.AcpiTFadt{a}: 278 AcpiShow.fadt(a) 279 case R.AcpiTHpet{a}: 280 AcpiShow.hpet(a) 281 case R.AcpiTMcfg{a}: 282 AcpiShow.mcfg(a) 283 case R.AcpiTSrat{a}: 284 AcpiShow.srat(a) 285 case R.AcpiTSlit{a}: 286 AcpiShow.slit(a) 287 case R.AcpiTBgrt{a}: 288 AcpiShow.bgrt(a) 289 case R.AcpiTAml{a}: 290 AcpiShow.aml(a) 291 case R.AcpiTRaw{H.AcpiSdt{h, b}}: 292 "RAW " ++ sh.n(B.Octets.len(b)) 293 case R.AcpiTExt{tag, x}: 294 "EXT " ++ sh.u(tag) 295 296 def AcpiShow.result(~X: Data, r: Result<&2, &2, E.AcpiError, R.AcpiTable>) -> String: 297 match r: 298 case Done{t}: 299 AcpiShow.table(~X, t) 300 case Fail{e}: 301 AcpiShow.error(e)