+/*
+ * Create sysctl entries coming from device tree.
+ *
+ * Entries from device tree are loaded here because DTLookupEntry() only works before
+ * PE_init_iokit(). Doing this also avoids the extern-C hackery to access these entries
+ * from IORegistry (which requires C++).
+ */
+void
+sysctl_load_devicetree_entries(void)
+{
+ DTEntry chosen;
+ void *value;
+ unsigned int size;
+
+ if (kSuccess != DTLookupEntry(0, "/chosen", &chosen)) {
+ return;
+ }
+
+ /* load osenvironment */
+ if (kSuccess == DTGetProperty(chosen, "osenvironment", (void **) &value, &size)) {
+ MALLOC(osenvironment, char *, size, M_TEMP, M_WAITOK);
+ if (osenvironment) {
+ memcpy(osenvironment, value, size);
+ osenvironment_size = size;
+ }
+ }
+
+ /* load ephemeral_storage */
+ if (kSuccess == DTGetProperty(chosen, "ephemeral-storage", (void **) &value, &size)) {
+ if (size == sizeof(uint32_t)) {
+ ephemeral_storage = *(uint32_t *)value;
+ property_existence.ephemeral_storage = 1;
+ }
+ }
+
+ /* load use_recovery_securityd */
+ if (kSuccess == DTGetProperty(chosen, "use-recovery-securityd", (void **) &value, &size)) {
+ if (size == sizeof(uint32_t)) {
+ use_recovery_securityd = *(uint32_t *)value;
+ property_existence.use_recovery_securityd = 1;
+ }
+ }
+}
+
+static int
+sysctl_osenvironment
+(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
+{
+ if (osenvironment_size > 0) {
+ return SYSCTL_OUT(req, osenvironment, osenvironment_size);
+ } else {
+ return EINVAL;
+ }
+}
+
+static int
+sysctl_ephemeral_storage
+(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
+{
+ if (property_existence.ephemeral_storage) {
+ return SYSCTL_OUT(req, &ephemeral_storage, sizeof(ephemeral_storage));
+ } else {
+ return EINVAL;
+ }
+}
+
+static int
+sysctl_use_recovery_securityd
+(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
+{
+ if (property_existence.use_recovery_securityd) {
+ return SYSCTL_OUT(req, &use_recovery_securityd, sizeof(use_recovery_securityd));
+ } else {
+ return EINVAL;
+ }
+}
+