registry.bend

bend-osdev-acpi@0.1.0.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.0.0/bytes.bend as B
10import bend-osdev-acpi@0.1.0.0/error.bend as E
11import bend-osdev-acpi@0.1.0.0/header.bend as H
12import bend-osdev-acpi@0.1.0.0/rsdt.bend as S
13import bend-osdev-acpi@0.1.0.0/madt.bend as M
14import bend-osdev-acpi@0.1.0.0/fadt.bend as F
15import bend-osdev-acpi@0.1.0.0/hpet.bend as P
16import bend-osdev-acpi@0.1.0.0/mcfg.bend as C
17import bend-osdev-acpi@0.1.0.0/srat.bend as R
18import bend-osdev-acpi@0.1.0.0/slit.bend as L
19import bend-osdev-acpi@0.1.0.0/bgrt.bend as G
20import bend-osdev-acpi@0.1.0.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)