19// There are two paths, and a capability is what selects between them: the hardware path where the
20// part has the thing, the software path where it does not. Nothing keys on which build this is.
21//
22// Each is #ifndef, so a build states what it has by defining it. A detected vendor answers for its
23// silicon below; a build with no vendor answers 0 and turns one on with -DPROTOCORE_HAS_<X>=1, which is
24// how a suite drives a hardware path on a machine that has no hardware.
25//
26// test/core_setup/ tests these to decide which backend TU compiles, and src/ tests them where a software
27// path and a hardware path both exist. There is no weak symbol behind any of them - linking no
28// backend is an undefined reference, linking two is a duplicate definition, and both fail the build
29// rather than silently selecting one.
30
31// AES-GCM. 1 = the vendor supplies an accelerated AEAD (test/core_setup/hal/<vendor>); 0 = the portable
32// software backend, which is software AES plus a table GHASH.
33//
34// Not a small difference and not a preference: measured sealing 1 KiB on an ESP32-S3 at 240 MHz, the
35// vendor AEAD is 81,085 cycles and the software path 616,567 - 7.6x. Hand it to the vendor whenever
36// there is one; choosing software is legitimate where there is not, but it has to be chosen.
37#ifndef PROTOCORE_HAS_HW_AESGCM
38#error \
39 "ProtoCore: this vendor must state PROTOCORE_HAS_HW_AESGCM (1 = accelerated AEAD in test/core_setup/hal/<vendor>, 0 = portable software AES + table GHASH, ~7.6x slower where measured). Choosing software is fine; defaulting into it is not."
40#endif
41
42// DH-2048 / RSA modexp. 1 = the vendor supplies an accelerated backend; 0 = the portable software
43// Montgomery backend (test/core_setup/hal/portable), which is data-dependent and NOT constant time -
44// see SECURITY.md, timing.
45#ifndef PROTOCORE_HAS_HW_BIGNUM
46#error \
47 "ProtoCore: this vendor must state PROTOCORE_HAS_HW_BIGNUM (1 = accelerated backend in test/core_setup/hal/<vendor>, 0 = portable software Montgomery, which is not constant time). Choosing software crypto is fine; defaulting into it is not."
48#endif
49
50// SHA-1 / SHA-256 / SHA-512. 1 = the vendor supplies a hashing peripheral and a backend over it;
51// 0 = the portable software compression functions.
52//
53// One capability for the family: a part that ships a SHA block ships it for the digests it supports,
54// and a build that has to fall back for one of them falls back for all of them rather than mixing a
55// peripheral digest with a software one inside the same handshake transcript.
56#ifndef PROTOCORE_HAS_HW_SHA
57#error \
58 "ProtoCore: this vendor must state PROTOCORE_HAS_HW_SHA (1 = a hashing peripheral in test/core_setup/hal/<vendor>, 0 = the portable software compression functions). Choosing software is fine; defaulting into it is not."
59#endif
60
61// AES block, and the CTR / CMAC / CCM modes over it. 1 = the vendor supplies an AES peripheral;
62// 0 = the portable software AES.
63//
64// Separate from PROTOCORE_HAS_HW_AESGCM: GHASH is its own multiplier and a part can ship one without the
65// other, so a build states each. The block cipher is what this one answers for.
66#ifndef PROTOCORE_HAS_HW_AES
67#error \
68 "ProtoCore: this vendor must state PROTOCORE_HAS_HW_AES (1 = an AES peripheral in test/core_setup/hal/<vendor>, 0 = the portable software AES). Choosing software is fine; defaulting into it is not."
69#endif
70
71// X25519 and ECDSA over P-256. 1 = the vendor supplies an accelerated curve backend; 0 = the
72// portable software field arithmetic.
73//
74// Not the same axis as PROTOCORE_HAS_HW_BIGNUM: that one answers for modexp over a 2048-bit modulus, this
75// one for curve point math, and a part can accelerate either alone.
76#ifndef PROTOCORE_HAS_HW_ECC
77#error \
78 "ProtoCore: this vendor must state PROTOCORE_HAS_HW_ECC (1 = an accelerated curve backend in test/core_setup/hal/<vendor>, 0 = the portable software field arithmetic, which is not constant time on every curve). Choosing software is fine; defaulting into it is not."
79#endif
80
81// mDNS / DNS-SD. 1 = the vendor ships its own responder component and the wrapper drives that;
82// 0 = the portable responder in network_drivers/application/mdns_service, which answers over the
83// UDP listener like every other datagram service.
84//
85// The vendor's does more than advertise: probing, conflict resolution, IPv6 records. Take it where
86// it exists. The portable one is what makes the feature exist at all on a part that has none.
87#ifndef PROTOCORE_HAS_VENDOR_MDNS
88#error \
89 "ProtoCore: this vendor must state PROTOCORE_HAS_VENDOR_MDNS (1 = the SDK's own responder component, 0 = the portable responder over the UDP listener). Choosing the portable one is fine; defaulting into it is not."
90#endif
91
92// SNTP has no vendor seam: network_drivers/application/ntp_service is the client on every target. It
93// asks a server over the UDP listener, keeps the epoch in its own state, and hands it out through
94// protocore_ntp_epoch(); nothing in libc moves.
95
96// DNS resolution. 1 = the stack resolves names itself and the module marshals into it; 0 = the
97// portable resolver in network_drivers/network/dns, which asks over the UDP listener.
98//
99// A stack resolver already knows the nameservers DHCP handed it and caches what it learns. The
100// portable one asks PROTOCORE_DNS_SERVER, once per call, and keeps nothing.
101#ifndef PROTOCORE_HAS_VENDOR_DNS_RESOLVER
102#error \
103 "ProtoCore: this vendor must state PROTOCORE_HAS_VENDOR_DNS_RESOLVER (1 = the stack's own resolver, 0 = the portable resolver over the UDP listener). Choosing the portable one is fine; defaulting into it is not."
104#endif
105
106// WiFi driver. 1 = the SDK exposes the radio below the IP stack, which is what monitor mode and a
107// vendor peer-to-peer protocol need; 0 = there is none, and both refuse. Not the same axis as
108// having a network interface: a stack can carry IP over ethernet with no radio underneath it.
109#ifndef PROTOCORE_HAS_VENDOR_WIFI
110#error \
111 "ProtoCore: this vendor must state PROTOCORE_HAS_VENDOR_WIFI (1 = an SDK WiFi driver reachable below the IP stack, 0 = none, and monitor mode and the peer-to-peer radio refuse). Choosing none is fine; defaulting into it is not."
112#endif
113
114// A stack with pcbs to bind. 1 = there is one to open a socket on; 0 = there is none, and every
115// listener and outbound client refuses. The transport owners (tcp.h, udp.h) are portable either
116// way - this answers whether anything is underneath them.
117// Declared, not sniffed. Unlike the bus and pin seams, whose owners resolve to a refusing arm on
118// their own, turning this on compiles whole transport translation units into every consumer - so an
119// env states it and carries those sources, rather than inheriting it from a header being reachable.
120#ifndef PROTOCORE_HAS_NET_STACK
121#error \
122 "ProtoCore: this vendor must state PROTOCORE_HAS_NET_STACK (1 = a stack with pcbs to bind, 0 = none, and every listener and client refuses). Choosing none is fine; defaulting into it is not."
123#endif
124
125// Non-volatile key-value storage. 1 = the SDK keeps a key-value store across a reboot, which is
126// what provisioned credentials are written to; 0 = there is none and provisioning has nowhere to
127// put them.
128#ifndef PROTOCORE_HAS_VENDOR_NVS
129#error \
130 "ProtoCore: this vendor must state PROTOCORE_HAS_VENDOR_NVS (1 = an SDK key-value store that survives a reboot, 0 = none, and provisioning does not compile). Choosing none is fine; defaulting into it is not."
131#endif
132
133// An internal RAM segment a pool can overflow. 1 = link-time placement is bounded and a pool that
134// does not fit has to be moved or acknowledged; 0 = one address space, so the budget guards have
135// nothing to protect.
136#ifndef PROTOCORE_HAS_BOUNDED_DRAM
137#error \
138 "ProtoCore: this vendor must state PROTOCORE_HAS_BOUNDED_DRAM (1 = a bounded internal RAM segment the budget guards check, 0 = one address space). Choosing one address space is fine; defaulting into it is not."
139#endif
140
141// External RAM a pool can be placed in. 1 = the toolchain has an attribute that moves a BSS object
142// out of internal DRAM; 0 = there is one memory and a pool stays where it is declared. It answers
143// only for the attribute existing: whether a given board is wired for it, and whether a given pool
144// should use it, are the PROTOCORE_*_IN_PSRAM flags.
145#ifndef PROTOCORE_HAS_PSRAM
146#error \
147 "ProtoCore: this vendor must state PROTOCORE_HAS_PSRAM (1 = an external-RAM placement attribute in its toolchain, 0 = one memory, and every pool stays in it). Choosing one memory is fine; defaulting into it is not."
148#endif
149
150// I2C / SPI / UART master. 1 = there is a seam to drive; 0 = there is none and every bus owner
151// resolves to its refusing arm. It sits here rather than with the vendor capabilities above because
152// it reads the seam macro the block above establishes.
153#ifndef PROTOCORE_HAS_BUS
154#error \
155 "ProtoCore: this vendor must state PROTOCORE_HAS_BUS (1 = an I2C / SPI / UART master in test/core_setup/hal/<vendor>, 0 = none, and every bus owner refuses). Choosing none is fine; defaulting into it is not."
156#endif
157
158// Digital pins. 1 = there is a seam to drive; 0 = there is none and every pin driver resolves to its
159// refusing arm. Its own capability rather than a term of PROTOCORE_HAS_BUS: a part can carry pins without
160// carrying an I2C / SPI / UART master.
161#ifndef PROTOCORE_HAS_GPIO
162#error \
163 "ProtoCore: this vendor must state PROTOCORE_HAS_GPIO (1 = protocore_platform_gpio_mode / _read / _write in test/core_setup/hal/<vendor>, 0 = none, and every pin driver refuses). Choosing none is fine; defaulting into it is not."
164#endif
165
166// Tasks to run on. 1 = there is a scheduler, so the pipeline runs on its own worker and a delay
167// sleeps; 0 = there is one context, the pipeline runs inline from the caller's loop, and a delay
168// spins on the clock. It sits here rather than with the vendor capabilities above because it reads
169// the seam macro the driver block establishes.
170#ifndef PROTOCORE_HAS_SCHEDULER
171#error \
172 "ProtoCore: this vendor must state PROTOCORE_HAS_SCHEDULER (1 = tasks the pipeline can run on, 0 = one context and an inline pipeline). Choosing one context is fine; defaulting into it is not."
173#endif
174
175// A factory MAC to read. 1 = the SDK hands back a burned-in address the device identity is derived
176// from; 0 = there is none, and the identity comes from wherever the application puts it.
177#ifndef PROTOCORE_HAS_VENDOR_MAC
178#error \
179 "ProtoCore: this vendor must state PROTOCORE_HAS_VENDOR_MAC (1 = a burned-in address from the SDK, 0 = none). Choosing none is fine; defaulting into it is not."
180#endif
181
182// Heap and reset introspection. 1 = the SDK reports free / minimum-free heap and why the part last
183// reset, which the health readouts and the guardrails report; 0 = there is none and they report 0.
184#ifndef PROTOCORE_HAS_VENDOR_HEAP_INFO
185#error \
186 "ProtoCore: this vendor must state PROTOCORE_HAS_VENDOR_HEAP_INFO (1 = SDK heap and reset-reason readouts, 0 = none, and the health panel reports 0). Choosing none is fine; defaulting into it is not."
187#endif
188
189// Power management. 1 = the SDK reports why the part reset, sets the CPU clock, reads the die
190// temperature and gates a radio's power domain; 0 = there is none of that to bind to.
191#ifndef PROTOCORE_HAS_VENDOR_PM
192#error \
193 "ProtoCore: this vendor must state PROTOCORE_HAS_VENDOR_PM (1 = SDK reset-reason / CPU clock / die temperature / power-domain gating, 0 = none, and the power plan is advice with nothing to apply it to). Choosing none is fine; defaulting into it is not."
194#endif
195
196// A Bluetooth controller whose memory can be released. 1 = the SDK ships one; 0 = there is none and
197// there is nothing to release. Its own axis from CONFIG_BT_ENABLED, which says whether a given
198// build compiled it in.
199#ifndef PROTOCORE_HAS_VENDOR_BT
200#error \
201 "ProtoCore: this vendor must state PROTOCORE_HAS_VENDOR_BT (1 = an SDK Bluetooth controller, 0 = none). Choosing none is fine; defaulting into it is not."
202#endif
203
204// Self-update. 1 = the SDK ships an updater that writes the other app partition and flips the boot
205// selector; 0 = there is none, and the OTA service and the rollback policy have nothing to drive.
206#ifndef PROTOCORE_HAS_VENDOR_OTA
207#error \
208 "ProtoCore: this vendor must state PROTOCORE_HAS_VENDOR_OTA (1 = the SDK's own updater + boot selector, 0 = none, and the OTA service does not compile). Choosing none is fine; defaulting into it is not."
209#endif
210
211// Crash-image capture. 1 = the SDK writes a core dump to its own flash partition; 0 = there is none.
212// The decoder that reads one is portable and is not gated on this.
213#ifndef PROTOCORE_HAS_VENDOR_COREDUMP
214#error \
215 "ProtoCore: this vendor must state PROTOCORE_HAS_VENDOR_COREDUMP (1 = the SDK's own crash-image capture, 0 = none, and only the portable decoder compiles). Choosing none is fine; defaulting into it is not."
216#endif
217
218// CAN controller. 1 = the SDK ships a CAN / TWAI driver; 0 = there is none and the bus capture
219// refuses. The SocketCAN framing over it is portable and is not gated on this.
220#ifndef PROTOCORE_HAS_VENDOR_CAN
221#error \
222 "ProtoCore: this vendor must state PROTOCORE_HAS_VENDOR_CAN (1 = an SDK CAN / TWAI driver, 0 = none, and the bus capture refuses). Choosing none is fine; defaulting into it is not."