rsdt.bend

bend-osdev-acpi@0.1.1.0 · 106 lines · 16 definitions

1# bend-osdev-acpi, rsdt.bend: the Root and Extended System Description
2# Tables (ACPI 6.5, sections 5.2.7 and 5.2.8): a header, then the physical
3# addresses of the other tables, 4 bytes each in the RSDT ("RSDT"), 8 bytes
4# each in the XSDT ("XSDT"). Addresses are answered as W64 for both.
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
9import bend-osdev-acpi@0.1.1.0/header.bend as H
10import bend-osdev-acpi@0.1.1.0/fields.bend as F
11
12type AcpiSdtList is Data:
13  AcpiSdtList{header: H.AcpiHeader, entries: List<&2, W.W64>}
14
15def AcpiSdtList.entries(t: AcpiSdtList) -> List<&2, W.W64>:
16  match t:
17    case AcpiSdtList{h, es}:
18      es
19
20def AcpiSdtList.header(t: AcpiSdtList) -> H.AcpiHeader:
21  match t:
22    case AcpiSdtList{h, es}:
23      h
24
25def sl.rev(xs: List<&2, W.W64>, acc: List<&2, W.W64>) -> List<&2, W.W64>:
26  match xs:
27    case Nil{}:
28      acc
29    case Con{h, t}:
30      sl.rev(t, Con{h, acc})
31
32# n entries of width 4 or 8 bytes from the front of o
33def sl.read(n: Nat, wide: Bool, +o: B.Octets, acc: List<&2, W.W64>) -> List<&2, W.W64>:
34  match n:
35    case 0n:
36      sl.rev(acc, Nil{})
37    case 1n+p:
38      match wide:
39        case True{}:
40          sl.read(p, True{}, B.Octets.drop(8n, o), Con{F.AcpiF.u64(o, 0n), acc})
41        case False{}:
42          sl.read(p, False{}, B.Octets.drop(4n, o), Con{W.W64.from_u32(F.AcpiF.u32(o, 0n)), acc})
43
44def sl.width(wide: Bool) -> Nat:
45  match wide:
46    case True{}:
47      8n
48    case False{}:
49      4n
50
51def sl.body(ok: Bool, +wide: Bool, +h: H.AcpiHeader, +body: B.Octets) -> Result<&2, &2, E.AcpiError, AcpiSdtList>:
52  match ok:
53    case False{}:
54      Fail{E.AcpiBadSize{B.Octets.len(body)}}
55    case True{}:
56      Done{AcpiSdtList{h, sl.read(Nat.div(B.Octets.len(body), sl.width(wide)), wide, body, Nil{})}}
57
58# a checked table's body as entries; AcpiBadSize if it is not a whole
59# number of them
60def sl.of_sdt(+wide: Bool, t: H.AcpiSdt) -> Result<&2, &2, E.AcpiError, AcpiSdtList>:
61  match t:
62    case H.AcpiSdt{h, +body}:
63      sl.body(Nat.is_eq(Nat.mod(B.Octets.len(body), sl.width(wide)), 0n), wide, h, body)
64
65def AcpiRsdt.of_sdt(t: H.AcpiSdt) -> Result<&2, &2, E.AcpiError, AcpiSdtList>:
66  sl.of_sdt(False{}, t)
67
68def AcpiXsdt.of_sdt(t: H.AcpiSdt) -> Result<&2, &2, E.AcpiError, AcpiSdtList>:
69  sl.of_sdt(True{}, t)
70
71def sl.parse(+wide: Bool, r: Result<&2, &2, E.AcpiError, H.AcpiSdt>) -> Result<&2, &2, E.AcpiError, AcpiSdtList>:
72  match r:
73    case Fail{e}:
74      Fail{e}
75    case Done{t}:
76      sl.of_sdt(wide, t)
77
78def AcpiRsdt.parse(+o: B.Octets) -> Result<&2, &2, E.AcpiError, AcpiSdtList>:
79  sl.parse(False{}, H.AcpiSdt.parse_sig(B.Octets.of_string("RSDT"), o))
80
81def AcpiXsdt.parse(+o: B.Octets) -> Result<&2, &2, E.AcpiError, AcpiSdtList>:
82  sl.parse(True{}, H.AcpiSdt.parse_sig(B.Octets.of_string("XSDT"), o))
83
84def sl.enc(xs: List<&2, W.W64>, wide: Bool) -> List<&2, B.Octets>:
85  match xs:
86    case Nil{}:
87      Nil{}
88    case Con{h, t}:
89      match wide:
90        case True{}:
91          Con{B.Octets.le64(h), sl.enc(t, True{})}
92        case False{}:
93          Con{B.Octets.le32(W.W64.lo(h)), sl.enc(t, False{})}
94
95# the table (header from H.AcpiHeader.make or decoded; its signature is
96# replaced, its length and checksum computed). RSDT entries keep the low 32
97# bits of each address.
98def AcpiRsdt.build(h: H.AcpiHeader, xs: List<&2, W.W64>) -> B.Octets:
99  match h:
100    case H.AcpiHeader{s, l, r, c, o, t, orv, ci, cr}:
101      H.AcpiSdt.build(H.AcpiHeader{B.Octets.of_string("RSDT"), l, r, c, o, t, orv, ci, cr}, B.Octets.concat(sl.enc(xs, False{})))
102
103def AcpiXsdt.build(h: H.AcpiHeader, xs: List<&2, W.W64>) -> B.Octets:
104  match h:
105    case H.AcpiHeader{s, l, r, c, o, t, orv, ci, cr}:
106      H.AcpiSdt.build(H.AcpiHeader{B.Octets.of_string("XSDT"), l, r, c, o, t, orv, ci, cr}, B.Octets.concat(sl.enc(xs, True{})))