]>
Commit | Line | Data |
---|---|---|
b061a43b | 1 | /* |
70ad1dc8 | 2 | * Copyright (c) 2016 Apple Inc. All rights reserved. |
b061a43b A |
3 | * |
4 | * @APPLE_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. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | ||
a9aaacca | 24 | #include <errno.h> |
b061a43b A |
25 | #include <stdlib.h> |
26 | #include <unistd.h> | |
27 | #include <sys/stat.h> | |
28 | #include <sys/sysctl.h> | |
29 | #include <sys/types.h> | |
30 | #include <dispatch/dispatch.h> | |
31 | #include <xpc/xpc.h> | |
32 | #include <xpc/private.h> | |
33 | #include <System/sys/csr.h> | |
34 | #include <System/machine/cpu_capabilities.h> | |
35 | ||
36 | #include <os/assumes.h> | |
507116e3 | 37 | #include <os/bsd.h> |
6dccf0e0 | 38 | #include <os/stdlib.h> |
b061a43b | 39 | #include <os/variant_private.h> |
a9aaacca | 40 | #include <os/boot_mode_private.h> |
b061a43b | 41 | |
6dccf0e0 A |
42 | /* |
43 | * Lists all properties overridden by an empty file | |
44 | */ | |
45 | #define ALL_OVERRIDES_STR "content,diagnostics,ui,security" | |
46 | ||
b061a43b | 47 | enum variant_property { |
b061a43b A |
48 | VP_CONTENT, |
49 | VP_DIAGNOSTICS, | |
50 | VP_UI, | |
51 | VP_SECURITY, | |
52 | VP_MAX | |
53 | }; | |
54 | ||
55 | enum check_status { | |
56 | S_UNKNOWN = 0, | |
57 | S_NO = 2, | |
58 | S_YES = 3 | |
59 | }; | |
60 | ||
507116e3 A |
61 | typedef struct { |
62 | const char *variant; | |
63 | bool (*function)(const char*); | |
64 | } variant_check_mapping; | |
65 | ||
b061a43b A |
66 | static bool |
67 | status2bool(enum check_status status) { | |
68 | switch (status) { | |
69 | case S_NO: | |
70 | return false; | |
71 | case S_YES: | |
72 | return true; | |
507116e3 | 73 | case S_UNKNOWN: |
b061a43b A |
74 | default: |
75 | os_crash("os_variant had unexpected status"); | |
76 | } | |
77 | } | |
78 | ||
79 | #define VAR_FILE_LEGACY "/var/db/disableAppleInternal" | |
80 | ||
81 | #if TARGET_OS_OSX | |
82 | #define VAR_FILE_OVERRIDE "/var/db/os_variant_override" | |
83 | #else | |
84 | #define VAR_FILE_OVERRIDE "/usr/share/misc/os_variant_override" | |
85 | #endif | |
86 | ||
87 | #if !TARGET_OS_SIMULATOR | |
88 | #define INTERNAL_CONTENT_PATH "/System/Library/CoreServices/AppleInternalVariant.plist" | |
89 | #else | |
90 | #define INTERNAL_CONTENT_PATH "/AppleInternal" | |
91 | #endif | |
92 | ||
93 | #define SYSTEM_VERSION_PLIST_PATH "/System/Library/CoreServices/SystemVersion.plist" | |
94 | #define SYSTEM_VERSION_PLIST_KEY "ReleaseType" | |
95 | ||
96 | #if TARGET_OS_IPHONE | |
97 | #define INTERNAL_SETTINGS_PATH "/AppleInternal/Library/PreferenceBundles/Internal Settings.bundle" | |
98 | #else | |
99 | #define INTERNAL_DIAGS_PROFILE_PATH "/var/db/ConfigurationProfiles/Settings/com.apple.InternalDiagnostics.plist" | |
6dccf0e0 | 100 | #define FACTORY_CONTENT_PATH "/System/Library/CoreServices/AppleFactoryVariant.plist" |
507116e3 | 101 | #define BASE_SYSTEM_CONTENT_PATH "/System/Library/BaseSystem" |
a9aaacca | 102 | #define DARWINOS_CONTENT_PATH "/System/Library/CoreServices/DarwinVariant.plist" |
b061a43b A |
103 | #endif |
104 | ||
a9aaacca A |
105 | static void _check_all_statuses(void); |
106 | ||
b061a43b A |
107 | #if !TARGET_OS_SIMULATOR |
108 | #define CACHE_SYSCTL_NAME "kern.osvariant_status" | |
109 | ||
110 | static void _restore_cached_check_status(uint64_t status); | |
111 | static uint64_t _get_cached_check_status(void); | |
112 | ||
113 | static char * _read_file(const char *path, size_t *size_out) | |
114 | { | |
115 | char *buf = NULL; | |
116 | ||
117 | int fd = open(path, O_RDONLY); | |
118 | if (fd == -1) return NULL; | |
119 | ||
120 | struct stat sb; | |
121 | int rc = fstat(fd, &sb); | |
122 | if (rc != 0 || sb.st_size == 0) { | |
123 | goto error; | |
124 | } | |
125 | ||
126 | size_t size_limit = (size_out && *size_out != 0) ? *size_out : 1024; | |
127 | size_t size = (size_t)sb.st_size; | |
128 | if (size_out) *size_out = (size_t)sb.st_size; | |
129 | if (size > size_limit) { | |
130 | goto error; | |
131 | } | |
132 | ||
133 | buf = malloc(size + 1); | |
134 | if (!buf) { | |
135 | goto error; | |
136 | } | |
137 | ||
138 | ssize_t bytes_read = read(fd, buf, size); | |
139 | buf[size] = '\0'; | |
140 | ||
141 | ||
142 | if (bytes_read == (ssize_t)size) { | |
143 | close(fd); | |
144 | return buf; | |
145 | } | |
146 | ||
147 | error: | |
148 | close(fd); | |
149 | free(buf); | |
150 | return NULL; | |
151 | } | |
152 | ||
153 | static xpc_object_t read_plist(const char *path) | |
154 | { | |
155 | size_t size = 16 * 1024; | |
156 | uint8_t *buf = (uint8_t*)_read_file(path, &size); | |
157 | if (!buf) return NULL; | |
158 | ||
159 | xpc_object_t plist = xpc_create_from_plist(buf, size); | |
160 | if (plist && xpc_get_type(plist) != XPC_TYPE_DICTIONARY) { | |
161 | xpc_release(plist); | |
162 | plist = NULL; | |
163 | } | |
164 | ||
165 | free(buf); | |
166 | ||
167 | return plist; | |
168 | } | |
169 | #endif | |
170 | ||
171 | #if !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR | |
172 | static enum check_status internal_content = S_UNKNOWN; | |
173 | #endif | |
174 | #if !TARGET_OS_SIMULATOR | |
175 | static enum check_status can_has_debugger = S_UNKNOWN; | |
a9aaacca | 176 | static enum check_status has_full_logging = S_UNKNOWN; |
b061a43b A |
177 | #if TARGET_OS_IPHONE |
178 | static enum check_status internal_release_type = S_UNKNOWN; | |
6dccf0e0 | 179 | static enum check_status factory_release_type = S_UNKNOWN; |
507116e3 A |
180 | static enum check_status darwin_release_type = S_UNKNOWN; |
181 | static enum check_status recovery_release_type = S_UNKNOWN; | |
182 | static enum check_status development_kernel = S_UNKNOWN; | |
b061a43b A |
183 | #else // TARGET_OS_IPHONE |
184 | static enum check_status internal_diags_profile = S_UNKNOWN; | |
6dccf0e0 | 185 | static enum check_status factory_content = S_UNKNOWN; |
507116e3 | 186 | static enum check_status base_system_content = S_UNKNOWN; |
a9aaacca | 187 | static enum check_status darwinos_content = S_UNKNOWN; |
b061a43b A |
188 | #endif // TARGET_OS_IPHONE |
189 | #endif // !TARGET_OS_SIMULATOR | |
507116e3 | 190 | static enum check_status is_ephemeral = S_UNKNOWN; |
b061a43b A |
191 | |
192 | static bool disabled_status[VP_MAX] = {}; | |
193 | ||
194 | static void _parse_disabled_status(char *test_string) | |
195 | { | |
196 | #if TARGET_OS_SIMULATOR | |
197 | #pragma unused(test_string) | |
198 | #else // TARGET_OS_SIMULATOR | |
199 | char *override_str = NULL; | |
200 | ||
201 | bzero(disabled_status, sizeof(disabled_status)); | |
202 | ||
203 | if (test_string != NULL) { | |
204 | /* used for unit tests */ | |
6dccf0e0 | 205 | override_str = os_strdup(test_string); |
b061a43b A |
206 | } else { |
207 | if (access(VAR_FILE_LEGACY, F_OK) == 0) { | |
6dccf0e0 | 208 | override_str = os_strdup(ALL_OVERRIDES_STR); |
b061a43b A |
209 | } else if (access(VAR_FILE_OVERRIDE, F_OK) != 0) { |
210 | return; | |
211 | } | |
212 | ||
213 | override_str = _read_file(VAR_FILE_OVERRIDE, NULL); | |
214 | } | |
215 | ||
6dccf0e0 A |
216 | if (override_str == NULL) { |
217 | override_str = os_strdup(ALL_OVERRIDES_STR); | |
218 | } | |
b061a43b A |
219 | |
220 | char *token, *string = override_str; | |
221 | while ((token = strsep(&string, ",\n")) != NULL) { | |
222 | if (strcmp(token, "content") == 0) { | |
223 | disabled_status[VP_CONTENT] = true; | |
224 | } else if (strcmp(token, "diagnostics") == 0) { | |
225 | disabled_status[VP_DIAGNOSTICS] = true; | |
226 | } else if (strcmp(token, "ui") == 0) { | |
227 | disabled_status[VP_UI] = true; | |
228 | } else if (strcmp(token, "security") == 0) { | |
229 | disabled_status[VP_SECURITY] = true; | |
230 | } | |
231 | } | |
232 | ||
233 | free(override_str); | |
234 | return; | |
b061a43b A |
235 | #endif //!TARGET_OS_SIMULATOR |
236 | } | |
237 | ||
238 | #if !TARGET_OS_SIMULATOR | |
239 | static bool _load_cached_status(void) | |
240 | { | |
241 | uint64_t status = 0; | |
242 | size_t status_size = sizeof(status); | |
243 | int ret = sysctlbyname(CACHE_SYSCTL_NAME, &status, &status_size, NULL, 0); | |
244 | if (ret != 0) { | |
245 | return false; | |
246 | } | |
247 | ||
248 | if (status) { | |
249 | _restore_cached_check_status(status); | |
250 | return true; | |
251 | } | |
252 | ||
b061a43b A |
253 | return false; |
254 | } | |
255 | #endif | |
256 | ||
a9aaacca | 257 | static void _initialize_status(void) |
b061a43b | 258 | { |
a9aaacca A |
259 | static dispatch_once_t once; |
260 | dispatch_once(&once, ^{ | |
261 | #if !TARGET_OS_SIMULATOR && !defined(VARIANT_SKIP_EXPORTED) | |
262 | if (_load_cached_status() && !_os_xbs_chrooted) { | |
263 | return; | |
264 | } | |
b061a43b | 265 | #endif |
a9aaacca A |
266 | _check_all_statuses(); |
267 | }); | |
b061a43b A |
268 | } |
269 | ||
270 | static bool _check_disabled(enum variant_property variant_property) | |
271 | { | |
a9aaacca | 272 | _initialize_status(); |
b061a43b A |
273 | |
274 | return disabled_status[variant_property]; | |
275 | } | |
276 | ||
277 | #if !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR | |
a9aaacca | 278 | static void _check_internal_content_impl(void) |
b061a43b | 279 | { |
a9aaacca A |
280 | if (_os_xbs_chrooted && internal_content != S_UNKNOWN) { |
281 | return; | |
282 | } else { | |
283 | os_assert(internal_content == S_UNKNOWN); | |
284 | } | |
285 | ||
b061a43b | 286 | #if !TARGET_OS_SIMULATOR |
a9aaacca | 287 | const char * path = INTERNAL_CONTENT_PATH; |
b061a43b | 288 | #else |
a9aaacca A |
289 | char *simulator_root = getenv("IPHONE_SIMULATOR_ROOT"); |
290 | char *to_free = NULL, *path = NULL; | |
291 | if (simulator_root) { | |
292 | asprintf(&path, "%s/%s", simulator_root, INTERNAL_CONTENT_PATH); | |
293 | if (path == NULL) { | |
294 | internal_content = S_NO; | |
295 | return; | |
b061a43b | 296 | } |
a9aaacca A |
297 | to_free = path; |
298 | } | |
b061a43b | 299 | #endif |
a9aaacca | 300 | internal_content = (access(path, F_OK) == 0) ? S_YES : S_NO; |
b061a43b | 301 | #if TARGET_OS_SIMULATOR |
a9aaacca | 302 | free(to_free); |
b061a43b | 303 | #endif |
a9aaacca A |
304 | } |
305 | ||
306 | static bool _check_internal_content(void) | |
307 | { | |
308 | _initialize_status(); | |
b061a43b A |
309 | return status2bool(internal_content); |
310 | } | |
311 | #endif // !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR | |
312 | ||
6dccf0e0 | 313 | #if TARGET_OS_OSX |
a9aaacca | 314 | static void _check_factory_content_impl(void) |
6dccf0e0 | 315 | { |
a9aaacca A |
316 | if (_os_xbs_chrooted && factory_content != S_UNKNOWN) { |
317 | return; | |
318 | } else { | |
319 | os_assert(factory_content == S_UNKNOWN); | |
6dccf0e0 | 320 | } |
a9aaacca A |
321 | |
322 | const char * path = FACTORY_CONTENT_PATH; | |
323 | factory_content = (access(path, F_OK) == 0) ? S_YES : S_NO; | |
324 | } | |
325 | ||
326 | static bool _check_factory_content(void) | |
327 | { | |
328 | _initialize_status(); | |
329 | ||
6dccf0e0 A |
330 | return status2bool(factory_content); |
331 | } | |
332 | #endif // TARGET_OS_OSX | |
333 | ||
b061a43b A |
334 | #if TARGET_OS_IPHONE |
335 | ||
6dccf0e0 A |
336 | #if !TARGET_OS_SIMULATOR |
337 | static bool _parse_system_version_plist(void) | |
338 | { | |
339 | xpc_object_t system_version_plist = read_plist(SYSTEM_VERSION_PLIST_PATH); | |
340 | if (!system_version_plist) { | |
341 | return false; | |
342 | } | |
343 | ||
344 | const char *release_type = | |
345 | xpc_dictionary_get_string(system_version_plist, | |
346 | SYSTEM_VERSION_PLIST_KEY); | |
347 | ||
348 | if (release_type == NULL) { | |
349 | /* | |
350 | * Confusingly, customer images are just completely missing this key. | |
351 | */ | |
352 | internal_release_type = S_NO; | |
353 | factory_release_type = S_NO; | |
507116e3 A |
354 | darwin_release_type = S_NO; |
355 | recovery_release_type = S_NO; | |
6dccf0e0 | 356 | } else if (strcmp(release_type, "NonUI") == 0) { |
6dccf0e0 | 357 | factory_release_type = S_YES; |
507116e3 A |
358 | internal_release_type = S_YES; |
359 | darwin_release_type = S_NO; | |
360 | recovery_release_type = S_NO; | |
6dccf0e0 | 361 | } else { |
6dccf0e0 | 362 | factory_release_type = S_NO; |
507116e3 A |
363 | internal_release_type = (strstr(release_type, "Internal") != NULL) ? S_YES : S_NO; |
364 | darwin_release_type = (strstr(release_type, "Darwin") != NULL) ? S_YES : S_NO; | |
365 | recovery_release_type = (strstr(release_type, "Recovery") != NULL) ? S_YES : S_NO; | |
6dccf0e0 A |
366 | } |
367 | ||
368 | xpc_release(system_version_plist); | |
369 | ||
370 | return true; | |
371 | } | |
a9aaacca A |
372 | |
373 | static void _check_system_version_plist_statuses_impl(void) | |
374 | { | |
375 | os_assert(internal_release_type == S_UNKNOWN); | |
376 | os_assert(factory_release_type == S_UNKNOWN); | |
377 | os_assert(darwin_release_type == S_UNKNOWN); | |
378 | os_assert(recovery_release_type == S_UNKNOWN); | |
379 | ||
380 | if (!_parse_system_version_plist()) { | |
381 | internal_release_type = (access(INTERNAL_SETTINGS_PATH, F_OK) == 0) ? S_YES : S_NO; | |
382 | factory_release_type = S_NO; | |
383 | darwin_release_type = S_NO; | |
384 | recovery_release_type = S_NO; | |
385 | } | |
386 | } | |
6dccf0e0 A |
387 | #endif //!TARGET_OS_SIMULATOR |
388 | ||
b061a43b A |
389 | static bool _check_internal_release_type(void) |
390 | { | |
391 | #if TARGET_OS_SIMULATOR | |
392 | return _check_internal_content(); | |
393 | #else // TARGET_OS_SIMULATOR | |
a9aaacca | 394 | _initialize_status(); |
b061a43b A |
395 | |
396 | return status2bool(internal_release_type); | |
397 | #endif // TARGET_OS_SIMULATOR | |
398 | } | |
399 | ||
6dccf0e0 A |
400 | static bool _check_factory_release_type(void) |
401 | { | |
402 | #if TARGET_OS_SIMULATOR | |
403 | return false; | |
404 | #else // TARGET_OS_SIMULATOR | |
a9aaacca | 405 | _initialize_status(); |
6dccf0e0 A |
406 | |
407 | return status2bool(factory_release_type); | |
408 | #endif // TARGET_OS_SIMULATOR | |
409 | } | |
410 | ||
507116e3 A |
411 | static bool _check_darwin_release_type(void) |
412 | { | |
413 | #if TARGET_OS_SIMULATOR | |
414 | return false; | |
415 | #else // TARGET_OS_SIMULATOR | |
a9aaacca | 416 | _initialize_status(); |
507116e3 A |
417 | |
418 | return status2bool(darwin_release_type); | |
419 | #endif // TARGET_OS_SIMULATOR | |
420 | } | |
421 | ||
422 | static bool _check_recovery_release_type(void) | |
423 | { | |
424 | #if TARGET_OS_SIMULATOR | |
425 | return false; | |
426 | #else // TARGET_OS_SIMULATOR | |
a9aaacca | 427 | _initialize_status(); |
507116e3 A |
428 | |
429 | return status2bool(recovery_release_type); | |
430 | #endif // TARGET_OS_SIMULATOR | |
431 | } | |
432 | ||
433 | #else // TARGET_OS_IPHONE | |
b061a43b | 434 | |
a9aaacca | 435 | static void _check_internal_diags_profile_impl(void) |
70ad1dc8 | 436 | { |
a9aaacca A |
437 | if (_os_xbs_chrooted && internal_diags_profile != S_UNKNOWN) { |
438 | return; | |
439 | } else { | |
440 | os_assert(internal_diags_profile == S_UNKNOWN); | |
b061a43b A |
441 | } |
442 | ||
a9aaacca A |
443 | xpc_object_t profile_settings = read_plist(INTERNAL_DIAGS_PROFILE_PATH); |
444 | if (profile_settings) { | |
445 | internal_diags_profile = xpc_dictionary_get_bool(profile_settings, "AppleInternal") ? S_YES : S_NO; | |
446 | xpc_release(profile_settings); | |
447 | } else { | |
448 | internal_diags_profile = S_NO; | |
449 | } | |
450 | } | |
451 | ||
452 | static bool _check_internal_diags_profile(void) | |
453 | { | |
454 | _initialize_status(); | |
455 | ||
b061a43b A |
456 | return status2bool(internal_diags_profile); |
457 | } | |
458 | ||
a9aaacca | 459 | static void _check_base_system_content_impl(void) |
507116e3 | 460 | { |
a9aaacca A |
461 | if (_os_xbs_chrooted && base_system_content != S_UNKNOWN) { |
462 | return; | |
463 | } else { | |
464 | os_assert(base_system_content == S_UNKNOWN); | |
507116e3 | 465 | } |
a9aaacca A |
466 | |
467 | const char * path = BASE_SYSTEM_CONTENT_PATH; | |
468 | base_system_content = (access(path, F_OK) == 0) ? S_YES : S_NO; | |
469 | } | |
470 | ||
471 | static bool _check_base_system_content(void) | |
472 | { | |
473 | _initialize_status(); | |
474 | ||
507116e3 A |
475 | return status2bool(base_system_content); |
476 | } | |
477 | ||
a9aaacca A |
478 | static void _check_darwinos_content_impl(void) |
479 | { | |
480 | if (_os_xbs_chrooted && darwinos_content != S_UNKNOWN) { | |
481 | return; | |
482 | } else { | |
483 | os_assert(darwinos_content == S_UNKNOWN); | |
484 | } | |
485 | ||
486 | const char * path = DARWINOS_CONTENT_PATH; | |
487 | darwinos_content = (access(path, F_OK) == 0) ? S_YES : S_NO; | |
488 | } | |
489 | ||
490 | static bool _check_darwinos_content(void) | |
491 | { | |
492 | _initialize_status(); | |
493 | ||
494 | return status2bool(darwinos_content); | |
495 | } | |
496 | ||
b061a43b A |
497 | #endif |
498 | ||
507116e3 | 499 | #if !TARGET_OS_SIMULATOR |
a9aaacca | 500 | static void _check_can_has_debugger_impl(void) |
b061a43b | 501 | { |
a9aaacca A |
502 | if (_os_xbs_chrooted && can_has_debugger != S_UNKNOWN) { |
503 | return; | |
504 | } else { | |
505 | os_assert(can_has_debugger == S_UNKNOWN); | |
506 | } | |
507 | ||
b061a43b | 508 | #if TARGET_OS_IPHONE |
a9aaacca | 509 | can_has_debugger = *((uint32_t *)_COMM_PAGE_DEV_FIRM) ? S_YES : S_NO; |
b061a43b | 510 | #else |
a9aaacca A |
511 | /* |
512 | * The comm page bit does exist on macOS, but also requires kernel | |
513 | * debugging in the CSR configuration. We don't need to be that strict | |
514 | * here. | |
515 | */ | |
516 | can_has_debugger = (csr_check(CSR_ALLOW_APPLE_INTERNAL) == 0) ? S_YES : S_NO; | |
b061a43b | 517 | #endif |
a9aaacca A |
518 | } |
519 | ||
520 | static bool _check_can_has_debugger(void) | |
521 | { | |
522 | _initialize_status(); | |
523 | ||
b061a43b | 524 | return status2bool(can_has_debugger); |
b061a43b | 525 | } |
507116e3 A |
526 | #endif // !TARGET_OS_SIMULATOR |
527 | ||
528 | #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR | |
a9aaacca | 529 | static void _check_development_kernel_impl(void) |
507116e3 | 530 | { |
a9aaacca A |
531 | os_assert(development_kernel == S_UNKNOWN); |
532 | /* | |
533 | * Whitelist values from SUPPORTED_KERNEL_CONFIGS. | |
534 | */ | |
535 | char *osbuildconfig = NULL; | |
536 | size_t osbuildconfig_sz = 0; | |
537 | errno_t err = sysctlbyname_get_data_np("kern.osbuildconfig", (void **)&osbuildconfig, &osbuildconfig_sz); | |
538 | if (err == 0) { | |
539 | if (strcmp(osbuildconfig, "development") == 0 || | |
540 | strcmp(osbuildconfig, "debug") == 0 || | |
541 | strcmp(osbuildconfig, "profile") == 0 || | |
542 | strcmp(osbuildconfig, "kasan") == 0) { | |
543 | development_kernel = S_YES; | |
507116e3 | 544 | } |
a9aaacca A |
545 | } |
546 | free(osbuildconfig); | |
507116e3 | 547 | |
a9aaacca A |
548 | if (development_kernel == S_UNKNOWN) { |
549 | development_kernel = S_NO; | |
507116e3 | 550 | } |
a9aaacca A |
551 | } |
552 | ||
553 | static bool _check_development_kernel(void) | |
554 | { | |
555 | _initialize_status(); | |
556 | ||
507116e3 A |
557 | return status2bool(development_kernel); |
558 | } | |
559 | #endif // TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR | |
b061a43b | 560 | |
a9aaacca A |
561 | static void _check_uses_ephemeral_storage_impl(void) |
562 | { | |
563 | if (_os_xbs_chrooted && is_ephemeral != S_UNKNOWN) { | |
564 | return; | |
565 | } else { | |
566 | os_assert(is_ephemeral == S_UNKNOWN); | |
567 | } | |
568 | ||
569 | uint32_t buffer = 0; | |
570 | size_t buffer_size = sizeof(buffer); | |
571 | ||
572 | sysctlbyname("hw.ephemeral_storage", (void *)&buffer, &buffer_size, NULL, 0); | |
573 | ||
574 | is_ephemeral = (buffer != 0) ? S_YES : S_NO; | |
575 | } | |
576 | ||
577 | static bool _check_uses_ephemeral_storage(void) | |
578 | { | |
579 | _initialize_status(); | |
580 | ||
581 | return status2bool(is_ephemeral); | |
582 | } | |
583 | ||
584 | #if !TARGET_OS_SIMULATOR | |
585 | // internal upcall into libtrace | |
586 | extern bool | |
587 | _os_trace_basesystem_storage_available(void); | |
588 | ||
589 | static void | |
590 | _init_has_full_logging(void) | |
591 | { | |
592 | #if TARGET_OS_OSX | |
593 | if (_check_base_system_content() && | |
594 | !_os_trace_basesystem_storage_available()) { | |
595 | has_full_logging = S_NO; | |
596 | return; | |
597 | } | |
598 | #endif | |
599 | ||
600 | has_full_logging = S_YES; | |
601 | } | |
602 | ||
603 | static bool _check_has_full_logging(void) | |
604 | { | |
605 | _initialize_status(); | |
606 | ||
607 | return status2bool(has_full_logging); | |
608 | } | |
609 | #endif // !TARGET_OS_SIMULATOR | |
610 | ||
611 | static void _check_all_statuses(void) | |
612 | { | |
613 | #if !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR | |
614 | _check_internal_content_impl(); | |
615 | #endif | |
616 | ||
617 | _check_uses_ephemeral_storage_impl(); | |
618 | ||
619 | #if !TARGET_OS_SIMULATOR | |
620 | _check_can_has_debugger_impl(); | |
621 | ||
622 | #if TARGET_OS_IPHONE | |
623 | _check_system_version_plist_statuses_impl(); | |
624 | _check_development_kernel_impl(); | |
625 | #else | |
626 | _check_internal_diags_profile_impl(); | |
627 | _check_factory_content_impl(); | |
628 | _check_base_system_content_impl(); | |
629 | _check_darwinos_content_impl(); | |
630 | #endif | |
631 | ||
632 | #endif // !TARGET_OS_SIMULUATOR | |
633 | ||
634 | _parse_disabled_status(NULL); | |
635 | } | |
636 | ||
637 | static bool | |
638 | os_variant_has_full_logging(const char * __unused subsystem) | |
639 | { | |
640 | #if TARGET_OS_SIMULATOR | |
641 | return true; | |
642 | #else | |
643 | return _check_has_full_logging(); | |
644 | #endif | |
645 | } | |
646 | ||
647 | static const variant_check_mapping _variant_map[] = { | |
648 | {.variant = "AllowsInternalSecurityPolicies", .function = os_variant_allows_internal_security_policies}, | |
649 | {.variant = "HasFactoryContent", .function = os_variant_has_factory_content}, | |
650 | {.variant = "HasFullLogging", .function = os_variant_has_full_logging}, | |
651 | {.variant = "HasInternalContent", .function = os_variant_has_internal_content}, | |
652 | {.variant = "HasInternalDiagnostics", .function = os_variant_has_internal_diagnostics}, | |
653 | {.variant = "HasInternalUI", .function = os_variant_has_internal_ui}, | |
654 | #if TARGET_OS_OSX | |
655 | {.variant = "IsBaseSystem", .function = os_variant_is_basesystem}, | |
656 | #endif | |
657 | {.variant = "IsDarwinOS", .function = os_variant_is_darwinos}, | |
658 | {.variant = "IsRecovery", .function = os_variant_is_recovery}, | |
659 | {.variant = "UsesEphemeralStorage", .function = os_variant_uses_ephemeral_storage}, | |
660 | {.variant = NULL, .function = NULL} | |
661 | }; | |
662 | ||
b061a43b A |
663 | // For unit tests |
664 | #ifndef VARIANT_SKIP_EXPORTED | |
665 | ||
666 | bool | |
667 | os_variant_has_internal_content(const char * __unused subsystem) | |
668 | { | |
669 | if (_check_disabled(VP_CONTENT)) { | |
670 | return false; | |
671 | } | |
672 | ||
673 | #if TARGET_OS_IPHONE | |
674 | return _check_internal_release_type(); | |
675 | #else | |
676 | return _check_internal_content(); | |
677 | #endif | |
678 | } | |
679 | ||
680 | ||
681 | bool | |
682 | os_variant_has_internal_diagnostics(const char * __unused subsystem) | |
683 | { | |
684 | if (_check_disabled(VP_DIAGNOSTICS)) { | |
685 | return false; | |
686 | } | |
687 | ||
688 | #if TARGET_OS_IPHONE | |
689 | return _check_internal_release_type(); | |
690 | #else | |
691 | return _check_internal_content() || _check_internal_diags_profile(); | |
692 | #endif | |
693 | } | |
694 | ||
695 | bool | |
696 | os_variant_has_internal_ui(const char * __unused subsystem) | |
697 | { | |
698 | if (_check_disabled(VP_UI)) { | |
699 | return false; | |
700 | } | |
701 | ||
702 | #if TARGET_OS_IPHONE | |
703 | return _check_internal_release_type(); | |
704 | #else | |
705 | return _check_internal_content(); | |
706 | #endif | |
707 | } | |
708 | ||
709 | bool | |
710 | os_variant_allows_internal_security_policies(const char * __unused subsystem) | |
711 | { | |
712 | if (_check_disabled(VP_SECURITY)) { | |
713 | return false; | |
714 | } | |
715 | ||
507116e3 A |
716 | #if TARGET_OS_SIMULATOR |
717 | return _check_internal_content(); | |
718 | #elif TARGET_OS_IPHONE | |
719 | return _check_can_has_debugger() || _check_development_kernel(); | |
720 | #else | |
b061a43b | 721 | return _check_can_has_debugger(); |
507116e3 | 722 | #endif |
b061a43b A |
723 | } |
724 | ||
6dccf0e0 A |
725 | bool |
726 | os_variant_has_factory_content(const char * __unused subsystem) | |
727 | { | |
728 | #if TARGET_OS_IPHONE | |
729 | return _check_factory_release_type(); | |
730 | #else | |
731 | return _check_factory_content(); | |
732 | #endif | |
733 | } | |
734 | ||
507116e3 A |
735 | bool |
736 | os_variant_is_darwinos(const char * __unused subsystem) | |
737 | { | |
507116e3 A |
738 | #if TARGET_OS_IPHONE |
739 | return _check_darwin_release_type(); | |
740 | #else | |
a9aaacca | 741 | return _check_darwinos_content(); |
507116e3 A |
742 | #endif |
743 | } | |
744 | ||
745 | bool | |
746 | os_variant_is_recovery(const char * __unused subsystem) | |
747 | { | |
748 | #if TARGET_OS_IPHONE | |
749 | return _check_recovery_release_type(); | |
750 | #else | |
751 | return _check_base_system_content(); | |
752 | #endif | |
753 | } | |
754 | ||
a9aaacca | 755 | #if TARGET_OS_OSX |
507116e3 | 756 | bool |
a9aaacca | 757 | os_variant_is_basesystem(const char * __unused subsystem) |
507116e3 | 758 | { |
a9aaacca A |
759 | return _check_base_system_content(); |
760 | } | |
761 | #endif | |
507116e3 | 762 | |
a9aaacca A |
763 | bool |
764 | os_variant_uses_ephemeral_storage(const char * __unused subsystem) | |
765 | { | |
766 | return _check_uses_ephemeral_storage(); | |
507116e3 A |
767 | } |
768 | ||
769 | bool | |
a9aaacca A |
770 | os_variant_check(const char *subsystem, const char *variant) |
771 | { | |
772 | variant_check_mapping *current = (variant_check_mapping *)_variant_map; | |
507116e3 A |
773 | |
774 | while (current->variant) { | |
775 | if (0 == strncasecmp(current->variant, variant, strlen(current->variant))) { | |
a9aaacca | 776 | return current->function(subsystem); |
507116e3 A |
777 | } |
778 | current ++; | |
779 | } | |
780 | ||
781 | return false; | |
782 | } | |
783 | ||
a9aaacca A |
784 | char * |
785 | os_variant_copy_description(const char *subsystem) | |
786 | { | |
787 | variant_check_mapping *current = (variant_check_mapping *)_variant_map; | |
788 | ||
789 | char *desc = NULL; | |
790 | size_t desc_size = 0; | |
791 | FILE *outstream = open_memstream(&desc, &desc_size); | |
792 | if (!outstream) { | |
793 | return NULL; | |
794 | } | |
795 | ||
796 | int error = 0; | |
797 | bool needs_space = false; | |
798 | while (current->variant) { | |
799 | if (current->function(subsystem)) { | |
800 | if (needs_space) { | |
801 | int written = fputc(' ', outstream); | |
802 | if (written == EOF) { | |
803 | error = errno; | |
804 | goto error_out; | |
805 | } | |
806 | } | |
807 | int written = fputs(current->variant, outstream); | |
808 | if (written == EOF) { | |
809 | error = errno; | |
810 | goto error_out; | |
811 | } | |
812 | needs_space = true; | |
813 | } | |
814 | current++; | |
815 | } | |
816 | ||
817 | int closed = fclose(outstream); | |
818 | if (closed == EOF) { | |
819 | error = errno; | |
820 | goto close_error_out; | |
821 | } | |
822 | return desc; | |
823 | ||
824 | error_out: | |
825 | (void)fclose(outstream); | |
826 | close_error_out: | |
827 | free(desc); | |
828 | errno = error; | |
829 | return NULL; | |
830 | } | |
831 | ||
832 | #if TARGET_OS_OSX | |
833 | ||
834 | // XXX As an implementation detail, os_boot_mode is piggy-backing on | |
835 | // os_variant's infrastructure. This is not necessarily its long-term home, | |
836 | // particularly after rdar://59966472 | |
837 | ||
838 | static enum boot_mode { | |
839 | BOOTMODE_UNKNOWN = 0, | |
840 | BOOTMODE_NONE, | |
841 | BOOTMODE_FVUNLOCK, | |
842 | BOOTMODE_KCGEN, | |
843 | BOOTMODE_DIAGNOSTICS, | |
844 | BOOTMODE_MIGRATION, | |
845 | } os_boot_mode; | |
846 | ||
847 | static void | |
848 | _os_boot_mode_launchd_init(const char *boot_mode) | |
849 | { | |
850 | if (boot_mode == NULL) { | |
851 | os_boot_mode = BOOTMODE_NONE; | |
852 | } else if (strcmp(boot_mode, OS_BOOT_MODE_FVUNLOCK) == 0) { | |
853 | os_boot_mode = BOOTMODE_FVUNLOCK; | |
854 | } else if (strcmp(boot_mode, OS_BOOT_MODE_KCGEN) == 0) { | |
855 | os_boot_mode = BOOTMODE_KCGEN; | |
856 | } else if (strcmp(boot_mode, OS_BOOT_MODE_DIAGNOSTICS) == 0) { | |
857 | os_boot_mode = BOOTMODE_DIAGNOSTICS; | |
858 | } else if (strcmp(boot_mode, OS_BOOT_MODE_MIGRATION) == 0) { | |
859 | os_boot_mode = BOOTMODE_MIGRATION; | |
860 | } | |
861 | } | |
862 | ||
863 | bool | |
864 | os_boot_mode_query(const char **boot_mode_out) | |
865 | { | |
866 | _initialize_status(); | |
867 | ||
868 | switch (os_boot_mode) { | |
869 | case BOOTMODE_NONE: | |
870 | *boot_mode_out = NULL; | |
871 | return true; | |
872 | case BOOTMODE_FVUNLOCK: | |
873 | *boot_mode_out = OS_BOOT_MODE_FVUNLOCK; | |
874 | return true; | |
875 | case BOOTMODE_KCGEN: | |
876 | *boot_mode_out = OS_BOOT_MODE_KCGEN; | |
877 | return true; | |
878 | case BOOTMODE_DIAGNOSTICS: | |
879 | *boot_mode_out = OS_BOOT_MODE_DIAGNOSTICS; | |
880 | return true; | |
881 | case BOOTMODE_MIGRATION: | |
882 | *boot_mode_out = OS_BOOT_MODE_MIGRATION; | |
883 | return true; | |
884 | default: | |
885 | return false; | |
886 | } | |
887 | } | |
888 | ||
889 | #endif // TARGET_OS_OSX | |
890 | ||
891 | void | |
892 | os_variant_init_4launchd(const char *boot_mode) | |
893 | { | |
894 | #if TARGET_OS_SIMULATOR | |
895 | os_crash("simulator launchd does not initialize os_variant"); | |
896 | #else | |
897 | os_assert(getpid() == 1); | |
898 | ||
899 | _init_has_full_logging(); | |
900 | ||
901 | #if TARGET_OS_OSX | |
902 | _os_boot_mode_launchd_init(boot_mode); | |
903 | #endif | |
904 | ||
905 | // re-initialize disabled status even if we've already initialized | |
906 | // previously, as it's possible we may have initialized before the override | |
907 | // file was available to read | |
908 | _parse_disabled_status(NULL); | |
909 | ||
910 | uint64_t status = _get_cached_check_status(); | |
911 | size_t status_size = sizeof(status); | |
912 | // TODO: assert that this succeeds | |
913 | sysctlbyname(CACHE_SYSCTL_NAME, NULL, 0, &status, status_size); | |
914 | #endif | |
915 | } | |
916 | ||
b061a43b A |
917 | #endif // VARIANT_SKIP_EXPORTED |
918 | ||
a9aaacca A |
919 | /* |
920 | * Bit allocation in kern.osvariant_status (all ranges inclusive): | |
921 | * - [0-27] are 2-bit check_status values | |
922 | * - [28-31] are 0xF | |
923 | * - [32-32+VP_MAX-1] encode variant_property booleans | |
924 | * - [48-51] encode the boot mode, if known | |
925 | * - [60-62] are 0x7 | |
926 | */ | |
b061a43b A |
927 | #define STATUS_INITIAL_BITS 0x70000000F0000000ULL |
928 | #define STATUS_BIT_WIDTH 2 | |
929 | #define STATUS_SET 0x2 | |
930 | #define STATUS_MASK 0x3 | |
931 | ||
932 | enum status_flags_positions { | |
933 | SFP_INTERNAL_CONTENT = 0, | |
934 | SFP_CAN_HAS_DEBUGGER = 1, | |
935 | SFP_INTERNAL_RELEASE_TYPE = 2, | |
6dccf0e0 A |
936 | SFP_INTERNAL_DIAGS_PROFILE = 3, |
937 | SFP_FACTORY_CONTENT = 4, | |
938 | SFP_FACTORY_RELEASE_TYPE = 5, | |
507116e3 A |
939 | SFP_DARWINOS_RELEASE_TYPE = 6, |
940 | SFP_EPHEMERAL_VOLUME = 7, | |
941 | SFP_RECOVERY_RELEASE_TYPE = 8, | |
942 | SFP_BASE_SYSTEM_CONTENT = 9, | |
943 | SFP_DEVELOPMENT_KERNEL = 10, | |
a9aaacca A |
944 | SFP_DARWINOS_CONTENT = 11, |
945 | SFP_FULL_LOGGING = 12, | |
b061a43b A |
946 | }; |
947 | ||
a9aaacca A |
948 | #define STATUS_BOOT_MODE_SHIFT 48 |
949 | #define STATUS_BOOT_MODE_MASK 0x000F000000000000ULL | |
950 | ||
b061a43b A |
951 | #if !TARGET_OS_SIMULATOR |
952 | static uint64_t _get_cached_check_status(void) | |
953 | { | |
a9aaacca A |
954 | _initialize_status(); |
955 | ||
b061a43b A |
956 | uint64_t res = STATUS_INITIAL_BITS; |
957 | ||
958 | #if !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR | |
a9aaacca A |
959 | os_assert(internal_content != S_UNKNOWN); |
960 | res |= internal_content << SFP_INTERNAL_CONTENT * STATUS_BIT_WIDTH; | |
b061a43b A |
961 | #endif |
962 | ||
a9aaacca A |
963 | os_assert(can_has_debugger != S_UNKNOWN); |
964 | res |= can_has_debugger << SFP_CAN_HAS_DEBUGGER * STATUS_BIT_WIDTH; | |
b061a43b | 965 | |
a9aaacca A |
966 | os_assert(is_ephemeral != S_UNKNOWN); |
967 | res |= is_ephemeral << SFP_EPHEMERAL_VOLUME * STATUS_BIT_WIDTH; | |
968 | ||
969 | #ifdef VARIANT_SKIP_EXPORTED | |
970 | // has_full_logging can't be computed outside launchd, so in the tests/etc. | |
971 | // cheat and use the value reported by libdarwin rather than re-computing | |
972 | has_full_logging = os_variant_check("com.apple.Libc.tests", "HasFullLogging") ? | |
973 | S_YES : S_NO; | |
974 | #else | |
975 | os_assert(has_full_logging != S_UNKNOWN); | |
976 | #endif | |
977 | res |= has_full_logging << SFP_FULL_LOGGING * STATUS_BIT_WIDTH; | |
507116e3 | 978 | |
b061a43b | 979 | #if TARGET_OS_IPHONE |
a9aaacca A |
980 | os_assert(internal_release_type != S_UNKNOWN); |
981 | res |= internal_release_type << SFP_INTERNAL_RELEASE_TYPE * STATUS_BIT_WIDTH; | |
6dccf0e0 | 982 | |
a9aaacca A |
983 | os_assert(factory_release_type != S_UNKNOWN); |
984 | res |= factory_release_type << SFP_FACTORY_RELEASE_TYPE * STATUS_BIT_WIDTH; | |
507116e3 | 985 | |
a9aaacca A |
986 | os_assert(darwin_release_type != S_UNKNOWN); |
987 | res |= darwin_release_type << SFP_DARWINOS_RELEASE_TYPE * STATUS_BIT_WIDTH; | |
507116e3 | 988 | |
a9aaacca A |
989 | os_assert(recovery_release_type != S_UNKNOWN); |
990 | res |= recovery_release_type << SFP_RECOVERY_RELEASE_TYPE * STATUS_BIT_WIDTH; | |
507116e3 | 991 | |
a9aaacca A |
992 | os_assert(development_kernel != S_UNKNOWN); |
993 | res |= development_kernel << SFP_DEVELOPMENT_KERNEL * STATUS_BIT_WIDTH; | |
b061a43b | 994 | #else |
a9aaacca A |
995 | os_assert(internal_diags_profile != S_UNKNOWN); |
996 | res |= internal_diags_profile << SFP_INTERNAL_DIAGS_PROFILE * STATUS_BIT_WIDTH; | |
997 | ||
998 | os_assert(factory_content != S_UNKNOWN); | |
999 | res |= factory_content << SFP_FACTORY_CONTENT * STATUS_BIT_WIDTH; | |
6dccf0e0 | 1000 | |
a9aaacca A |
1001 | os_assert(base_system_content != S_UNKNOWN); |
1002 | res |= base_system_content << SFP_BASE_SYSTEM_CONTENT * STATUS_BIT_WIDTH; | |
507116e3 | 1003 | |
a9aaacca A |
1004 | os_assert(darwinos_content != S_UNKNOWN); |
1005 | res |= darwinos_content << SFP_DARWINOS_CONTENT * STATUS_BIT_WIDTH; | |
b061a43b A |
1006 | #endif |
1007 | ||
b061a43b A |
1008 | for (int i = 0; i < VP_MAX; i++) { |
1009 | if (disabled_status[i]) { | |
1010 | res |= 0x1ULL << (i + 32); | |
1011 | } | |
1012 | } | |
1013 | ||
a9aaacca A |
1014 | #if !defined(VARIANT_SKIP_EXPORTED) && TARGET_OS_OSX |
1015 | res |= ((uint64_t)os_boot_mode) << STATUS_BOOT_MODE_SHIFT; | |
1016 | #endif // TARGET_OS_OSX | |
1017 | ||
b061a43b A |
1018 | return res; |
1019 | } | |
1020 | ||
1021 | static void _restore_cached_check_status(uint64_t status) | |
1022 | { | |
1023 | #if !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR | |
1024 | if ((status >> (SFP_INTERNAL_CONTENT * STATUS_BIT_WIDTH)) & STATUS_SET) | |
1025 | internal_content = (status >> (SFP_INTERNAL_CONTENT * STATUS_BIT_WIDTH)) & STATUS_MASK; | |
1026 | #endif | |
6dccf0e0 | 1027 | |
b061a43b A |
1028 | if ((status >> (SFP_CAN_HAS_DEBUGGER * STATUS_BIT_WIDTH)) & STATUS_SET) |
1029 | can_has_debugger = (status >> (SFP_CAN_HAS_DEBUGGER * STATUS_BIT_WIDTH)) & STATUS_MASK; | |
6dccf0e0 | 1030 | |
507116e3 A |
1031 | if ((status >> (SFP_EPHEMERAL_VOLUME * STATUS_BIT_WIDTH)) & STATUS_SET) |
1032 | is_ephemeral = (status >> (SFP_EPHEMERAL_VOLUME * STATUS_BIT_WIDTH)) & STATUS_MASK; | |
1033 | ||
a9aaacca A |
1034 | if ((status >> (SFP_FULL_LOGGING * STATUS_BIT_WIDTH)) & STATUS_SET) |
1035 | has_full_logging = (status >> (SFP_FULL_LOGGING * STATUS_BIT_WIDTH)) & STATUS_MASK; | |
1036 | ||
b061a43b A |
1037 | #if TARGET_OS_IPHONE |
1038 | if ((status >> (SFP_INTERNAL_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_SET) | |
1039 | internal_release_type = (status >> (SFP_INTERNAL_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_MASK; | |
6dccf0e0 A |
1040 | |
1041 | if ((status >> (SFP_FACTORY_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_SET) | |
1042 | factory_release_type = (status >> (SFP_FACTORY_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_MASK; | |
507116e3 A |
1043 | |
1044 | if ((status >> (SFP_DARWINOS_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_SET) | |
1045 | darwin_release_type = (status >> (SFP_DARWINOS_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_MASK; | |
1046 | ||
1047 | if ((status >> (SFP_RECOVERY_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_SET) | |
1048 | recovery_release_type = (status >> (SFP_RECOVERY_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_MASK; | |
1049 | ||
1050 | if ((status >> (SFP_DEVELOPMENT_KERNEL * STATUS_BIT_WIDTH)) & STATUS_SET) | |
1051 | development_kernel = (status >> (SFP_DEVELOPMENT_KERNEL * STATUS_BIT_WIDTH)) & STATUS_MASK; | |
b061a43b A |
1052 | #else |
1053 | if ((status >> (SFP_INTERNAL_DIAGS_PROFILE * STATUS_BIT_WIDTH)) & STATUS_SET) | |
1054 | internal_diags_profile = (status >> (SFP_INTERNAL_DIAGS_PROFILE * STATUS_BIT_WIDTH)) & STATUS_MASK; | |
6dccf0e0 A |
1055 | |
1056 | if ((status >> (SFP_FACTORY_CONTENT * STATUS_BIT_WIDTH)) & STATUS_SET) | |
1057 | factory_content = (status >> (SFP_FACTORY_CONTENT * STATUS_BIT_WIDTH)) & STATUS_MASK; | |
507116e3 A |
1058 | |
1059 | if ((status >> (SFP_BASE_SYSTEM_CONTENT * STATUS_BIT_WIDTH)) & STATUS_SET) | |
1060 | base_system_content = (status >> (SFP_BASE_SYSTEM_CONTENT * STATUS_BIT_WIDTH)) & STATUS_MASK; | |
a9aaacca A |
1061 | |
1062 | if ((status >> (SFP_DARWINOS_CONTENT * STATUS_BIT_WIDTH)) & STATUS_SET) | |
1063 | darwinos_content = (status >> (SFP_DARWINOS_CONTENT * STATUS_BIT_WIDTH)) & STATUS_MASK; | |
b061a43b A |
1064 | #endif |
1065 | ||
1066 | for (int i = 0; i < VP_MAX; i++) { | |
1067 | disabled_status[i] = (status >> (32 + i)) & 0x1; | |
1068 | } | |
a9aaacca A |
1069 | |
1070 | #if !defined(VARIANT_SKIP_EXPORTED) && TARGET_OS_OSX | |
1071 | os_boot_mode = (enum boot_mode)((status & STATUS_BOOT_MODE_MASK) >> STATUS_BOOT_MODE_SHIFT); | |
1072 | #endif // TARGET_OS_OSX | |
b061a43b A |
1073 | } |
1074 | #endif // !TARGET_OS_SIMULATOR |