1/*
2 * Copyright (c) 2000-2021 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_FREE_COPYRIGHT@
30 */
31
32#include <pexpert/pexpert.h>
33#include <pexpert/protos.h>
34#include <pexpert/device_tree.h>
35#include <kern/debug.h>
36
37#include <libkern/section_keywords.h>
38
39#if CONFIG_SPTM
40#include <sptm/sptm_xnu.h>
41#endif
42
43#if defined(__arm64__)
44SECURITY_READ_ONLY_LATE(static uint32_t) gPEKernelConfigurationBitmask;
45#else
46static uint32_t gPEKernelConfigurationBitmask;
47#endif
48
49int32_t gPESerialBaud = -1;
50
51int debug_cpu_performance_degradation_factor = 1;
52
53void
54pe_init_debug(void)
55{
56 boolean_t boot_arg_value;
57
58 gPEKernelConfigurationBitmask = 0;
59
60 if (!PE_parse_boot_argn(arg_string: "assertions", arg_ptr: &boot_arg_value, max_arg: sizeof(boot_arg_value))) {
61#if MACH_ASSERT
62 boot_arg_value = TRUE;
63#else
64 boot_arg_value = FALSE;
65#endif
66 }
67 gPEKernelConfigurationBitmask |= (boot_arg_value ? kPEICanHasAssertions : 0);
68
69 if (!PE_parse_boot_argn(arg_string: "statistics", arg_ptr: &boot_arg_value, max_arg: sizeof(boot_arg_value))) {
70#if DEVELOPMENT || DEBUG
71 boot_arg_value = TRUE;
72#else
73 boot_arg_value = FALSE;
74#endif
75 }
76 gPEKernelConfigurationBitmask |= (boot_arg_value ? kPEICanHasStatistics : 0);
77
78#if SECURE_KERNEL
79 boot_arg_value = FALSE;
80#else
81 if (!PE_i_can_has_debugger(NULL)) {
82 boot_arg_value = FALSE;
83 } else if (!PE_parse_boot_argn(arg_string: "diagnostic_api", arg_ptr: &boot_arg_value, max_arg: sizeof(boot_arg_value))) {
84 boot_arg_value = TRUE;
85 }
86#endif
87 gPEKernelConfigurationBitmask |= (boot_arg_value ? kPEICanHasDiagnosticAPI : 0);
88
89
90 int factor = 1;
91 boolean_t have_bootarg = PE_parse_boot_argn(arg_string: "cpu-factor", arg_ptr: &factor, max_arg: sizeof(factor));
92 if (have_bootarg) {
93 debug_cpu_performance_degradation_factor = factor;
94 } else {
95 DTEntry root;
96 if (SecureDTLookupEntry(NULL, pathName: "/", foundEntry: &root) == kSuccess) {
97 void const *prop = NULL;
98 uint32_t size = 0;
99 if (SecureDTGetProperty(entry: root, propertyName: "target-is-fpga", propertyValue: &prop, propertySize: &size) == kSuccess) {
100 debug_cpu_performance_degradation_factor = 10;
101 }
102 }
103 }
104}
105
106void
107PE_enter_debugger(const char *cause)
108{
109 if (debug_boot_arg & DB_NMI) {
110 Debugger(message: cause);
111 }
112}
113
114uint32_t
115PE_i_can_has_kernel_configuration(void)
116{
117 return gPEKernelConfigurationBitmask;
118}
119
120/* extern references */
121extern void vcattach(void);
122
123/* Globals */
124typedef void (*PE_putc_t)(char);
125
126#if XNU_TARGET_OS_OSX
127PE_putc_t PE_putc;
128#else
129SECURITY_READ_ONLY_LATE(PE_putc_t) PE_putc;
130#endif
131
132extern void console_write_char(char);
133
134void
135PE_init_printf(boolean_t vm_initialized)
136{
137 if (!vm_initialized) {
138 PE_putc = console_write_char;
139 } else {
140 vcattach();
141 }
142}
143
144uint32_t
145PE_get_random_seed(unsigned char *dst_random_seed, uint32_t request_size)
146{
147 uint32_t size = 0;
148 uint8_t *random_seed;
149
150#if CONFIG_SPTM
151 char const prefix[] = "randseed";
152 size_t const prefix_len = sizeof(prefix) - 1;
153
154 extern const sptm_bootstrap_args_xnu_t *SPTMArgs;
155
156#pragma clang diagnostic push
157#pragma clang diagnostic ignored "-Wcast-qual"
158 /* Legal, because we are not locked down yet. */
159 random_seed = (uint8_t*)&SPTMArgs->random_seed;
160#pragma GCC diagnostic pop
161
162 size = (uint32_t)SPTMArgs->random_seed_length;
163
164 if (size < prefix_len) {
165 panic("random seed field too short");
166 }
167
168 if (memcmp(random_seed, prefix, prefix_len) != 0) {
169 panic("random seed corrupted");
170 }
171
172 random_seed += prefix_len;
173 size -= prefix_len;
174#else /* CONFIG_SPTM */
175 DTEntry entryP;
176
177 if ((SecureDTLookupEntry(NULL, pathName: "/chosen", foundEntry: &entryP) != kSuccess)
178 || (SecureDTGetProperty(entry: entryP, propertyName: "random-seed",
179 /* casting away the const is permissible here, since
180 * this function runs before lockdown. */
181 propertyValue: (const void **)(uintptr_t)&random_seed, propertySize: &size) != kSuccess)) {
182 random_seed = NULL;
183 size = 0;
184 }
185#endif /* CONFIG_SPTM */
186
187 if (random_seed == NULL || size == 0) {
188 panic("no random seed");
189 }
190
191 unsigned char *src_random_seed;
192 unsigned int i;
193 unsigned int null_count = 0;
194
195 src_random_seed = (unsigned char *)random_seed;
196
197 if (size > request_size) {
198 size = request_size;
199 }
200
201 /*
202 * Copy from the device tree into the destination buffer,
203 * count the number of null bytes and null out the device tree.
204 */
205 for (i = 0; i < size; i++, src_random_seed++, dst_random_seed++) {
206 *dst_random_seed = *src_random_seed;
207 null_count += *src_random_seed == (unsigned char)0;
208 *src_random_seed = (unsigned char)0;
209 }
210 if (null_count == size) {
211 /* All nulls is no seed - return 0 */
212 size = 0;
213 }
214
215 return size;
216}
217
218unsigned char appleClut8[256 * 3] = {
219// 00
220 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xFF, 0xFF, 0x99, 0xFF, 0xFF, 0x66,
221 0xFF, 0xFF, 0x33, 0xFF, 0xFF, 0x00, 0xFF, 0xCC, 0xFF, 0xFF, 0xCC, 0xCC,
222 0xFF, 0xCC, 0x99, 0xFF, 0xCC, 0x66, 0xFF, 0xCC, 0x33, 0xFF, 0xCC, 0x00,
223 0xFF, 0x99, 0xFF, 0xFF, 0x99, 0xCC, 0xFF, 0x99, 0x99, 0xFF, 0x99, 0x66,
224// 10
225 0xFF, 0x99, 0x33, 0xFF, 0x99, 0x00, 0xFF, 0x66, 0xFF, 0xFF, 0x66, 0xCC,
226 0xFF, 0x66, 0x99, 0xFF, 0x66, 0x66, 0xFF, 0x66, 0x33, 0xFF, 0x66, 0x00,
227 0xFF, 0x33, 0xFF, 0xFF, 0x33, 0xCC, 0xFF, 0x33, 0x99, 0xFF, 0x33, 0x66,
228 0xFF, 0x33, 0x33, 0xFF, 0x33, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xCC,
229// 20
230 0xFF, 0x00, 0x99, 0xFF, 0x00, 0x66, 0xFF, 0x00, 0x33, 0xFF, 0x00, 0x00,
231 0xCC, 0xFF, 0xFF, 0xCC, 0xFF, 0xCC, 0xCC, 0xFF, 0x99, 0xCC, 0xFF, 0x66,
232 0xCC, 0xFF, 0x33, 0xCC, 0xFF, 0x00, 0xCC, 0xCC, 0xFF, 0xCC, 0xCC, 0xCC,
233 0xCC, 0xCC, 0x99, 0xCC, 0xCC, 0x66, 0xCC, 0xCC, 0x33, 0xCC, 0xCC, 0x00,
234// 30
235 0xCC, 0x99, 0xFF, 0xCC, 0x99, 0xCC, 0xCC, 0x99, 0x99, 0xCC, 0x99, 0x66,
236 0xCC, 0x99, 0x33, 0xCC, 0x99, 0x00, 0xCC, 0x66, 0xFF, 0xCC, 0x66, 0xCC,
237 0xCC, 0x66, 0x99, 0xCC, 0x66, 0x66, 0xCC, 0x66, 0x33, 0xCC, 0x66, 0x00,
238 0xCC, 0x33, 0xFF, 0xCC, 0x33, 0xCC, 0xCC, 0x33, 0x99, 0xCC, 0x33, 0x66,
239// 40
240 0xCC, 0x33, 0x33, 0xCC, 0x33, 0x00, 0xCC, 0x00, 0xFF, 0xCC, 0x00, 0xCC,
241 0xCC, 0x00, 0x99, 0xCC, 0x00, 0x66, 0xCC, 0x00, 0x33, 0xCC, 0x00, 0x00,
242 0x99, 0xFF, 0xFF, 0x99, 0xFF, 0xCC, 0x99, 0xFF, 0x99, 0x99, 0xFF, 0x66,
243 0x99, 0xFF, 0x33, 0x99, 0xFF, 0x00, 0x99, 0xCC, 0xFF, 0x99, 0xCC, 0xCC,
244// 50
245 0x99, 0xCC, 0x99, 0x99, 0xCC, 0x66, 0x99, 0xCC, 0x33, 0x99, 0xCC, 0x00,
246 0x99, 0x99, 0xFF, 0x99, 0x99, 0xCC, 0x99, 0x99, 0x99, 0x99, 0x99, 0x66,
247 0x99, 0x99, 0x33, 0x99, 0x99, 0x00, 0x99, 0x66, 0xFF, 0x99, 0x66, 0xCC,
248 0x99, 0x66, 0x99, 0x99, 0x66, 0x66, 0x99, 0x66, 0x33, 0x99, 0x66, 0x00,
249// 60
250 0x99, 0x33, 0xFF, 0x99, 0x33, 0xCC, 0x99, 0x33, 0x99, 0x99, 0x33, 0x66,
251 0x99, 0x33, 0x33, 0x99, 0x33, 0x00, 0x99, 0x00, 0xFF, 0x99, 0x00, 0xCC,
252 0x99, 0x00, 0x99, 0x99, 0x00, 0x66, 0x99, 0x00, 0x33, 0x99, 0x00, 0x00,
253 0x66, 0xFF, 0xFF, 0x66, 0xFF, 0xCC, 0x66, 0xFF, 0x99, 0x66, 0xFF, 0x66,
254// 70
255 0x66, 0xFF, 0x33, 0x66, 0xFF, 0x00, 0x66, 0xCC, 0xFF, 0x66, 0xCC, 0xCC,
256 0x66, 0xCC, 0x99, 0x66, 0xCC, 0x66, 0x66, 0xCC, 0x33, 0x66, 0xCC, 0x00,
257 0x66, 0x99, 0xFF, 0x66, 0x99, 0xCC, 0x66, 0x99, 0x99, 0x66, 0x99, 0x66,
258 0x66, 0x99, 0x33, 0x66, 0x99, 0x00, 0x66, 0x66, 0xFF, 0x66, 0x66, 0xCC,
259// 80
260 0x66, 0x66, 0x99, 0x66, 0x66, 0x66, 0x66, 0x66, 0x33, 0x66, 0x66, 0x00,
261 0x66, 0x33, 0xFF, 0x66, 0x33, 0xCC, 0x66, 0x33, 0x99, 0x66, 0x33, 0x66,
262 0x66, 0x33, 0x33, 0x66, 0x33, 0x00, 0x66, 0x00, 0xFF, 0x66, 0x00, 0xCC,
263 0x66, 0x00, 0x99, 0x66, 0x00, 0x66, 0x66, 0x00, 0x33, 0x66, 0x00, 0x00,
264// 90
265 0x33, 0xFF, 0xFF, 0x33, 0xFF, 0xCC, 0x33, 0xFF, 0x99, 0x33, 0xFF, 0x66,
266 0x33, 0xFF, 0x33, 0x33, 0xFF, 0x00, 0x33, 0xCC, 0xFF, 0x33, 0xCC, 0xCC,
267 0x33, 0xCC, 0x99, 0x33, 0xCC, 0x66, 0x33, 0xCC, 0x33, 0x33, 0xCC, 0x00,
268 0x33, 0x99, 0xFF, 0x33, 0x99, 0xCC, 0x33, 0x99, 0x99, 0x33, 0x99, 0x66,
269// a0
270 0x33, 0x99, 0x33, 0x33, 0x99, 0x00, 0x33, 0x66, 0xFF, 0x33, 0x66, 0xCC,
271 0x33, 0x66, 0x99, 0x33, 0x66, 0x66, 0x33, 0x66, 0x33, 0x33, 0x66, 0x00,
272 0x33, 0x33, 0xFF, 0x33, 0x33, 0xCC, 0x33, 0x33, 0x99, 0x33, 0x33, 0x66,
273 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x33, 0x00, 0xFF, 0x33, 0x00, 0xCC,
274// b0
275 0x33, 0x00, 0x99, 0x33, 0x00, 0x66, 0x33, 0x00, 0x33, 0x33, 0x00, 0x00,
276 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xCC, 0x00, 0xFF, 0x99, 0x00, 0xFF, 0x66,
277 0x00, 0xFF, 0x33, 0x00, 0xFF, 0x00, 0x00, 0xCC, 0xFF, 0x00, 0xCC, 0xCC,
278 0x00, 0xCC, 0x99, 0x00, 0xCC, 0x66, 0x00, 0xCC, 0x33, 0x00, 0xCC, 0x00,
279// c0
280 0x00, 0x99, 0xFF, 0x00, 0x99, 0xCC, 0x00, 0x99, 0x99, 0x00, 0x99, 0x66,
281 0x00, 0x99, 0x33, 0x00, 0x99, 0x00, 0x00, 0x66, 0xFF, 0x00, 0x66, 0xCC,
282 0x00, 0x66, 0x99, 0x00, 0x66, 0x66, 0x00, 0x66, 0x33, 0x00, 0x66, 0x00,
283 0x00, 0x33, 0xFF, 0x00, 0x33, 0xCC, 0x00, 0x33, 0x99, 0x00, 0x33, 0x66,
284// d0
285 0x00, 0x33, 0x33, 0x00, 0x33, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xCC,
286 0x00, 0x00, 0x99, 0x00, 0x00, 0x66, 0x00, 0x00, 0x33, 0xEE, 0x00, 0x00,
287 0xDD, 0x00, 0x00, 0xBB, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x88, 0x00, 0x00,
288 0x77, 0x00, 0x00, 0x55, 0x00, 0x00, 0x44, 0x00, 0x00, 0x22, 0x00, 0x00,
289// e0
290 0x11, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0xDD, 0x00, 0x00, 0xBB, 0x00,
291 0x00, 0xAA, 0x00, 0x00, 0x88, 0x00, 0x00, 0x77, 0x00, 0x00, 0x55, 0x00,
292 0x00, 0x44, 0x00, 0x00, 0x22, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xEE,
293 0x00, 0x00, 0xDD, 0x00, 0x00, 0xBB, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x88,
294// f0
295 0x00, 0x00, 0x77, 0x00, 0x00, 0x55, 0x00, 0x00, 0x44, 0x00, 0x00, 0x22,
296 0x00, 0x00, 0x11, 0xEE, 0xEE, 0xEE, 0xDD, 0xDD, 0xDD, 0xBB, 0xBB, 0xBB,
297 0xAA, 0xAA, 0xAA, 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x55, 0x55, 0x55,
298 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00
299};
300