Skip to main content

consortium_cfg/
error.rs

1// Copyright 2026 Ethan Wu
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// SPDX-License-Identifier: Apache-2.0
16
17use thiserror::Error;
18
19#[derive(Error, Debug, PartialEq, Eq, Clone, Hash)]
20pub enum CfgError {
21    #[error("failed to parse Consortium manifest: {0}")]
22    Manifest(String),
23
24    /// Chip-family database and per-core chip-map resolution errors, raised by
25    /// the `consortium-data` loaders.
26    #[error(transparent)]
27    Data(#[from] consortium_data::DataError),
28
29    /// A vendor device-tree source failed to parse while building the merged
30    /// Linux device tree.
31    #[error("failed to parse device-tree source '{file}': {detail}")]
32    DtsParse {
33        /// The offending file name.
34        file: String,
35        /// The parser's diagnostic.
36        detail: String,
37    },
38
39    #[error(
40        "doorbell '{name}' is not available on chip '{chip}'. Available doorbells: {available}. \
41         Refer to the TRM ({trm}). \
42         Sorry — customized hardware doorbells are not supported yet."
43    )]
44    UnknownDoorbell {
45        name: String,
46        chip: String,
47        /// Reference manual URL for the chip.
48        trm: String,
49        /// Pre-rendered list of supported doorbells with their TRM pages.
50        available: String,
51    },
52
53    #[error("peripheral '{0}' is owned by '{1}', which is not a core on chip '{2}'")]
54    OwnerNotVisible(String, String, String),
55
56    #[error(
57        "peripheral '{name}' is not accessible from core '{core}' on chip '{chip}'. \
58         Only peripherals present in that core's peripheral map may be assigned to it"
59    )]
60    PeripheralNotOnCore {
61        name: String,
62        core: String,
63        chip: String,
64    },
65
66    #[error(
67        "peripheral '{peripheral}' pin '{signal}': no pad on chip '{chip}' carries \
68         {function}. Pin keys are the signal names from the datasheet's alternate-function \
69         table (e.g. `tx`, `sda`, `mosi`)"
70    )]
71    PinSignalUnknown {
72        peripheral: String,
73        signal: String,
74        function: String,
75        chip: String,
76    },
77
78    #[error(
79        "peripheral '{peripheral}' pin '{signal}' = \"{pad}\": that pad cannot carry \
80         {function}. Pads that can: {allowed}"
81    )]
82    PinCannotCarry {
83        peripheral: String,
84        signal: String,
85        pad: String,
86        function: String,
87        allowed: String,
88    },
89
90    #[error(
91        "peripheral '{peripheral}' pin '{signal}' = \"{pad}\": pad is not bonded out in \
92         chip '{chip}''s {package} package"
93    )]
94    PinNotInPackage {
95        peripheral: String,
96        signal: String,
97        pad: String,
98        package: String,
99        chip: String,
100    },
101
102    #[error("pad \"{pad}\" is assigned twice: to {first} and to {second}")]
103    PinConflict {
104        pad: String,
105        first: String,
106        second: String,
107    },
108
109    #[error("IPC channel endpoint '{0}' names core '{1}', which is not visible on chip '{2}'")]
110    IpcEndpointNotVisible(String, String, String),
111
112    #[error(
113        "doorbell '{doorbell}' does not configure party '{party}' on chip '{chip}'. \
114         Configured parties: {available}. Check the doorbell party table in the TRM ({trm}) p. {page}"
115    )]
116    DoorbellPartyUnavailable {
117        doorbell: String,
118        party: String,
119        chip: String,
120        available: String,
121        trm: String,
122        page: u32,
123    },
124
125    #[error(
126        "doorbell '{doorbell}' channel {channel} is unavailable on chip '{chip}'. \
127         Valid channels are 0..{channels}. Check the channel table in the TRM ({trm}) p. {page}"
128    )]
129    DoorbellChannelUnavailable {
130        doorbell: String,
131        channel: u32,
132        channels: u32,
133        chip: String,
134        trm: String,
135        page: u32,
136    },
137
138    #[error(
139        "doorbell '{doorbell}' channel {channel} is assigned more than once: \
140         '{first_party}' and '{second_party}' both use it"
141    )]
142    DoorbellChannelDuplicate {
143        doorbell: String,
144        channel: u32,
145        first_party: String,
146        second_party: String,
147    },
148
149    #[error(
150        "[dbg.ap] is not allowed: the application processor is always the debug host, \
151         not a logger. Declare a coprocessor logger such as [dbg.cm33] instead"
152    )]
153    DbgHostNotLoggable,
154
155    #[error("[dbg.{core}] names core '{core}', which is not a coprocessor on chip '{chip}'")]
156    DbgCoreNotVisible { core: String, chip: String },
157
158    #[error("no memory region set")]
159    MemoryRegionNotSet,
160
161    #[error("UIO device '{device}' exposes {found} mappings, but Linux UIO supports at most {max}")]
162    UioMmapLimit {
163        device: String,
164        found: usize,
165        max: usize,
166    },
167
168    #[error(
169        "[memory.{region}] lies in chip '{chip}' memory region '{window}', which core '{core}' cannot access \
170         (accessible to: {visible}); move it to a region every core using it can reach"
171    )]
172    RegionNotVisible {
173        region: String,
174        window: String,
175        core: String,
176        visible: String,
177        chip: String,
178    },
179
180    #[error(
181        "[memory.{region}] spans {base:#x}..{end:#x}, which is not contained in any memory region of chip '{chip}'. \
182         Check the SRAM memory map in the TRM ({trm}) p. {pages}"
183    )]
184    RegionOutOfBounds {
185        region: String,
186        base: u32,
187        end: u32,
188        chip: String,
189        /// Reference manual URL for the chip.
190        trm: String,
191        /// Pre-rendered list of TRM pages documenting the memory map.
192        pages: String,
193    },
194
195    #[error(
196        "[memory.{a}] ({a_base:#x}..{a_end:#x}) overlaps [memory.{b}] ({b_base:#x}..{b_end:#x})"
197    )]
198    RegionOverlap {
199        a: String,
200        a_base: u32,
201        a_end: u32,
202        b: String,
203        b_base: u32,
204        b_end: u32,
205    },
206
207    #[error("[memory.{region}] has zero length")]
208    RegionEmpty { region: String },
209
210    #[error(
211        "[memory.{region}] ({base:#x}, len {length:#x}) is not a valid MPU region: {requirement}. \
212         ARMv7-M/ARMv8-M MPU regions must have a power-of-two size of at least 32 bytes, with the \
213         base aligned to the size"
214    )]
215    RegionNotMpuAligned {
216        region: String,
217        base: u32,
218        length: u32,
219        /// The specific constraint that failed.
220        requirement: &'static str,
221    },
222
223    #[error(
224        "[memory.{region}] ({base:#x}, len {length:#x}) is not cache-line aligned: {requirement}. \
225         Cached shared-memory regions must start and end on 64-byte boundaries"
226    )]
227    RegionNotCacheAligned {
228        region: String,
229        base: u32,
230        length: u32,
231        /// The specific constraint that failed.
232        requirement: &'static str,
233    },
234
235    #[error(
236        "ipc channel '{channel}' enables controller-side caching on '{core}', but only Cortex-M7 \
237         cores in the supported chip set have an L1 data cache"
238    )]
239    IpcCacheUnsupported { channel: String, core: String },
240
241    #[error(
242        "ipc channel '{channel}' shared-memory region is {length:#x} bytes, but MTU {mtu} requires \
243         at least {required:#x} bytes for the aligned descriptor and bidirectional slot pair"
244    )]
245    IpcRegionTooSmall {
246        channel: String,
247        length: u32,
248        mtu: u32,
249        required: usize,
250    },
251
252    #[error(
253        "ipc channel '{channel}' sets config.ack, so party '{party}' must declare an ack_chan:          acknowledgement needs a doorbell line of its own, because every line carries exactly          one waiter"
254    )]
255    IpcAckChannelMissing { channel: String, party: String },
256
257    #[error(
258        "ipc channel '{channel}' party '{party}' declares an ack_chan, but the channel does not          set config.ack"
259    )]
260    IpcAckChannelUnexpected { channel: String, party: String },
261}