]> git.saurik.com Git - apple/libc.git/blob - libdarwin/variant.c
Libc-1353.100.2.tar.gz
[apple/libc.git] / libdarwin / variant.c
1 /*
2 * Copyright (c) 2016 Apple Inc. All rights reserved.
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
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <sys/stat.h>
27 #include <sys/sysctl.h>
28 #include <sys/types.h>
29 #include <dispatch/dispatch.h>
30 #include <xpc/xpc.h>
31 #include <xpc/private.h>
32 #include <System/sys/csr.h>
33 #include <System/machine/cpu_capabilities.h>
34
35 #include <os/assumes.h>
36 #include <os/bsd.h>
37 #include <os/stdlib.h>
38 #include <os/variant_private.h>
39
40 /*
41 * Lists all properties overridden by an empty file
42 */
43 #define ALL_OVERRIDES_STR "content,diagnostics,ui,security"
44
45 enum variant_property {
46 VP_CONTENT,
47 VP_DIAGNOSTICS,
48 VP_UI,
49 VP_SECURITY,
50 VP_MAX
51 };
52
53 enum check_status {
54 S_UNKNOWN = 0,
55 S_NO = 2,
56 S_YES = 3
57 };
58
59 typedef struct {
60 const char *variant;
61 bool (*function)(const char*);
62 } variant_check_mapping;
63
64 static bool
65 status2bool(enum check_status status) {
66 switch (status) {
67 case S_NO:
68 return false;
69 case S_YES:
70 return true;
71 case S_UNKNOWN:
72 default:
73 os_crash("os_variant had unexpected status");
74 }
75 }
76
77 #define VAR_FILE_LEGACY "/var/db/disableAppleInternal"
78
79 #if TARGET_OS_OSX
80 #define VAR_FILE_OVERRIDE "/var/db/os_variant_override"
81 #else
82 #define VAR_FILE_OVERRIDE "/usr/share/misc/os_variant_override"
83 #endif
84
85 #if !TARGET_OS_SIMULATOR
86 #define INTERNAL_CONTENT_PATH "/System/Library/CoreServices/AppleInternalVariant.plist"
87 #else
88 #define INTERNAL_CONTENT_PATH "/AppleInternal"
89 #endif
90
91 #define SYSTEM_VERSION_PLIST_PATH "/System/Library/CoreServices/SystemVersion.plist"
92 #define SYSTEM_VERSION_PLIST_KEY "ReleaseType"
93
94 #if TARGET_OS_IPHONE
95 #define INTERNAL_SETTINGS_PATH "/AppleInternal/Library/PreferenceBundles/Internal Settings.bundle"
96 #else
97 #define INTERNAL_DIAGS_PROFILE_PATH "/var/db/ConfigurationProfiles/Settings/com.apple.InternalDiagnostics.plist"
98 #define FACTORY_CONTENT_PATH "/System/Library/CoreServices/AppleFactoryVariant.plist"
99 #define BASE_SYSTEM_CONTENT_PATH "/System/Library/BaseSystem"
100 #endif
101
102 #if !TARGET_OS_SIMULATOR
103 #define CACHE_SYSCTL_NAME "kern.osvariant_status"
104
105 static void _restore_cached_check_status(uint64_t status);
106 static uint64_t _get_cached_check_status(void);
107
108 static char * _read_file(const char *path, size_t *size_out)
109 {
110 char *buf = NULL;
111
112 int fd = open(path, O_RDONLY);
113 if (fd == -1) return NULL;
114
115 struct stat sb;
116 int rc = fstat(fd, &sb);
117 if (rc != 0 || sb.st_size == 0) {
118 goto error;
119 }
120
121 size_t size_limit = (size_out && *size_out != 0) ? *size_out : 1024;
122 size_t size = (size_t)sb.st_size;
123 if (size_out) *size_out = (size_t)sb.st_size;
124 if (size > size_limit) {
125 goto error;
126 }
127
128 buf = malloc(size + 1);
129 if (!buf) {
130 goto error;
131 }
132
133 ssize_t bytes_read = read(fd, buf, size);
134 buf[size] = '\0';
135
136
137 if (bytes_read == (ssize_t)size) {
138 close(fd);
139 return buf;
140 }
141
142 error:
143 close(fd);
144 free(buf);
145 return NULL;
146 }
147
148 static xpc_object_t read_plist(const char *path)
149 {
150 size_t size = 16 * 1024;
151 uint8_t *buf = (uint8_t*)_read_file(path, &size);
152 if (!buf) return NULL;
153
154 xpc_object_t plist = xpc_create_from_plist(buf, size);
155 if (plist && xpc_get_type(plist) != XPC_TYPE_DICTIONARY) {
156 xpc_release(plist);
157 plist = NULL;
158 }
159
160 free(buf);
161
162 return plist;
163 }
164 #endif
165
166 #if !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
167 static enum check_status internal_content = S_UNKNOWN;
168 #endif
169 #if !TARGET_OS_SIMULATOR
170 static enum check_status can_has_debugger = S_UNKNOWN;
171 #if TARGET_OS_IPHONE
172 static enum check_status internal_release_type = S_UNKNOWN;
173 static enum check_status factory_release_type = S_UNKNOWN;
174 static enum check_status darwin_release_type = S_UNKNOWN;
175 static enum check_status recovery_release_type = S_UNKNOWN;
176 static enum check_status development_kernel = S_UNKNOWN;
177 #else // TARGET_OS_IPHONE
178 static enum check_status internal_diags_profile = S_UNKNOWN;
179 static enum check_status factory_content = S_UNKNOWN;
180 static enum check_status base_system_content = S_UNKNOWN;
181 #endif // TARGET_OS_IPHONE
182 #endif // !TARGET_OS_SIMULATOR
183 static enum check_status is_ephemeral = S_UNKNOWN;
184
185 static bool disabled_status[VP_MAX] = {};
186
187 static void _parse_disabled_status(char *test_string)
188 {
189 #if TARGET_OS_SIMULATOR
190 #pragma unused(test_string)
191 #else // TARGET_OS_SIMULATOR
192 char *override_str = NULL;
193
194 bzero(disabled_status, sizeof(disabled_status));
195
196 if (test_string != NULL) {
197 /* used for unit tests */
198 override_str = os_strdup(test_string);
199 } else {
200 if (access(VAR_FILE_LEGACY, F_OK) == 0) {
201 override_str = os_strdup(ALL_OVERRIDES_STR);
202 } else if (access(VAR_FILE_OVERRIDE, F_OK) != 0) {
203 return;
204 }
205
206 override_str = _read_file(VAR_FILE_OVERRIDE, NULL);
207 }
208
209 if (override_str == NULL) {
210 override_str = os_strdup(ALL_OVERRIDES_STR);
211 }
212
213 char *token, *string = override_str;
214 while ((token = strsep(&string, ",\n")) != NULL) {
215 if (strcmp(token, "content") == 0) {
216 disabled_status[VP_CONTENT] = true;
217 } else if (strcmp(token, "diagnostics") == 0) {
218 disabled_status[VP_DIAGNOSTICS] = true;
219 } else if (strcmp(token, "ui") == 0) {
220 disabled_status[VP_UI] = true;
221 } else if (strcmp(token, "security") == 0) {
222 disabled_status[VP_SECURITY] = true;
223 }
224 }
225
226 free(override_str);
227 return;
228 #endif //!TARGET_OS_SIMULATOR
229 }
230
231 #if !TARGET_OS_SIMULATOR
232 static bool _load_cached_status(void)
233 {
234 uint64_t status = 0;
235 size_t status_size = sizeof(status);
236 int ret = sysctlbyname(CACHE_SYSCTL_NAME, &status, &status_size, NULL, 0);
237 if (ret != 0) {
238 return false;
239 }
240
241 if (status) {
242 _restore_cached_check_status(status);
243 return true;
244 }
245
246 if (status == 0 && getpid() == 1) {
247 /*
248 * Looks like we are in launchd; try to set the status.
249 *
250 * We don't actually care if this works because we'll have warmed our state.
251 */
252 status = _get_cached_check_status();
253 sysctlbyname(CACHE_SYSCTL_NAME, NULL, 0, &status, status_size);
254 return true;
255 }
256
257 return false;
258 }
259 #endif
260
261 static void _initialize_status(void * __unused ctx)
262 {
263 #if !TARGET_OS_SIMULATOR
264 if (!_load_cached_status()) {
265 _parse_disabled_status(NULL);
266 }
267 #else
268 _parse_disabled_status(NULL);
269 #endif
270 }
271
272 static bool _check_disabled(enum variant_property variant_property)
273 {
274 static dispatch_once_t disabled_status_pred;
275 dispatch_once_f(&disabled_status_pred, NULL, _initialize_status);
276
277 return disabled_status[variant_property];
278 }
279
280 #if !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
281 static bool _check_internal_content(void)
282 {
283 if (internal_content == S_UNKNOWN) {
284 #if !TARGET_OS_SIMULATOR
285 const char * path = INTERNAL_CONTENT_PATH;
286 #else
287 char *simulator_root = getenv("IPHONE_SIMULATOR_ROOT");
288 char *to_free = NULL, *path = NULL;
289 if (simulator_root) {
290 asprintf(&path, "%s/%s", simulator_root, INTERNAL_CONTENT_PATH);
291 if (path == NULL) {
292 return false;
293 }
294 to_free = path;
295 }
296 #endif
297 internal_content = (access(path, F_OK) == 0) ? S_YES : S_NO;
298 #if TARGET_OS_SIMULATOR
299 free(to_free);
300 #endif
301 }
302 return status2bool(internal_content);
303 }
304 #endif // !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
305
306 #if TARGET_OS_OSX
307 static bool _check_factory_content(void)
308 {
309 if (factory_content == S_UNKNOWN) {
310 const char * path = FACTORY_CONTENT_PATH;
311 factory_content = (access(path, F_OK) == 0) ? S_YES : S_NO;
312 }
313 return status2bool(factory_content);
314 }
315 #endif // TARGET_OS_OSX
316
317 #if TARGET_OS_IPHONE
318
319 #if !TARGET_OS_SIMULATOR
320 static bool _parse_system_version_plist(void)
321 {
322 xpc_object_t system_version_plist = read_plist(SYSTEM_VERSION_PLIST_PATH);
323 if (!system_version_plist) {
324 return false;
325 }
326
327 const char *release_type =
328 xpc_dictionary_get_string(system_version_plist,
329 SYSTEM_VERSION_PLIST_KEY);
330
331 if (release_type == NULL) {
332 /*
333 * Confusingly, customer images are just completely missing this key.
334 */
335 internal_release_type = S_NO;
336 factory_release_type = S_NO;
337 darwin_release_type = S_NO;
338 recovery_release_type = S_NO;
339 } else if (strcmp(release_type, "NonUI") == 0) {
340 factory_release_type = S_YES;
341 internal_release_type = S_YES;
342 darwin_release_type = S_NO;
343 recovery_release_type = S_NO;
344 } else {
345 factory_release_type = S_NO;
346 internal_release_type = (strstr(release_type, "Internal") != NULL) ? S_YES : S_NO;
347 darwin_release_type = (strstr(release_type, "Darwin") != NULL) ? S_YES : S_NO;
348 recovery_release_type = (strstr(release_type, "Recovery") != NULL) ? S_YES : S_NO;
349 }
350
351 xpc_release(system_version_plist);
352
353 return true;
354 }
355 #endif //!TARGET_OS_SIMULATOR
356
357 /*
358 * This set of criteria was taken from copyInternalBuild in MobileGestalt.c
359 */
360 static bool _check_internal_release_type(void)
361 {
362 #if TARGET_OS_SIMULATOR
363 return _check_internal_content();
364 #else // TARGET_OS_SIMULATOR
365 if (internal_release_type == S_UNKNOWN) {
366 if (!_parse_system_version_plist()) {
367 internal_release_type = (access(INTERNAL_SETTINGS_PATH, F_OK) == 0) ? S_YES : S_NO;
368 }
369 }
370
371 return status2bool(internal_release_type);
372 #endif // TARGET_OS_SIMULATOR
373 }
374
375 static bool _check_factory_release_type(void)
376 {
377 #if TARGET_OS_SIMULATOR
378 return false;
379 #else // TARGET_OS_SIMULATOR
380 if (factory_release_type == S_UNKNOWN) {
381 if (!_parse_system_version_plist()) {
382 factory_release_type = S_NO;
383 }
384 }
385
386 return status2bool(factory_release_type);
387 #endif // TARGET_OS_SIMULATOR
388 }
389
390 static bool _check_darwin_release_type(void)
391 {
392 #if TARGET_OS_SIMULATOR
393 return false;
394 #else // TARGET_OS_SIMULATOR
395 if (darwin_release_type == S_UNKNOWN) {
396 if (!_parse_system_version_plist()) {
397 darwin_release_type = S_NO;
398 }
399 }
400
401 return status2bool(darwin_release_type);
402 #endif // TARGET_OS_SIMULATOR
403 }
404
405 static bool _check_recovery_release_type(void)
406 {
407 #if TARGET_OS_SIMULATOR
408 return false;
409 #else // TARGET_OS_SIMULATOR
410 if (recovery_release_type == S_UNKNOWN) {
411 if (!_parse_system_version_plist()) {
412 recovery_release_type = S_NO;
413 }
414 }
415
416 return status2bool(recovery_release_type);
417 #endif // TARGET_OS_SIMULATOR
418 }
419
420 #else // TARGET_OS_IPHONE
421
422 static bool _check_internal_diags_profile(void)
423 {
424 if (internal_diags_profile == S_UNKNOWN) {
425 xpc_object_t profile_settings = read_plist(INTERNAL_DIAGS_PROFILE_PATH);
426 if (profile_settings) {
427 internal_diags_profile = xpc_dictionary_get_bool(profile_settings, "AppleInternal") ? S_YES : S_NO;
428 xpc_release(profile_settings);
429 } else {
430 internal_diags_profile = S_NO;
431 }
432 }
433
434 return status2bool(internal_diags_profile);
435 }
436
437 static bool _check_base_system_content(void)
438 {
439 if (base_system_content == S_UNKNOWN) {
440 const char * path = BASE_SYSTEM_CONTENT_PATH;
441 base_system_content = (access(path, F_OK) == 0) ? S_YES : S_NO;
442 }
443 return status2bool(base_system_content);
444 }
445
446 #endif
447
448 #if !TARGET_OS_SIMULATOR
449 static bool _check_can_has_debugger(void)
450 {
451 if (can_has_debugger == S_UNKNOWN) {
452 #if TARGET_OS_IPHONE
453 can_has_debugger = *((uint32_t *)_COMM_PAGE_DEV_FIRM) ? S_YES : S_NO;
454 #else
455 /*
456 * The comm page bit does exist on macOS, but also requires kernel
457 * debugging in the CSR configuration. We don't need to be that strict
458 * here.
459 */
460 can_has_debugger = (csr_check(CSR_ALLOW_APPLE_INTERNAL) == 0) ? S_YES : S_NO;
461 #endif
462 }
463 return status2bool(can_has_debugger);
464 }
465 #endif // !TARGET_OS_SIMULATOR
466
467 #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
468 static bool _check_development_kernel(void)
469 {
470 if (development_kernel == S_UNKNOWN) {
471 /*
472 * Whitelist values from SUPPORTED_KERNEL_CONFIGS.
473 */
474 char *osbuildconfig = NULL;
475 size_t osbuildconfig_sz = 0;
476 errno_t err = sysctlbyname_get_data_np("kern.osbuildconfig", (void **)&osbuildconfig, &osbuildconfig_sz);
477 if (err == 0) {
478 if (strcmp(osbuildconfig, "development") == 0 ||
479 strcmp(osbuildconfig, "debug") == 0 ||
480 strcmp(osbuildconfig, "profile") == 0 ||
481 strcmp(osbuildconfig, "kasan") == 0) {
482 development_kernel = S_YES;
483 }
484 }
485 free(osbuildconfig);
486
487 if (development_kernel == S_UNKNOWN) {
488 development_kernel = S_NO;
489 }
490 }
491 return status2bool(development_kernel);
492 }
493 #endif // TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
494
495 // For unit tests
496 #ifndef VARIANT_SKIP_EXPORTED
497
498 bool
499 os_variant_has_internal_content(const char * __unused subsystem)
500 {
501 if (_check_disabled(VP_CONTENT)) {
502 return false;
503 }
504
505 #if TARGET_OS_IPHONE
506 return _check_internal_release_type();
507 #else
508 return _check_internal_content();
509 #endif
510 }
511
512
513 bool
514 os_variant_has_internal_diagnostics(const char * __unused subsystem)
515 {
516 if (_check_disabled(VP_DIAGNOSTICS)) {
517 return false;
518 }
519
520 #if TARGET_OS_IPHONE
521 return _check_internal_release_type();
522 #else
523 return _check_internal_content() || _check_internal_diags_profile();
524 #endif
525 }
526
527 bool
528 os_variant_has_internal_ui(const char * __unused subsystem)
529 {
530 if (_check_disabled(VP_UI)) {
531 return false;
532 }
533
534 #if TARGET_OS_IPHONE
535 return _check_internal_release_type();
536 #else
537 return _check_internal_content();
538 #endif
539 }
540
541 bool
542 os_variant_allows_internal_security_policies(const char * __unused subsystem)
543 {
544 if (_check_disabled(VP_SECURITY)) {
545 return false;
546 }
547
548 #if TARGET_OS_SIMULATOR
549 return _check_internal_content();
550 #elif TARGET_OS_IPHONE
551 return _check_can_has_debugger() || _check_development_kernel();
552 #else
553 return _check_can_has_debugger();
554 #endif
555 }
556
557 bool
558 os_variant_has_factory_content(const char * __unused subsystem)
559 {
560 #if TARGET_OS_IPHONE
561 return _check_factory_release_type();
562 #else
563 return _check_factory_content();
564 #endif
565 }
566
567 bool
568 os_variant_is_darwinos(const char * __unused subsystem)
569 {
570
571 #if TARGET_OS_IPHONE
572 return _check_darwin_release_type();
573 #else
574 return false;
575 #endif
576 }
577
578 bool
579 os_variant_is_recovery(const char * __unused subsystem)
580 {
581 #if TARGET_OS_IPHONE
582 return _check_recovery_release_type();
583 #else
584 return _check_base_system_content();
585 #endif
586 }
587
588 bool
589 os_variant_uses_ephemeral_storage(const char * __unused subsystem)
590 {
591 if (is_ephemeral == S_UNKNOWN) {
592 uint32_t buffer = 0;
593 size_t buffer_size = sizeof(buffer);
594
595 sysctlbyname("hw.ephemeral_storage", (void *)&buffer, &buffer_size, NULL, 0);
596
597 is_ephemeral = (buffer != 0) ? S_YES : S_NO;
598 }
599
600 return status2bool(is_ephemeral);
601 }
602
603 bool
604 os_variant_check(const char * __unused subsystem, const char *variant)
605 {
606 static const variant_check_mapping map[] = {
607 {.variant = "HasInternalContent", .function = os_variant_has_internal_content},
608 {.variant = "HasInternalDiagnostics", .function = os_variant_has_internal_diagnostics},
609 {.variant = "HasInternalUI", .function = os_variant_has_internal_ui},
610 {.variant = "AllowsInternalSecurityPolicies", .function = os_variant_allows_internal_security_policies},
611 {.variant = "HasFactoryContent", .function = os_variant_has_factory_content},
612 {.variant = "IsDarwinOS", .function = os_variant_is_darwinos},
613 {.variant = "UsesEphemeralStorage", .function = os_variant_uses_ephemeral_storage},
614 {.variant = "IsRecovery", .function = os_variant_is_recovery},
615 {.variant = NULL, .function = NULL}
616 };
617 variant_check_mapping *current = (variant_check_mapping *)map;
618
619 while (current->variant) {
620 if (0 == strncasecmp(current->variant, variant, strlen(current->variant))) {
621 return current->function("");
622 }
623 current ++;
624 }
625
626 return false;
627 }
628
629 #endif // VARIANT_SKIP_EXPORTED
630
631 #define STATUS_INITIAL_BITS 0x70000000F0000000ULL
632 #define STATUS_BIT_WIDTH 2
633 #define STATUS_SET 0x2
634 #define STATUS_MASK 0x3
635
636 enum status_flags_positions {
637 SFP_INTERNAL_CONTENT = 0,
638 SFP_CAN_HAS_DEBUGGER = 1,
639 SFP_INTERNAL_RELEASE_TYPE = 2,
640 SFP_INTERNAL_DIAGS_PROFILE = 3,
641 SFP_FACTORY_CONTENT = 4,
642 SFP_FACTORY_RELEASE_TYPE = 5,
643 SFP_DARWINOS_RELEASE_TYPE = 6,
644 SFP_EPHEMERAL_VOLUME = 7,
645 SFP_RECOVERY_RELEASE_TYPE = 8,
646 SFP_BASE_SYSTEM_CONTENT = 9,
647 SFP_DEVELOPMENT_KERNEL = 10,
648 };
649
650 #if !TARGET_OS_SIMULATOR
651 static uint64_t _get_cached_check_status(void)
652 {
653 uint64_t res = STATUS_INITIAL_BITS;
654
655 #if !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
656 _check_internal_content();
657 if (internal_content != S_UNKNOWN)
658 res |= internal_content << SFP_INTERNAL_CONTENT * STATUS_BIT_WIDTH;
659 #endif
660
661 _check_can_has_debugger();
662 if (can_has_debugger != S_UNKNOWN)
663 res |= can_has_debugger << SFP_CAN_HAS_DEBUGGER * STATUS_BIT_WIDTH;
664
665 (void)os_variant_uses_ephemeral_storage("");
666 if (is_ephemeral != S_UNKNOWN)
667 res |= is_ephemeral << SFP_EPHEMERAL_VOLUME * STATUS_BIT_WIDTH;
668
669 #if TARGET_OS_IPHONE
670 _check_internal_release_type();
671 if (internal_release_type != S_UNKNOWN)
672 res |= internal_release_type << SFP_INTERNAL_RELEASE_TYPE * STATUS_BIT_WIDTH;
673
674 _check_factory_release_type();
675 if (factory_release_type != S_UNKNOWN)
676 res |= factory_release_type << SFP_FACTORY_RELEASE_TYPE * STATUS_BIT_WIDTH;
677
678 _check_darwin_release_type();
679 if (darwin_release_type != S_UNKNOWN)
680 res |= darwin_release_type << SFP_DARWINOS_RELEASE_TYPE * STATUS_BIT_WIDTH;
681
682 _check_recovery_release_type();
683 if (recovery_release_type != S_UNKNOWN)
684 res |= recovery_release_type << SFP_RECOVERY_RELEASE_TYPE * STATUS_BIT_WIDTH;
685
686 _check_development_kernel();
687 if (development_kernel != S_UNKNOWN)
688 res |= development_kernel << SFP_DEVELOPMENT_KERNEL * STATUS_BIT_WIDTH;
689 #else
690 _check_internal_diags_profile();
691 if (internal_diags_profile != S_UNKNOWN)
692 res |= internal_diags_profile << SFP_INTERNAL_DIAGS_PROFILE * STATUS_BIT_WIDTH;
693
694 _check_factory_content();
695 if (factory_content != S_UNKNOWN)
696 res |= factory_content << SFP_FACTORY_CONTENT * STATUS_BIT_WIDTH;
697
698 _check_base_system_content();
699 if (base_system_content != S_UNKNOWN)
700 res |= base_system_content << SFP_BASE_SYSTEM_CONTENT * STATUS_BIT_WIDTH;
701 #endif
702
703 _parse_disabled_status(NULL);
704 for (int i = 0; i < VP_MAX; i++) {
705 if (disabled_status[i]) {
706 res |= 0x1ULL << (i + 32);
707 }
708 }
709
710 return res;
711 }
712
713 static void _restore_cached_check_status(uint64_t status)
714 {
715 #if !TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
716 if ((status >> (SFP_INTERNAL_CONTENT * STATUS_BIT_WIDTH)) & STATUS_SET)
717 internal_content = (status >> (SFP_INTERNAL_CONTENT * STATUS_BIT_WIDTH)) & STATUS_MASK;
718 #endif
719
720 if ((status >> (SFP_CAN_HAS_DEBUGGER * STATUS_BIT_WIDTH)) & STATUS_SET)
721 can_has_debugger = (status >> (SFP_CAN_HAS_DEBUGGER * STATUS_BIT_WIDTH)) & STATUS_MASK;
722
723 if ((status >> (SFP_EPHEMERAL_VOLUME * STATUS_BIT_WIDTH)) & STATUS_SET)
724 is_ephemeral = (status >> (SFP_EPHEMERAL_VOLUME * STATUS_BIT_WIDTH)) & STATUS_MASK;
725
726 #if TARGET_OS_IPHONE
727 if ((status >> (SFP_INTERNAL_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_SET)
728 internal_release_type = (status >> (SFP_INTERNAL_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_MASK;
729
730 if ((status >> (SFP_FACTORY_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_SET)
731 factory_release_type = (status >> (SFP_FACTORY_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_MASK;
732
733 if ((status >> (SFP_DARWINOS_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_SET)
734 darwin_release_type = (status >> (SFP_DARWINOS_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_MASK;
735
736 if ((status >> (SFP_RECOVERY_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_SET)
737 recovery_release_type = (status >> (SFP_RECOVERY_RELEASE_TYPE * STATUS_BIT_WIDTH)) & STATUS_MASK;
738
739 if ((status >> (SFP_DEVELOPMENT_KERNEL * STATUS_BIT_WIDTH)) & STATUS_SET)
740 development_kernel = (status >> (SFP_DEVELOPMENT_KERNEL * STATUS_BIT_WIDTH)) & STATUS_MASK;
741 #else
742 if ((status >> (SFP_INTERNAL_DIAGS_PROFILE * STATUS_BIT_WIDTH)) & STATUS_SET)
743 internal_diags_profile = (status >> (SFP_INTERNAL_DIAGS_PROFILE * STATUS_BIT_WIDTH)) & STATUS_MASK;
744
745 if ((status >> (SFP_FACTORY_CONTENT * STATUS_BIT_WIDTH)) & STATUS_SET)
746 factory_content = (status >> (SFP_FACTORY_CONTENT * STATUS_BIT_WIDTH)) & STATUS_MASK;
747
748 if ((status >> (SFP_BASE_SYSTEM_CONTENT * STATUS_BIT_WIDTH)) & STATUS_SET)
749 base_system_content = (status >> (SFP_BASE_SYSTEM_CONTENT * STATUS_BIT_WIDTH)) & STATUS_MASK;
750 #endif
751
752 for (int i = 0; i < VP_MAX; i++) {
753 disabled_status[i] = (status >> (32 + i)) & 0x1;
754 }
755 }
756 #endif // !TARGET_OS_SIMULATOR