/*
 * Copyright (c) 2000, 2024 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
 *
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. The rights granted to you under the License
 * may not be used to create, or enable the creation or redistribution of,
 * unlawful or unlicensed copies of an Apple operating system, or to
 * circumvent, violate, or enable the circumvention or violation of, any
 * terms of an Apple operating system software license agreement.
 *
 * Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this file.
 *
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
 */
#ifndef _PEXPERT_DEVICE_TREE_H_
#define _PEXPERT_DEVICE_TREE_H_

#include <stdbool.h>

#include <mach/mach_types.h>
#include <mach/vm_types.h>

#include <sys/appleapiopts.h>

#ifdef __APPLE_API_PRIVATE

#ifdef __cplusplus
extern "C" {
#endif

/*
 *  -------------------------------------------------------------------------------
 *  Foundation Types
 *  -------------------------------------------------------------------------------
 */
enum {
	kDTPathNameSeparator    = '/'                           /* 0x2F */
};


/* Property Name Definitions (Property Names are C-Strings)*/
enum {
	kDTMaxPropertyNameLength=31     /* Max length of Property Name (terminator not included) */
};

typedef char DTPropertyNameBuf[32];


/* Entry Name Definitions (Entry Names are C-Strings)*/
enum {
	kDTMaxEntryNameLength           = 63    /* Max length of a C-String Entry Name (terminator not included) */
};

/* length of DTEntryNameBuf = kDTMaxEntryNameLength +1*/
typedef char DTEntryNameBuf[kDTMaxEntryNameLength + 1];

/*
 *  Structures for a Flattened Device Tree
 */

#define kPropNameLength 32

typedef struct DeviceTreeNodeProperty {
	char                name[kPropNameLength];// NUL terminated property name
	uint32_t            length;     // Length (bytes) of folloing prop value
//  unsigned long	value[1];	// Variable length value of property
	// Padded to a multiple of a longword?
} DeviceTreeNodeProperty;

typedef struct OpaqueDTEntry {
	uint32_t            nProperties;// Number of props[] elements (0 => end)
	uint32_t            nChildren;  // Number of children[] elements
//  DeviceTreeNodeProperty	props[];// array size == nProperties
//  DeviceTreeNode	children[];	// array size == nChildren
} DeviceTreeNode;

typedef const DeviceTreeNode *RealDTEntry;

typedef struct DTSavedScope {
	struct DTSavedScope * nextScope;
	RealDTEntry scope;
	RealDTEntry entry;
	unsigned long index;
} *DTSavedScopePtr;

/* Entry Iterator*/
typedef struct OpaqueDTEntryIterator {
	RealDTEntry outerScope;
	RealDTEntry currentScope;
	RealDTEntry currentEntry;
	DTSavedScopePtr savedScope;
	unsigned long currentIndex;
} OpaqueDTEntryIterator, *DTEntryIterator;

/* Property Iterator*/
typedef struct OpaqueDTPropertyIterator {
	RealDTEntry entry;
	DeviceTreeNodeProperty const *currentProperty;
	unsigned long currentIndex;
} OpaqueDTPropertyIterator, *DTPropertyIterator;

/* Entry*/
typedef const struct OpaqueDTEntry* DTEntry;

/* Entry Iterator*/
typedef struct OpaqueDTEntryIterator* DTEntryIterator;

/* Property Iterator*/
typedef struct OpaqueDTPropertyIterator* DTPropertyIterator;


/* status values*/
enum {
	kError = -1,
	kIterationDone = 0,
	kSuccess = 1
};


#ifndef __MWERKS__
/*
 *  -------------------------------------------------------------------------------
 *  Device Tree Calls
 *  -------------------------------------------------------------------------------
 */

/* Used to initalize the device tree functions. */
/* base is the base address of the flatened device tree */
extern void SecureDTInit(void const *base, size_t size);

/* Whether the device tree is locked down after machine lockdown. */
/* Returns false if there is no meaningful distinction, in */
/* contrast to SecureDTFindEntry. */
extern bool SecureDTIsLockedDown(void);

/*
 *  -------------------------------------------------------------------------------
 *  Entry Handling
 *  -------------------------------------------------------------------------------
 */
/* Compare two Entry's for equality. */
extern int SecureDTEntryIsEqual(const DTEntry ref1, const DTEntry ref2);

/*
 *  -------------------------------------------------------------------------------
 *  LookUp Entry by Name
 *  -------------------------------------------------------------------------------
 */
/*
 *  Find Entry
 *  Find the device tree entry that contains propName=propValue.
 *  It currently  searches the entire
 *  tree.  This function should eventually go in DeviceTree.c.
 *  This only works for string properties where `propValue` is null-terminated.
 *  Returns:    kSuccess = entry was found.  Entry is in entryH.
 *            kError   = entry was not found
 */
extern int SecureDTFindEntry(const char *propName, const char *propValue, DTEntry *entryH);

/**
 * @brief Finds the devicetree node that has the specified property equal to the
 * specified value.
 *
 * This function works with properties of any type; it just checks that the size
 * and bytes of the value are what the caller wants.
 *
 * @note This function also works with properties that don't have a value—just
 * specify NULL for `propertyValue` and 0 for `propertyValueSize`.
 *
 * @param[in] propertyName The name of the property.
 * @param[in] propertyValue A pointer to some bytes that make up the value.
 * @param[in] propertyValueSize The number of bytes that make up the value.
 * @param[out] devicetreeNode A pointer to the target devicetree node, if found.
 *
 * @return kSuccess if the node was found and kError otherwise.
 */
extern int SecureDTFindNodeWithPropertyEqualToValue(
	const char *const propertyName,
	const void *const propertyValue,
	const size_t propertyValueSize,
	const DeviceTreeNode **const devicetreeNode);

/**
 * @brief Finds the devicetree node with the specified phandle.
 *
 * This is a convenience wrapper around `SecureDTFindNodeWithPropertyEqualToValue()`.
 *
 * @param[in] phandle The phandle of interest.
 * @param[out] devicetreeNode A pointer to the target devicetree node, if found.
 *
 * @return kSuccess if the node was found and kError otherwise.
 */
extern int SecureDTFindNodeWithPhandle(
	const uint32_t phandle,
	const DeviceTreeNode **const devicetreeNode);

/**
 * @brief Finds the devicetree node with the specified string property.
 *
 * This is a convenience wrapper around `SecureDTFindNodeWithPropertyEqualToValue()`.
 *
 * @param[in] propertyName The name of the string property.
 * @param[in] propertyValue The value of the string property.
 * @param[out] devicetreeNode A pointer to the target devicetree node, if found.
 *
 * @return kSuccess if the node was found and kError otherwise.
 */
extern int SecureDTFindNodeWithStringProperty(
	const char *const propertyName,
	const char *const propertyValue,
	const DeviceTreeNode **const devicetreeNode);

/*
 *  Lookup Entry
 *  Locates an entry given a specified subroot (searchPoint) and path name.  If the
 *  searchPoint pointer is NULL, the path name is assumed to be an absolute path
 *  name rooted to the root of the device tree.
 *  Returns:    kSuccess = entry was found.  Entry is in foundEntry.
 *            kError   = entry was not found
 */
extern int SecureDTLookupEntry(const DTEntry searchPoint, const char *pathName, DTEntry *foundEntry);

/*
 *  -------------------------------------------------------------------------------
 *  Entry Iteration
 *  -------------------------------------------------------------------------------
 */
/*
 *  An Entry Iterator maintains three variables that are of interest to clients.
 *  First is an "OutermostScope" which defines the outer boundry of the iteration.
 *  This is defined by the starting entry and includes that entry plus all of it's
 *  embedded entries. Second is a "currentScope" which is the entry the iterator is
 *  currently in. And third is a "currentPosition" which is the last entry returned
 *  during an iteration.
 *
 *  Initialize Entry Iterator
 *  Fill out the iterator structure. The outermostScope and currentScope of the iterator
 *  are set to "startEntry".  If "startEntry" = NULL, the outermostScope and
 *  currentScope are set to the root entry.  The currentPosition for the iterator is
 *  set to "nil".
 */
extern int SecureDTInitEntryIterator(const DTEntry startEntry, DTEntryIterator iter);

/*
 *  Enter Child Entry
 *  Move an Entry Iterator into the scope of a specified child entry.  The
 *  currentScope of the iterator is set to the entry specified in "childEntry".  If
 *  "childEntry" is nil, the currentScope is set to the entry specified by the
 *  currentPosition of the iterator.
 */
extern int SecureDTEnterEntry(DTEntryIterator iterator, DTEntry childEntry);

/*
 *  Exit to Parent Entry
 *  Move an Entry Iterator out of the current entry back into the scope of it's parent
 *  entry. The currentPosition of the iterator is reset to the current entry (the
 *  previous currentScope), so the next iteration call will continue where it left off.
 *  This position is returned in parameter "currentPosition".
 */
extern int SecureDTExitEntry(DTEntryIterator iterator, DTEntry *currentPosition);

/*
 *  Iterate Entries
 *  Iterate and return entries contained within the entry defined by the current
 *  scope of the iterator.  Entries are returned one at a time. When
 *  int == kIterationDone, all entries have been exhausted, and the
 *  value of nextEntry will be Nil.
 */
extern int SecureDTIterateEntries(DTEntryIterator iterator, DTEntry *nextEntry);

/*
 *  Restart Entry Iteration
 *  Restart an iteration within the current scope.  The iterator is reset such that
 *  iteration of the contents of the currentScope entry can be restarted. The
 *  outermostScope and currentScope of the iterator are unchanged. The currentPosition
 *  for the iterator is set to "nil".
 */
extern int SecureDTRestartEntryIteration(DTEntryIterator iterator);

/*
 *  -------------------------------------------------------------------------------
 *  Get Property Values
 *  -------------------------------------------------------------------------------
 */
/*
 *  Get the value of the specified property for the specified entry.
 *
 *  Get Property
 */
extern int SecureDTGetProperty(const DTEntry entry, const char *propertyName,
    void const **propertyValue, unsigned int *propertySize);

extern int SecureDTGetPropertyRegion(const DTEntry entry, const char *propertyName,
    void const **propertyValue, unsigned int *propertySize,
    vm_offset_t const region_start, vm_size_t region_size);

/*
 *  -------------------------------------------------------------------------------
 *  Iterating Properties
 *  -------------------------------------------------------------------------------
 */
/*
 *  Initialize Property Iterator
 *  Fill out the property iterator structure. The target entry is defined by entry.
 */
extern int SecureDTInitPropertyIterator(const DTEntry entry, DTPropertyIterator iter);

/*
 *  Iterate Properites
 *  Iterate and return properties for given entry.
 *  When int == kIterationDone, all properties have been exhausted.
 */

extern int SecureDTIterateProperties(DTPropertyIterator iterator,
    char const **foundProperty);

/*
 *  Restart Property Iteration
 *  Used to re-iterate over a list of properties.  The Property Iterator is
 *  reset to the beginning of the list of properties for an entry.
 */

extern int SecureDTRestartPropertyIteration(DTPropertyIterator iterator);

/*
 *  -------------------------------------------------------------------------------
 *  Conventional Device Tree Types
 *  -------------------------------------------------------------------------------
 */

/*
 * Memory Ranges
 * Used in the chosen/memory-map node, populated by iBoot.
 */

typedef struct DTMemoryMapRange {
	vm_offset_t paddr;
	size_t length;
} DTMemoryMapRange;


#ifdef __cplusplus
}
#endif

#endif /* __MWERKS__ */

#endif /* __APPLE_API_PRIVATE */

#endif /* _PEXPERT_DEVICE_TREE_H_ */
