/*
 * Copyright (C) 2011-2012 Apple Inc. All rights reserved.
 *
 * This document is the property of Apple Inc.
 * It is considered confidential and proprietary.
 *
 * This document may not be reproduced or transmitted in any form,
 * in whole or in part, without the express written permission of
 * Apple Inc.
 */
#ifndef __CONSISTENT_DEBUG_HELPER_FNS__
#define __CONSISTENT_DEBUG_HELPER_FNS__

#include "consistent_debug_registry.h"

// C Helper functions that should serve as a pseudo-library
// for other codebases that use Consistent Debug


// Root Pointer encoder/decoder

/**
 * Encode 64-bit physical address of root pointer into a 
 * suitable 32-bit format. 
 * 
 * @param root_pointer 64-bit pointer to the physical address of 
 * the consistent debug registry 
 * @param pointer_type One of the types documented in "Debug 
 * Root Pointer Scratch Register Format" of 
 * consistent_debug_registry.h 
 * 
 * @return uint32_t 0: Cannot encode address with specified 
 * type, or invalid type. Otherwise, returns a 32-bit 
 * representation of the address. 
 */
static inline uint32_t consistent_debug_encode_root_pointer(uint64_t root_pointer, dbg_root_ptr_type_t pointer_type)
{
	// Only ADDR types are supported
	if (pointer_type > DBG_ROOT_PTR_TYPE_BOOT_PANIC_BUFFER_ADDR) {
		return 0;
	}

	if ((root_pointer & DBG_ROOT_PTR_ADDR_ALIGNMENT_MASK) != 0) {
		return 0;
	}

	if (root_pointer > DBG_ROOT_PTR_ADDR_MAX_MASK) {
		return 0;
	}

	return (uint32_t)((root_pointer >> DBG_ROOT_PTR_ADDR_ALIGMENT_SHIFT) | (pointer_type << DBG_ROOT_PTR_TYPE_SHIFT));
}

/**
 * opposite of consistent_debug_decode_root_pointer; decodes a root 
 * pointer encoded in that manner. 
 * 
 * @return uint64_t 0 if cannot be decoded, otherwise the 
 *         physical address.
 */
static inline uint64_t consistent_debug_decode_root_pointer(uint32_t encoded_value, dbg_root_ptr_type_t *pointer_type)
{
	uint32_t type = (encoded_value >> DBG_ROOT_PTR_TYPE_SHIFT) & DBG_ROOT_PTR_TYPE_MASK;
	if (type > DBG_ROOT_PTR_TYPE_BOOT_PANIC_BUFFER_ADDR) {
		return 0; // // Only ADDR types are supported
	}

	uint64_t ret = encoded_value & DBG_ROOT_PTR_ADDR_MASK;
	ret <<= DBG_ROOT_PTR_ADDR_ALIGMENT_SHIFT;
	*pointer_type = (dbg_root_ptr_type_t)type;
	return ret;
}


#endif // __CONSISTENT_DEBUG_HELPER_FNS__
