ZXFoundation™ 26h2
Loading...
Searching...
No Matches
protocol.cxxm
Go to the documentation of this file.
1/// SPDX-License-Identifier: Apache-2.0
2/// @file arch/s390x/init/zxfl/protocol.cxxm
3/// @brief ZXFoundationLoader boot protocol — kernel-side C++23 view.
4
5export module arch.s390x.init.zxfl.protocol;
6import arch.s390x.cpu.features;
7import zxfoundation.base.types;
8import zxfoundation.base.config;
9import crypto.sha256.core;
10import std;
11
12export {
13
14namespace arch::s390x::init::zxfl {
15
16 constexpr auto ZXFL_MAGIC = 0x5A58464CU;
17 constexpr auto ZXFL_VERSION_4 = 0x00000004U;
18 constexpr auto ZXFL_LOADER_MAJOR = 1U;
19 constexpr auto ZXFL_LOADER_MINOR = 0U;
20 constexpr auto ZXFL_SEED = 0xA5F0C3E1B2D49687UL;
21 constexpr auto ZXFL_OFFSET_KERNEL_STACK_TOP = 400U;
22
23 constexpr auto ZXFL_FLAG_SMP = 1U << 0;
24 constexpr auto ZXFL_FLAG_MEM_MAP = 1U << 1;
25 constexpr auto ZXFL_FLAG_CMDLINE = 1U << 2;
26 constexpr auto ZXFL_FLAG_LOWCORE = 1U << 3;
27 constexpr auto ZXFL_FLAG_STFLE = 1U << 4;
28 constexpr auto ZXFL_FLAG_SYSINFO = 1U << 5;
29 constexpr auto ZXFL_FLAG_TOD = 1U << 6;
30 constexpr auto ZXFL_FLAG_SCLP = 1U << 8;
31 constexpr auto ZXFL_FLAG_ECAG = 1U << 12;
32
33 constexpr auto ZXFL_MEM_MAP_MAX = 16U;
34 constexpr auto ZXFL_CPU_MAP_MAX = zxfoundation::base::config::CONFIG_ZX_MAX_CPUS;
35
36 constexpr auto ZXFL_MEM_USABLE = 0x01U;
37 constexpr auto ZXFL_MEM_RESERVED = 0x02U;
38 constexpr auto ZXFL_MEM_LOADER = 0x03U;
39 constexpr auto ZXFL_MEM_KERNEL = 0x04U;
40
41 constexpr auto ZXFL_MEMPROBE_UNKNOWN = 0;
42 constexpr auto ZXFL_MEMPROBE_SCLP = 1;
43 constexpr auto ZXFL_MEMPROBE_DIAG = 2;
44 constexpr auto ZXFL_MEMPROBE_TPROT = 3;
45
46 constexpr auto ZXFL_CPU_ONLINE = 0x01U;
47 constexpr auto ZXFL_CPU_STOPPED = 0x02U;
48 constexpr auto ZXFL_CPU_UNKNOWN = 0x00U;
49
50 /// @note This is NOT z/Architecture CPU Types, this is just ZXFL variables
51 constexpr auto ZXFL_CPU_TYPE_CP = 1U;
52 constexpr auto ZXFL_CPU_TYPE_IFL = 2U;
53 constexpr auto ZXFL_CPU_TYPE_ICF = 3U;
54 constexpr auto ZXFL_CPU_TYPE_ZIIP = 4U;
55 constexpr auto ZXFL_CPU_TYPE_ZAAP = 5U;
56 constexpr auto ZXFL_CPU_TYPE_UNKNOWN = 0xFFU;
57
58 constexpr auto ZXFL_CPU_EVIDENCE_NONE = 0x00U;
59 constexpr auto ZXFL_CPU_EVIDENCE_SIGP = 0x01U;
60 constexpr auto ZXFL_CPU_EVIDENCE_STSI = 0x02U;
61 constexpr auto ZXFL_CPU_EVIDENCE_FALLBACK = 0x04U;
62
63 constexpr auto ZXFL_LOWCORE_PHYS = 0x0ULL;
64
65 /// @brief One entry in the physical memory map.
66 struct mem_region {
67 u64 base{};
68 u64 length{};
69 u32 type{};
70 u8 numa_node{};
71 u8 _pad[3]{};
72 };
73
74 /// @brief One entry in the CPU map.
75 struct cpu_info {
76 u16 cpu_addr{};
77 u8 type{};
78 u8 state{};
79 u8 numa_node{};
80 u8 drawer_id{};
81 u8 book_id{};
82 u8 socket_id{};
83 u8 core_id{};
84 u8 smt_id{};
85 u8 topology_evidence{};
86 u8 capacity{};
87 };
88
89 /// @brief IPL type values for ipl_info::ipl_type.
90 constexpr auto IPL_TYPE_CCW = 0U;
91 constexpr auto IPL_TYPE_FCP = 1U;
92 constexpr auto IPL_TYPE_ECKD = 2U;
93 constexpr auto IPL_TYPE_NVME = 3U;
94 constexpr auto IPL_TYPE_UNKNOWN = 0xFFU;
95
96 /// @brief SCLP feature bit indices for sclp_info::feature_bits.
97 constexpr auto SCLP_FEAT_SIEF2 = 0U;
98 constexpr auto SCLP_FEAT_SIIF = 1U;
99 constexpr auto SCLP_FEAT_SIGPIF = 2U;
100 constexpr auto SCLP_FEAT_GPERF = 3U;
101 constexpr auto SCLP_FEAT_IB = 4U;
102 constexpr auto SCLP_FEAT_CEI = 5U;
103 constexpr auto SCLP_FEAT_SKEY = 6U;
104
105 /// @brief System identification — populated from STSI (EBCDIC converted to ASCII by loader).
106 struct systeminfo {
107 // STSI 1.1.1
108 char manufacturer[16]{};
109 char type[4]{};
110 char model[16]{};
111 char sequence[16]{};
112 char plant[4]{};
113 char model_capacity[16]{};
114 char model_perm_cap[16]{};
115 char model_temp_cap[16]{};
116 char model_var_cap[16]{};
117 u32 model_cap_rating{};
118 u32 model_perm_cap_rating{};
119 u32 model_temp_cap_rating{};
120 u32 model_var_cap_rating{};
121 u32 ncr{}, npr{}, ntr{}, nvr{};
122 u8 typepct[5]{};
123
124 // STSI 2.2.2
125 char lpar_name[8]{};
126 u16 lpar_number{};
127 u8 lpar_characteristics{};
128 u16 lpar_cpus_dedicated{};
129 u16 lpar_cpus_shared{};
130 u32 lpar_caf{};
131 u8 lpar_mt_installed{};
132 u8 lpar_mt_stid{};
133 u8 lpar_mt_gtid{};
134 u8 lpar_vsne{};
135 u8 lpar_uuid[16]{};
136
137 // STSI 1.2.2
138 u16 cpus_total{};
139 u16 cpus_configured{};
140 u16 cpus_standby{};
141 u16 cpus_reserved{};
142 u32 capability{};
143 u32 nominal_cap{};
144 u32 secondary_cap{};
145 };
146
147 /// @brief SCLP facility info detected by loader.
148 struct sclp_info {
149 u64 facilities{};
150 u32 max_cores{};
151 u32 mtid{};
152 u32 mtid_cp{};
153 u32 ibc{};
154 u64 rnmax{};
155 u64 rzm{};
156 u64 hamax{};
157 u64 hsa_size{};
158 u64 hmfai{};
159 u32 feature_bits{};
160 };
161
162 /// @brief ECAG CPU attributes.
163 struct ecag_info {
164 u32 cache_line_size{};
165 u32 cache_total_size{};
166 u32 cache_associativity{};
167 u32 _pad0{};
168 u16 numa_node{};
169 u16 socket_id{};
170 u16 core_id{};
171 u8 smt_id{};
172 u8 _pad1[9]{};
173 };
174
175 /// @brief System Modules - (sysmodule=N in parmfile)
176 struct sysmodule {
177 char name[32]{};
178 u64 phys_start{}; ///< Physical start of module
179 u64 size_bytes{};
180 };
181
182 /// @brief ZXFoundationLoader boot protocol. (C++-ify)
183 struct protocol {
184 u32 magic{};
185 u32 version{};
186 u32 flags{};
187 u32 _pad0{};
188
189 u64 binding_token{};
190
191 u16 loader_major{};
192 u16 loader_minor{};
193 u32 loader_timestamp{};
194 u64 loader_build_id{};
195
196 u32 ipl_schid{};
197 u16 ipl_dev_type{};
198 u16 ipl_dev_model{};
199 u32 _pad1{};
200 u32 _pad2{};
201
202 u64 kernel_phys_start{};
203 u64 kernel_phys_end{};
204 u64 kernel_entry{}; ///< Entry point (HHDM virtual address)
205
206 u64 mem_total_bytes{};
207 u64 mem_map_addr{}; ///< HHDM virtual address of mem_region[]
208 u32 mem_map_count{};
209 u8 mem_detect_source{}; ///< 0=none, 1=SCLP, 2=DIAG260, 3=TPROT
210 u8 _pad3[3]{};
211 u64 hhdm_phys_coverage_end{}; ///< Exclusive physical end covered by initial HHDM DAT.
212
213 u64 stfle_fac[cpu::features::STFLE_MAX_DWORDS]{};
214 u32 stfle_count{};
215 u32 _pad4{};
216
217 /// @brief Physical address of the BSP lowcore prefix area (always 0x0).
218 u64 lowcore_phys{};
219
220 u64 cmdline_addr{}; ///< HHDM virtual address of NUL-terminated cmdline
221 u32 cmdline_len{};
222 u32 _pad6{};
223
224 u64 kernel_stack_top{}; ///< HHDM virtual address of initial stack top
225
226 u64 cr0_snapshot{};
227 u64 cr1_snapshot{};
228 u64 cr13_snapshot{};
229
230 /// @brief Physical end (exclusive) of the loader's page-table bump pool.
231 /// The kernel PMM must not allocate from [kernel_phys_end, pgtbl_pool_end).
232 u64 pgtbl_pool_end{};
233
234 cpu_info cpu_map[ZXFL_CPU_MAP_MAX]{};
235 u32 cpu_count{};
236 u16 bsp_cpu_addr{};
237 u16 _pad7{};
238
239 systeminfo sysinfo;
240
241 u64 tod_boot{};
242
243 u32 module_count{};
244 u32 _pad8{};
245 sysmodule modules[16];
246
247 u64 cksum_table{};
248
249 /// @brief HHDM virtual address of the structural lock segment (converted by mmu.c).
250 u64 lock_phys{};
251
252 /// @brief SHA-256 of stage2 .text+.rodata+.data. Verified by kernel.
253 u8 loader_digest[32]{};
254
255 /// @brief HHDM virt addr of sclp_info struct
256 u64 sclp_info_addr{};
257
258 /// @brief HHDM virt addr of ecag_info struct
259 u64 ecag_info_addr{};
260 };
261
262 /// @brief Pretty-print a ZXFL memory region type.
263 [[nodiscard]] auto mem_type_str(u32 type) noexcept -> std::string_view {
264 switch (type) {
265 case ZXFL_MEM_USABLE: return "usable";
266 case ZXFL_MEM_RESERVED: return "reserved";
267 case ZXFL_MEM_LOADER: return "loader";
268 case ZXFL_MEM_KERNEL: return "kernel";
269 default: return "unknown";
270 }
271 }
272
273 /// @brief Pretty-print a ZXFL CPU state.
274 [[nodiscard]] auto cpu_state_str(u8 state) noexcept -> std::string_view {
275 switch (state) {
276 case ZXFL_CPU_ONLINE: return "online";
277 case ZXFL_CPU_STOPPED: return "stopped";
278 default: return "unknown";
279 }
280 }
281
282 /// @brief Pretty-print a ZXFL CPU type.
283 [[nodiscard]] auto cpu_type_str(u8 type) noexcept -> std::string_view {
284 switch (type) {
285 case ZXFL_CPU_TYPE_CP: return "CP";
286 case ZXFL_CPU_TYPE_IFL: return "IFL";
287 case ZXFL_CPU_TYPE_ICF: return "ICF";
288 case ZXFL_CPU_TYPE_ZIIP: return "zIIP";
289 case ZXFL_CPU_TYPE_ZAAP: return "zAAP";
290 case ZXFL_CPU_TYPE_UNKNOWN: return "unknown";
291 default: return "?";
292 }
293 }
294
295} // namespace arch::s390x::init::zxfl
296
297namespace arch::s390x::init::zxvl {
298
299 constexpr auto ZXVL_SEED = 0xA5F0C3E1B2D49687UL;
300 constexpr auto ZXVL_SEED_HI = 0xA5F0C3E1U;
301 constexpr auto ZXVL_SEED_LO = 0xB2D49687U;
302
303 constexpr auto ZXVL_HS_CHALLENGE = 0xFEEDFACECAFEBABEUL;
304 constexpr auto ZXVL_HS_RESPONSE = 0xDEADBEEF0BADF00DUL;
305 constexpr auto ZXVL_HS_RESPONSE_HI = 0xDEADBEEFU;
306 constexpr auto ZXVL_HS_RESPONSE_LO = 0x0BADF00DU;
307 constexpr auto ZXVL_PFLAGS_HS = 0x00400005U;
308 constexpr auto ZXVL_PFLAGS_ENTRY = 0x00800005U;
309
310 constexpr auto ZXVL_FRAME_MAGIC_A = 0xC0FFEE00FACADE42UL;
311 constexpr auto ZXVL_FRAME_MAGIC_B = 0x1337BABE0DDBA115UL;
312 constexpr auto ZXVL_FRAME_SIZE = 64U;
313
314 constexpr auto ZXVL_LOCK_MASK = 0x3C1E0F8704B2D596UL;
315 constexpr auto ZXVL_LOCK_EXPECTED = 0xF0A5C3B2E1D49687UL;
316 constexpr auto ZXVL_LOCK_EMBED_HI = 0xCCBBCC35U;
317 constexpr auto ZXVL_LOCK_EMBED_LO = 0xE5664311U;
318 constexpr auto ZXVL_LOCK_SENTINEL = 0x5A58464CU;
319 constexpr auto ZXVL_PFLAGS_LOCK = 0x00100006U;
320
321 constexpr auto ZXVL_CKSUM_MAGIC = 0x5A58564CU;
322 constexpr auto ZXVL_CKSUM_VERSION = 0x00000001U;
323 constexpr auto ZXVL_CKSUM_ALGO_SHA256 = 0x00000001U;
324 constexpr auto ZXVL_CKSUM_MAX_ENTRIES = 16U;
325 constexpr auto ZXVL_PFLAGS_CKSUM = 0x00200004U;
326
327 /// @brief Expected SHA-256 digest of the authorized stage2 loader.
328 inline constexpr u8 ZXFL_EXPECTED_DIGEST[crypto::sha256::SHA256_DIGEST_SIZE]{};
329 static_assert(sizeof(ZXFL_EXPECTED_DIGEST) == 32U,
330 "ZXFL_EXPECTED_DIGEST must be exactly 32 bytes");
331
332 [[nodiscard]] constexpr auto compute_token(u64 stfle0, u64 schid) noexcept -> u64 {
333 return ZXVL_SEED ^ stfle0 ^ schid;
334 }
335
336 struct [[gnu::packed]] checksum_entry {
337 u64 phys_start{};
338 u64 size{};
339 u8 digest[crypto::sha256::SHA256_DIGEST_SIZE]{};
340 };
341
342 struct [[gnu::packed]] checksum_table {
343 u32 magic{}, version{}, algo{}, count{};
344 checksum_entry entries[ZXVL_CKSUM_MAX_ENTRIES]{};
345 };
346
347 static_assert(sizeof(checksum_entry) == 48U,
348 "checksum_entry size mismatch vs zxvl_cksum_entry_t");
349 static_assert(sizeof(checksum_table) == 784U,
350 "checksum_table size mismatch vs zxvl_checksum_table_t");
351
352} // namespace arch::s390x::init::zxvl
353
354} // end export