registry.bend
bend-osdev-acpi@0.1.2.0 · 210 lines · 0 definitions
1# bend-osdev-acpi, registry.bend: tables by signature. A registry maps each
2# signature to the parser that reads it; AcpiTable.parse checks a table
3# (length, checksum: header.bend) and hands it to the parser its signature
4# names. A new table plugs in two ways: map its signature to AcpiKRaw{} or to
5# one of the parsers here (AcpiRegistry.set), or give it a tag,
6# AcpiKExt{tag}, and pass a parser for it as the template argument of
7# AcpiTable.parse_with, which answers that parser's own type in AcpiTExt.
8import Base
9import bend-osdev-bytes@0.1.1.1/bytes.bend as B
10import bend-osdev-acpi@0.1.2.0/error.bend as E
11import bend-osdev-acpi@0.1.2.0/header.bend as H
12import bend-osdev-acpi@0.1.2.0/rsdt.bend as S
13import bend-osdev-acpi@0.1.2.0/madt.bend as M
14import bend-osdev-acpi@0.1.2.0/fadt.bend as F
15import bend-osdev-acpi@0.1.2.0/hpet.bend as P
16import bend-osdev-acpi@0.1.2.0/mcfg.bend as C
17import bend-osdev-acpi@0.1.2.0/srat.bend as R
18import bend-osdev-acpi@0.1.2.0/slit.bend as L
19import bend-osdev-acpi@0.1.2.0/bgrt.bend as G
20import bend-osdev-acpi@0.1.2.0/dsdt.bend as D
21
22# the parsers a signature can name
23type AcpiKind is Data:
24 AcpiKRsdt{}
25 AcpiKXsdt{}
26 AcpiKMadt{}
27 AcpiKFadt{}
28 AcpiKHpet{}
29 AcpiKMcfg{}
30 AcpiKSrat{}
31 AcpiKSlit{}
32 AcpiKBgrt{}
33 # DSDT, SSDT: the AML definition block, as bytes
34 AcpiKAml{}
35 # header and body, unread
36 AcpiKRaw{}
37 # the caller's parser (AcpiTable.parse_with), told this tag
38 AcpiKExt{tag: U32}
39
40type AcpiRegEntry is Data:
41 AcpiRegEntry{signature: B.Octets, kind: AcpiKind}
42
43type AcpiRegistry is Data:
44 AcpiRegistry{entries: List<&2, AcpiRegEntry>}
45
46def reg.e(s: String, k: AcpiKind) -> AcpiRegEntry:
47 AcpiRegEntry{B.Octets.of_string(s), k}
48
49# every table this package reads
50def AcpiRegistry.default() -> AcpiRegistry:
51 AcpiRegistry{[reg.e("RSDT", AcpiKRsdt{}), reg.e("XSDT", AcpiKXsdt{}), reg.e("APIC", AcpiKMadt{}), reg.e("FACP", AcpiKFadt{}), reg.e("HPET", AcpiKHpet{}), reg.e("MCFG", AcpiKMcfg{}), reg.e("SRAT", AcpiKSrat{}), reg.e("SLIT", AcpiKSlit{}), reg.e("BGRT", AcpiKBgrt{}), reg.e("DSDT", AcpiKAml{}), reg.e("SSDT", AcpiKAml{})]}
52
53# no parsers: every table raw
54def AcpiRegistry.empty() -> AcpiRegistry:
55 AcpiRegistry{Nil{}}
56
57def reg.lookup.pick(hit: Bool, k: AcpiKind, rest: AcpiKind) -> AcpiKind:
58 match hit:
59 case True{}:
60 k
61 case False{}:
62 rest
63
64def reg.lookup(es: List<&2, AcpiRegEntry>, +sig: B.Octets) -> AcpiKind:
65 match es:
66 case Nil{}:
67 AcpiKRaw{}
68 case Con{AcpiRegEntry{s, k}, t}:
69 reg.lookup.pick(B.Octets.is_eq(s, sig), k, reg.lookup(t, sig))
70
71# the parser for a signature (AcpiKRaw{} if the registry has none)
72def AcpiRegistry.lookup(r: AcpiRegistry, +sig: B.Octets) -> AcpiKind:
73 match r:
74 case AcpiRegistry{es}:
75 reg.lookup(es, sig)
76
77def reg.keep(hit: Bool, e: AcpiRegEntry, rest: List<&2, AcpiRegEntry>) -> List<&2, AcpiRegEntry>:
78 match hit:
79 case True{}:
80 rest
81 case False{}:
82 Con{e, rest}
83
84def reg.drop(es: List<&2, AcpiRegEntry>, +sig: B.Octets) -> List<&2, AcpiRegEntry>:
85 match es:
86 case Nil{}:
87 Nil{}
88 case Con{AcpiRegEntry{+s, k}, t}:
89 reg.keep(B.Octets.is_eq(s, sig), AcpiRegEntry{s, k}, reg.drop(t, sig))
90
91# the registry with sig mapped to k (replacing any earlier mapping)
92def AcpiRegistry.set(r: AcpiRegistry, +sig: B.Octets, k: AcpiKind) -> AcpiRegistry:
93 match r:
94 case AcpiRegistry{es}:
95 AcpiRegistry{Con{AcpiRegEntry{sig, k}, reg.drop(es, sig)}}
96
97# the registry without sig (its tables then read raw)
98def AcpiRegistry.remove(r: AcpiRegistry, +sig: B.Octets) -> AcpiRegistry:
99 match r:
100 case AcpiRegistry{es}:
101 AcpiRegistry{reg.drop(es, sig)}
102
103# A parsed table. X is the type the caller's extension parser answers
104# (AcpiNoExt when there is none).
105type AcpiTable<-X: Data> is Data:
106 AcpiTRsdt{t: S.AcpiSdtList}
107 AcpiTXsdt{t: S.AcpiSdtList}
108 AcpiTMadt{t: M.AcpiMadt}
109 AcpiTFadt{t: F.AcpiFadt}
110 AcpiTHpet{t: P.AcpiHpet}
111 AcpiTMcfg{t: C.AcpiMcfg}
112 AcpiTSrat{t: R.AcpiSrat}
113 AcpiTSlit{t: L.AcpiSlit}
114 AcpiTBgrt{t: G.AcpiBgrt}
115 AcpiTAml{t: D.AcpiAml}
116 AcpiTRaw{t: H.AcpiSdt}
117 AcpiTExt{tag: U32, x: X}
118
119type AcpiNoExt is Data:
120 AcpiNoExt{}
121
122# the extension parser of AcpiTable.parse: refuses every tag
123def AcpiNoExt.parse(tag: U32, t: H.AcpiSdt) -> Result<&2, &2, E.AcpiError, AcpiNoExt>:
124 Fail{E.AcpiBadSignature{H.AcpiHeader.signature(H.AcpiSdt.header(t))}}
125
126def reg.wrap(~X: Data, ~A: Data, ~f: A -> AcpiTable<X>, r: Result<&2, &2, E.AcpiError, A>) -> Result<&2, &2, E.AcpiError, AcpiTable<X>>:
127 match r:
128 case Fail{e}:
129 Fail{e}
130 case Done{a}:
131 Done{f(a)}
132
133def reg.ext(~X: Data, +tag: U32, r: Result<&2, &2, E.AcpiError, X>) -> Result<&2, &2, E.AcpiError, AcpiTable<X>>:
134 match r:
135 case Fail{e}:
136 Fail{e}
137 case Done{a}:
138 Done{AcpiTExt{tag, a}}
139
140def reg.dispatch(~X: Data, ~ext: U32 -> H.AcpiSdt -> Result<&2, &2, E.AcpiError, X>, k: AcpiKind, +t: H.AcpiSdt) -> Result<&2, &2, E.AcpiError, AcpiTable<X>>:
141 match k:
142 case AcpiKRsdt{}:
143 reg.wrap(~X, ~S.AcpiSdtList, ~(a => AcpiTRsdt{a}), S.AcpiRsdt.of_sdt(t))
144 case AcpiKXsdt{}:
145 reg.wrap(~X, ~S.AcpiSdtList, ~(a => AcpiTXsdt{a}), S.AcpiXsdt.of_sdt(t))
146 case AcpiKMadt{}:
147 reg.wrap(~X, ~M.AcpiMadt, ~(a => AcpiTMadt{a}), M.AcpiMadt.of_sdt(t))
148 case AcpiKFadt{}:
149 reg.wrap(~X, ~F.AcpiFadt, ~(a => AcpiTFadt{a}), F.AcpiFadt.of_sdt(t))
150 case AcpiKHpet{}:
151 reg.wrap(~X, ~P.AcpiHpet, ~(a => AcpiTHpet{a}), P.AcpiHpet.of_sdt(t))
152 case AcpiKMcfg{}:
153 reg.wrap(~X, ~C.AcpiMcfg, ~(a => AcpiTMcfg{a}), C.AcpiMcfg.of_sdt(t))
154 case AcpiKSrat{}:
155 reg.wrap(~X, ~R.AcpiSrat, ~(a => AcpiTSrat{a}), R.AcpiSrat.of_sdt(t))
156 case AcpiKSlit{}:
157 reg.wrap(~X, ~L.AcpiSlit, ~(a => AcpiTSlit{a}), L.AcpiSlit.of_sdt(t))
158 case AcpiKBgrt{}:
159 reg.wrap(~X, ~G.AcpiBgrt, ~(a => AcpiTBgrt{a}), G.AcpiBgrt.of_sdt(t))
160 case AcpiKAml{}:
161 reg.wrap(~X, ~D.AcpiAml, ~(a => AcpiTAml{a}), D.AcpiAml.of_sdt(t))
162 case AcpiKRaw{}:
163 Done{AcpiTRaw{t}}
164 case AcpiKExt{+tag}:
165 reg.ext(~X, tag, ext(tag, t))
166
167def reg.go(~X: Data, ~ext: U32 -> H.AcpiSdt -> Result<&2, &2, E.AcpiError, X>, +reg: AcpiRegistry, r: Result<&2, &2, E.AcpiError, H.AcpiSdt>) -> Result<&2, &2, E.AcpiError, AcpiTable<X>>:
168 match r:
169 case Fail{e}:
170 Fail{e}
171 case Done{+t}:
172 reg.dispatch(~X, ~ext, AcpiRegistry.lookup(reg, H.AcpiHeader.signature(H.AcpiSdt.header(t))), t)
173
174# the table at the front of o: checked (AcpiSdt.check: length and checksum),
175# then read by the parser the registry names for its signature, with ext
176# for AcpiKExt tags
177def AcpiTable.parse_with(~X: Data, ~ext: U32 -> H.AcpiSdt -> Result<&2, &2, E.AcpiError, X>, +reg: AcpiRegistry, +o: B.Octets) -> Result<&2, &2, E.AcpiError, AcpiTable<X>>:
178 reg.go(~X, ~ext, reg, H.AcpiSdt.parse(o))
179
180# the same without extension parsers
181def AcpiTable.parse(+reg: AcpiRegistry, +o: B.Octets) -> Result<&2, &2, E.AcpiError, AcpiTable<AcpiNoExt>>:
182 AcpiTable.parse_with(~AcpiNoExt, ~AcpiNoExt.parse, reg, o)
183
184# the name of the parser that read the table
185def AcpiTable.name(~X: Data, t: AcpiTable<X>) -> String:
186 match t:
187 case AcpiTRsdt{a}:
188 "RSDT"
189 case AcpiTXsdt{a}:
190 "XSDT"
191 case AcpiTMadt{a}:
192 "APIC"
193 case AcpiTFadt{a}:
194 "FACP"
195 case AcpiTHpet{a}:
196 "HPET"
197 case AcpiTMcfg{a}:
198 "MCFG"
199 case AcpiTSrat{a}:
200 "SRAT"
201 case AcpiTSlit{a}:
202 "SLIT"
203 case AcpiTBgrt{a}:
204 "BGRT"
205 case AcpiTAml{a}:
206 B.Octets.to_string(H.AcpiHeader.signature(D.AcpiAml.header(a)))
207 case AcpiTRaw{a}:
208 B.Octets.to_string(H.AcpiHeader.signature(H.AcpiSdt.header(a)))
209 case AcpiTExt{tag, x}:
210 "ext " ++ U32.show(tag)