aml_value.bend
bend-osdev-acpi@0.1.1.0 · 388 lines · 39 definitions
1
2
3
4
5import Base
6import bend-osdev-word64@0.1.1.0/word64.bend as W
7import bend-osdev-bytes@0.1.1.0/bytes.bend as B
8import bend-osdev-acpi@0.1.1.0/error.bend as E
9
10
11type AmlLoc is Data:
12
13 AmlLName{path: String}
14 AmlLLocal{i: Nat}
15 AmlLArg{i: Nat}
16
17 AmlLIndex{base: AmlLoc, i: Nat}
18
19 AmlLElem{v: AmlValue, i: Nat}
20 AmlLDebug{}
21
22 AmlLNone{}
23
24type AmlValue is Data:
25 AmlUninit{}
26 AmlInt{v: W.W64}
27
28 AmlStr{s: B.Octets}
29 AmlBuf{b: B.Octets}
30 AmlPkg{xs: List<&2, AmlValue>}
31
32 AmlRef{loc: AmlLoc}
33
34
35 AmlObj{path: String, kind: U32}
36
37
38
39
40
41def AmlValue.type(v: AmlValue) -> U32:
42 match v:
43 case AmlUninit{}:
44 0
45 case AmlInt{x}:
46 1
47 case AmlStr{s}:
48 2
49 case AmlBuf{b}:
50 3
51 case AmlPkg{xs}:
52 4
53 case AmlRef{l}:
54 0
55 case AmlObj{p, k}:
56 k
57
58
59
60
61def AmlInt.fit(wide: Bool, +v: W.W64) -> W.W64:
62 match wide:
63 case True{}:
64 v
65 case False{}:
66 W.W64.from_u32(W.W64.lo(v))
67
68def AmlInt.ones(wide: Bool) -> W.W64:
69 AmlInt.fit(wide, W.W64.max())
70
71
72def AmlInt.of_bool(+wide: Bool, b: Bool) -> W.W64:
73 match b:
74 case True{}:
75 AmlInt.ones(wide)
76 case False{}:
77 W.W64.zero()
78
79def AmlInt.width_bytes(wide: Bool) -> Nat:
80 match wide:
81 case True{}:
82 8n
83 case False{}:
84 4n
85
86
87
88
89def val.le.go(n: Nat, xs: List<&2, U32>, +sh: Nat, acc: W.W64) -> W.W64:
90 match n:
91 case 0n:
92 acc
93 case 1n+p:
94 match xs:
95 case Nil{}:
96 acc
97 case Con{h, t}:
98 val.le.go(p, t, Nat.add(sh, 8n), W.W64.or(acc, W.W64.shl(W.W64.from_u32(U32.and(h, 255)), sh)))
99
100def val.hexdig.pick(d: Bool, u: Bool, l: Bool, +c: U32) -> Maybe<&2, U32>:
101 match d:
102 case True{}:
103 Some{U32.sub(c, 48)}
104 case False{}:
105 match u:
106 case True{}:
107 Some{U32.sub(c, 55)}
108 case False{}:
109 match l:
110 case True{}:
111 Some{U32.sub(c, 87)}
112 case False{}:
113 None{}
114
115def val.hexdig(+c: U32) -> Maybe<&2, U32>:
116 val.hexdig.pick(Bool.and(U32.is_le(48, c), U32.is_le(c, 57)), Bool.and(U32.is_le(65, c), U32.is_le(c, 70)), Bool.and(U32.is_le(97, c), U32.is_le(c, 102)), c)
117
118def val.decdig(+c: U32) -> Maybe<&2, U32>:
119 val.hexdig.pick(Bool.and(U32.is_le(48, c), U32.is_le(c, 57)), False{}, False{}, c)
120
121def val.dig.head(hex: Bool, xs: List<&2, U32>) -> Maybe<&2, U32>:
122 match hex xs:
123 case _ Nil{}:
124 None{}
125 case True{} Con{+h, t}:
126 val.hexdig(h)
127 case False{} Con{+h, t}:
128 val.decdig(h)
129
130def val.base(hex: Bool) -> W.W64:
131 match hex:
132 case True{}:
133 W.W64.from_u32(16)
134 case False{}:
135 W.W64.from_u32(10)
136
137
138
139
140def val.digits(n: Nat, xs: List<&2, U32>, m: Maybe<&2, U32>, acc: W.W64, +hex: Bool) -> W.W64:
141 match n:
142 case 0n:
143 acc
144 case 1n+p:
145 match xs:
146 case Nil{}:
147 acc
148 case Con{h, +t}:
149 match m:
150 case None{}:
151 acc
152 case Some{d}:
153 val.digits(p, t, val.dig.head(hex, t), W.W64.add(W.W64.mul(acc, val.base(hex)), W.W64.from_u32(d)), hex)
154
155def val.hex.parse(+wide: Bool, +xs: List<&2, U32>) -> W.W64:
156 val.digits(Nat.mul(2n, AmlInt.width_bytes(wide)), xs, val.dig.head(True{}, xs), W.W64.zero(), True{})
157
158def val.has0x(xs: List<&2, U32>) -> Bool:
159 match xs:
160 case Con{a, Con{+b, t}}:
161 Bool.and(U32.is_eq(a, 48), Bool.or(U32.is_eq(b, 120), U32.is_eq(b, 88)))
162 case _:
163 False{}
164
165def val.parse_int.pick(hex: Bool, +wide: Bool, +xs: List<&2, U32>) -> W.W64:
166 match hex:
167 case True{}:
168 AmlInt.fit(wide, val.hex.parse(wide, B.drop(2n, xs)))
169 case False{}:
170 AmlInt.fit(wide, val.digits(20n, xs, val.dig.head(False{}, xs), W.W64.zero(), False{}))
171
172
173
174
175
176
177def AmlValue.parse_int(+wide: Bool, +xs: List<&2, U32>) -> W.W64:
178 val.parse_int.pick(val.has0x(xs), wide, xs)
179
180def AmlValue.to_int(+wide: Bool, v: AmlValue) -> Result<&2, &2, E.AcpiError, W.W64>:
181 match v:
182 case AmlInt{x}:
183 Done{AmlInt.fit(wide, x)}
184 case AmlBuf{b}:
185 Done{val.le.go(AmlInt.width_bytes(wide), B.Octets.to_list(b), 0n, W.W64.zero())}
186 case AmlStr{s}:
187 Done{val.hex.parse(wide, B.Octets.to_list(s))}
188 case AmlUninit{}:
189 Fail{E.AcpiAmlBadType{"uninitialized value used as an integer"}}
190 case AmlPkg{xs}:
191 Fail{E.AcpiAmlBadType{"package used as an integer"}}
192 case AmlRef{l}:
193 Fail{E.AcpiAmlBadType{"reference used as an integer"}}
194 case AmlObj{p, k}:
195 Fail{E.AcpiAmlBadType{"object used as an integer"}}
196
197def val.int.bytes(wide: Bool, +x: W.W64) -> B.Octets:
198 match wide:
199 case True{}:
200 B.Octets.le64(x)
201 case False{}:
202 B.Octets.le32(W.W64.lo(x))
203
204
205
206def AmlValue.to_buf(+wide: Bool, v: AmlValue) -> Result<&2, &2, E.AcpiError, B.Octets>:
207 match v:
208 case AmlInt{x}:
209 Done{val.int.bytes(wide, x)}
210 case AmlBuf{b}:
211 Done{b}
212 case AmlStr{s}:
213 Done{B.Octets.append(s, B.Octets.of_list([0]))}
214 case _:
215 Fail{E.AcpiAmlBadType{"cannot convert to a buffer"}}
216
217def val.hex.digit.pick(lt: Bool, +d: U32) -> U32:
218 match lt:
219 case True{}:
220 U32.add(48, d)
221 case False{}:
222 U32.add(55, d)
223
224
225
226def val.hex.digit(+d: U32) -> U32:
227 val.hex.digit.pick(U32.is_lt(d, 10), d)
228
229def val.hex.text(n: Nat, +x: W.W64, acc: List<&2, U32>) -> List<&2, U32>:
230 match n:
231 case 0n:
232 acc
233 case 1n+p:
234 val.hex.text(p, W.W64.shr(x, 4n), Con{val.hex.digit(U32.and(W.W64.lo(x), 15)), acc})
235
236def val.buf.text(xs: List<&2, U32>, first: Bool) -> List<&2, U32>:
237 match xs:
238 case Nil{}:
239 Nil{}
240 case Con{+h, t}:
241 match first:
242 case True{}:
243 Con{val.hex.digit(U32.shrn(h, 4n)), Con{val.hex.digit(U32.and(h, 15)), val.buf.text(t, False{})}}
244 case False{}:
245 Con{32, Con{val.hex.digit(U32.shrn(h, 4n)), Con{val.hex.digit(U32.and(h, 15)), val.buf.text(t, False{})}}}
246
247
248
249def AmlValue.to_str(+wide: Bool, v: AmlValue) -> Result<&2, &2, E.AcpiError, B.Octets>:
250 match v:
251 case AmlInt{x}:
252 Done{B.Octets.of_list(val.hex.text(Nat.mul(2n, AmlInt.width_bytes(wide)), x, Nil{}))}
253 case AmlStr{s}:
254 Done{s}
255 case AmlBuf{b}:
256 Done{B.Octets.of_list(val.buf.text(B.Octets.to_list(b), True{}))}
257 case _:
258 Fail{E.AcpiAmlBadType{"cannot convert to a string"}}
259
260
261
262
263def val.cmp.then(prev: Cmp, c: Cmp) -> Cmp:
264 match prev:
265 case EQ{}:
266 c
267 case LT{}:
268 LT{}
269 case GT{}:
270 GT{}
271
272def val.cmp.go(xs: List<&2, U32>, ys: List<&2, U32>, prev: Cmp) -> Cmp:
273 match xs ys:
274 case Nil{} Nil{}:
275 prev
276 case Nil{} Con{y, t}:
277 val.cmp.then(prev, LT{})
278 case Con{x, t} Nil{}:
279 val.cmp.then(prev, GT{})
280 case Con{+x, xt} Con{+y, yt}:
281 val.cmp.go(xt, yt, val.cmp.then(prev, U32.cmp(x, y)))
282
283def val.bytes.cmp(xs: List<&2, U32>, ys: List<&2, U32>) -> Cmp:
284 val.cmp.go(xs, ys, EQ{})
285
286
287def AmlValue.compare(+wide: Bool, a: AmlValue, +b: AmlValue) -> Result<&2, &2, E.AcpiError, Cmp>:
288 match a:
289 case AmlInt{x}:
290 Result.map(&2, &2, E.AcpiError, W.W64, Cmp, y => W.W64.cmp(AmlInt.fit(wide, x), y), AmlValue.to_int(wide, b))
291 case AmlStr{s}:
292 Result.map(&2, &2, E.AcpiError, B.Octets, Cmp, t => val.bytes.cmp(B.Octets.to_list(s), B.Octets.to_list(t)), AmlValue.to_str(wide, b))
293 case AmlBuf{s}:
294 Result.map(&2, &2, E.AcpiError, B.Octets, Cmp, t => val.bytes.cmp(B.Octets.to_list(s), B.Octets.to_list(t)), AmlValue.to_buf(wide, b))
295 case _:
296 Fail{E.AcpiAmlBadType{"cannot compare"}}
297
298
299
300
301def val.lz.z(xs: List<&2, U32>) -> Bool:
302 match xs:
303 case Nil{}:
304 False{}
305 case Con{+h, +t}:
306 Bool.and(U32.is_eq(h, 48), Bool.not(List.is_empty(&2, U32, t)))
307
308
309def val.lz(xs: List<&2, U32>, still: Bool, z: Bool) -> List<&2, U32>:
310 match xs:
311 case Nil{}:
312 Nil{}
313 case Con{h, +t}:
314 match still:
315 case True{}:
316 match z:
317 case True{}:
318 val.lz(t, True{}, val.lz.z(t))
319 case False{}:
320 Con{h, val.lz(t, False{}, False{})}
321 case False{}:
322 Con{h, val.lz(t, False{}, False{})}
323
324def val.lower.pick(up: Bool, +h: U32) -> U32:
325 match up:
326 case True{}:
327 U32.add(h, 32)
328 case False{}:
329 h
330
331def val.lower(xs: List<&2, U32>) -> List<&2, U32>:
332 match xs:
333 case Nil{}:
334 Nil{}
335 case Con{+h, t}:
336 Con{val.lower.pick(U32.is_le(65, h), h), val.lower(t)}
337
338def AmlValue.show_int(+x: W.W64) -> String:
339 +ds = val.hex.text(16n, x, Nil{})
340 "0x" ++ B.to_string(val.lower(val.lz(ds, True{}, val.lz.z(ds))))
341
342def val.sep(first: Bool) -> String:
343 match first:
344 case True{}:
345 ""
346 case False{}:
347 ", "
348
349def val.ref.show(l: AmlLoc) -> String:
350 match l:
351 case AmlLName{p}:
352 "ref " ++ p
353 case AmlLLocal{i}:
354 "ref Local" ++ Nat.show(i)
355 case AmlLArg{i}:
356 "ref Arg" ++ Nat.show(i)
357 case AmlLIndex{b, i}:
358 "ref index " ++ Nat.show(i)
359 case AmlLElem{v, i}:
360 "ref element " ++ Nat.show(i)
361 case AmlLDebug{}:
362 "ref Debug"
363 case AmlLNone{}:
364 "ref none"
365
366def val.show.list(vs: List<&2, AmlValue>, +first: Bool) -> String:
367 match vs:
368 case Nil{}:
369 ""
370 case Con{v, rest}:
371 match v:
372 case AmlPkg{xs}:
373 val.sep(first) ++ "{" ++ val.show.list(xs, True{}) ++ "}" ++ val.show.list(rest, False{})
374 case AmlUninit{}:
375 val.sep(first) ++ "uninit" ++ val.show.list(rest, False{})
376 case AmlInt{x}:
377 val.sep(first) ++ AmlValue.show_int(x) ++ val.show.list(rest, False{})
378 case AmlStr{t}:
379 val.sep(first) ++ "\"" ++ B.Octets.to_string(t) ++ "\"" ++ val.show.list(rest, False{})
380 case AmlBuf{b}:
381 val.sep(first) ++ "buf[" ++ B.to_string(val.lower(val.buf.text(B.Octets.to_list(b), True{}))) ++ "]" ++ val.show.list(rest, False{})
382 case AmlRef{l}:
383 val.sep(first) ++ val.ref.show(l) ++ val.show.list(rest, False{})
384 case AmlObj{p, k}:
385 val.sep(first) ++ "object " ++ p ++ val.show.list(rest, False{})
386
387def AmlValue.show(v: AmlValue) -> String:
388 val.show.list([v], True{})