Files
linux-legacy/drivers/mxc/security/scc2_internals.h
Anish Trivedi 414ad74dc6 ENGR00122290-2 MX5x Enable SCC2 and SAHARA drivers
SCC2 driver changes to set base address of registers and
scc ram based on resources

Signed-off-by: Anish Trivedi <anish@freescale.com>
2010-08-10 11:49:03 -05:00

520 lines
15 KiB
C

/*
* Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#ifndef SCC_INTERNALS_H
#define SCC_INTERNALS_H
/** @file scc2_internals.h
*
* @brief This is intended to be the file which contains most or all of the
* code or changes need to port the driver. It also includes other definitions
* needed by the driver.
*
* This header file should only ever be included by scc2_driver.c
*
* Compile-time flags minimally needed:
*
* @li Some sort of platform flag. Currently TAHITI and MXC are understood.
* @li Some start-of-SCC consideration, such as SCC_BASE_ADDR
*
* Some changes which could be made when porting this driver:
* #SCC_SPIN_COUNT
*
*/
#include <linux/version.h> /* Current version Linux kernel */
#include <linux/module.h> /* Basic support for loadable modules,
printk */
#include <linux/init.h> /* module_init, module_exit */
#include <linux/kernel.h> /* General kernel system calls */
#include <linux/sched.h> /* for interrupt.h */
#include <linux/spinlock.h>
#include <linux/io.h> /* ioremap() */
#include <linux/interrupt.h> /* IRQ / interrupt definitions */
#include <linux/mxc_scc2_driver.h>
#if defined(MXC)
#include <mach/iim.h>
#include <mach/mxc_scc.h>
/**
* This macro is used to determine whether the SCC is enabled/available
* on the platform. This macro may need to be ported.
*/
#define SCC_FUSE __raw_readl(IO_ADDRESS(IIM_BASE_ADDR + MXC_IIMHWV1))
#define SCC_ENABLED() ((SCC_FUSE & MXC_IIMHWV1_SCC_DISABLE) == 0)
#else /* neither TAHITI nor MXC */
#error Do not understand target architecture
#endif /* TAHITI */
/**
* Define the number of Stored Keys which the SCC driver will make available.
* Value shall be from 0 to 20. Default is zero (0).
*/
/*#define SCC_KEY_SLOTS 20*/
/* Temporarily define compile-time flags to make Doxygen happy. */
#ifdef DOXYGEN_HACK
/** @addtogroup scccompileflags */
/** @{ */
/** @def NO_SMN_INTERRUPT
* The SMN interrupt is not wired to the CPU at all.
*/
#define NO_SMN_INTERRUPT
/**
* Register an interrupt handler for the SMN as well as
* the SCM. In some implementations, the SMN is not connected at all (see
* #NO_SMN_INTERRUPT), and in others, it is on the same interrupt line as the
* SCM. When defining this flag, the SMN interrupt should be on a separate
* line from the SCM interrupt.
*/
#define USE_SMN_INTERRUPT
/**
* Turn on generation of run-time operational, debug, and error messages
*/
#define SCC_DEBUG
/**
* Turn on generation of run-time logging of access to the SCM and SMN
* registers.
*/
#define SCC_REGISTER_DEBUG
/**
* Turn on generation of run-time logging of access to the SCM Red and
* Black memories. Will only work if #SCC_REGISTER_DEBUG is also defined.
*/
#define SCC_RAM_DEBUG
/**
* If the driver finds the SCC in HEALTH_CHECK state, go ahead and
* run a quick ASC to bring it to SECURE state.
*/
#define SCC_BRINGUP
/**
* Expected to come from platform header files or compile command line.
* This symbol must be the address of the SCC
*/
#define SCC_BASE
/**
* This must be the interrupt line number of the SCM interrupt.
*/
#define INT_SCM
/**
* if #USE_SMN_INTERRUPT is defined, this must be the interrupt line number of
* the SMN interrupt.
*/
#define INT_SMN
/**
* Define the number of Stored Keys which the SCC driver will make available.
* Value shall be from 0 to 20. Default is zero (0).
*/
#define SCC_KEY_SLOTS
/**
* Make sure that this flag is defined if compiling for a Little-Endian
* platform. Linux Kernel builds provide this flag.
*/
#define __LITTLE_ENDIAN
/**
* Make sure that this flag is defined if compiling for a Big-Endian platform.
* Linux Kernel builds provide this flag.
*/
#define __BIG_ENDIAN
/**
* Read a 32-bit register value from a 'peripheral'. Standard Linux/Unix
* macro.
*
* @param offset Bus address of register to be read
*
* @return The value of the register
*/
#define readl(offset)
/**
* Write a 32-bit value to a register in a 'peripheral'. Standard Linux/Unix
* macro.
*
* @param value The 32-bit value to store
* @param offset Bus address of register to be written
*
* return (none)
*/
#define writel(value,offset)
/** @} */ /* end group scccompileflags */
#endif /* DOXYGEN_HACK */
#ifndef SCC_KEY_SLOTS
#define SCC_KEY_SLOTS 0
#else
#if (SCC_KEY_SLOTS < 0) || (SCC_KEY_SLOTS > 20)
#error Bad value for SCC_KEY_SLOTS
#endif
#endif
/**
* Maximum length of key/secret value which can be stored in SCC.
*/
#define SCC_MAX_KEY_SIZE 256
/**
* This is the size, in bytes, of each key slot, and therefore the maximum size
* of the wrapped key.
*/
#define SCC_KEY_SLOT_SIZE 32
/* These come for free with Linux, but may need to be set in a port. */
#ifndef __BIG_ENDIAN
#ifndef __LITTLE_ENDIAN
#error One of __LITTLE_ENDIAN or __BIG_ENDIAN must be #defined
#endif
#else
#ifdef __LITTLE_ENDIAN
#error Exactly one of __LITTLE_ENDIAN or __BIG_ENDIAN must be #defined
#endif
#endif
#ifndef SCC_CALLBACK_SIZE
/** The number of function pointers which can be stored in #scc_callbacks.
* Defaults to 4, can be overridden with compile-line argument.
*/
#define SCC_CALLBACK_SIZE 4
#endif
/** Initial CRC value for CCITT-CRC calculation. */
#define CRC_CCITT_START 0xFFFF
#ifdef TAHITI
/**
* The SCC_BASE has to be SMN_BASE_ADDR on TAHITI, as the banks of
* registers are swapped in place.
*/
#define SCC_BASE SMN_BASE_ADDR
/** The interrupt number for the SCC (SCM only!) on Tahiti */
#define INT_SCC_SCM 62
/** Tahiti does not have the SMN interrupt wired to the CPU. */
#define NO_SMN_INTERRUPT
#endif /* TAHITI */
/** Number of times to spin between polling of SCC while waiting for cipher
* or zeroizing function to complete. See also #SCC_CIPHER_MAX_POLL_COUNT. */
#define SCC_SPIN_COUNT 1000
/** Number of times to polling SCC while waiting for cipher
* or zeroizing function to complete. See also #SCC_SPIN_COUNT. */
#define SCC_CIPHER_MAX_POLL_COUNT 100
/**
* @def SCC_READ_REGISTER
* Read a 32-bit value from an SCC register. Macro which depends upon
* #scc_base. Linux readl()/writel() macros operate on 32-bit quantities, as
* do SCC register reads/writes.
*
* @param offset Register offset within SCC.
*
* @return The value from the SCC's register.
*/
#ifndef SCC_REGISTER_DEBUG
#define SCC_READ_REGISTER(offset) __raw_readl(scc_base+(offset))
#else
#define SCC_READ_REGISTER(offset) dbg_scc_read_register(offset)
#endif
/**
* Write a 32-bit value to an SCC register. Macro depends upon #scc_base.
* Linux readl()/writel() macros operate on 32-bit quantities, as do SCC
* register reads/writes.
*
* @param offset Register offset within SCC.
* @param value 32-bit value to store into the register
*
* @return (void)
*/
#ifndef SCC_REGISTER_DEBUG
#define SCC_WRITE_REGISTER(offset,value) \
(void)__raw_writel(value, scc_base+(offset))
#else
#define SCC_WRITE_REGISTER(offset,value) \
dbg_scc_write_register(offset, value)
#endif
/**
* Calculate the kernel virtual address of a partition from the partition number.
*/
#define SCM_PART_ADDRESS(part) \
(scm_ram_base + (part*scc_configuration.partition_size_bytes))
/**
* Calculate the partition number from the kernel virtual address.
*/
#define SCM_PART_NUMBER(address) \
((address - (uint32_t)scm_ram_base)/scc_configuration.partition_size_bytes)
/**
* Calculates the byte offset into a word
* @param bp The byte (char*) pointer
* @return The offset (0, 1, 2, or 3)
*/
#define SCC_BYTE_OFFSET(bp) ((uint32_t)(bp) % sizeof(uint32_t))
/**
* Converts (by rounding down) a byte pointer into a word pointer
* @param bp The byte (char*) pointer
* @return The word (uint32_t) as though it were an aligned (uint32_t*)
*/
#define SCC_WORD_PTR(bp) (((uint32_t)(bp)) & ~(sizeof(uint32_t)-1))
/**
* Determine number of bytes in an SCC block
*
* @return Bytes / block
*/
#define SCC_BLOCK_SIZE_BYTES() scc_configuration.block_size_bytes
/**
* Maximum number of additional bytes which may be added in CRC+padding mode.
*/
#define PADDING_BUFFER_MAX_BYTES (CRC_SIZE_BYTES + sizeof(scc_block_padding))
/**
* Shorthand (clearer, anyway) for number of bytes in a CRC.
*/
#define CRC_SIZE_BYTES (sizeof(crc_t))
/**
* The polynomial used in CCITT-CRC calculation
*/
#define CRC_POLYNOMIAL 0x1021
/**
* Calculate CRC on one byte of data
*
* @param[in,out] running_crc A value of type crc_t where CRC is kept. This
* must be an rvalue and an lvalue.
* @param[in] byte_value The byte (uint8_t, char) to be put in the CRC
*
* @return none
*/
#define CALC_CRC(byte_value,running_crc) { \
uint8_t data; \
data = (0xff&(byte_value)) ^ (running_crc >> 8); \
running_crc = scc_crc_lookup_table[data] ^ (running_crc << 8); \
}
/** Value of 'beginning of padding' marker in driver-provided padding */
#define SCC_DRIVER_PAD_CHAR 0x80
/** Name of the driver. Used (on Linux, anyway) when registering interrupts */
#define SCC_DRIVER_NAME "mxc_scc"
/* Port -- these symbols are defined in Linux 2.6 and later. They are defined
* here for backwards compatibility because this started life as a 2.4
* driver, and as a guide to portation to other platforms.
*/
#if !defined(LINUX_VERSION_CODE) || LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#define irqreturn_t void /* Return type of an interrupt handler */
#define IRQ_HANDLED /* Would be '1' for handled -- as in return IRQ_HANDLED; */
#define IRQ_NONE /* would be '0' for not handled -- as in return IRQ_NONE; */
#define IRQ_RETVAL(x) /* Return x==0 (not handled) or non-zero (handled) */
#endif /* LINUX earlier than 2.5 */
/* These are nice to have around */
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
/** Provide a typedef for the CRC which can be used in encrypt/decrypt */
typedef uint16_t crc_t;
/** Gives high-level view of state of the SCC */
enum scc_status {
SCC_STATUS_INITIAL, /**< State of driver before ever checking */
SCC_STATUS_CHECKING, /**< Transient state while driver loading */
SCC_STATUS_UNIMPLEMENTED, /**< SCC is non-existent or unuseable */
SCC_STATUS_OK, /**< SCC is in Secure or Default state */
SCC_STATUS_FAILED /**< In Failed state */
};
/**
* Information about a key slot.
*/
struct scc_key_slot
{
uint64_t owner_id; /**< Access control value. */
uint32_t length; /**< Length of value in slot. */
uint32_t offset; /**< Offset of value from start of RAM. */
uint32_t status; /**< 0 = unassigned, 1 = assigned. */
uint32_t part_ctl; /**< for the CCMD register */
};
/* Forward-declare a number routines which are not part of user api */
static int scc_init(void);
static void scc_cleanup(void);
static int __init scc_driver_init(void);
static void __exit scc_driver_exit(void);
/* Forward defines of internal functions */
OS_DEV_ISR(scc_irq);
/*static irqreturn_t scc_irq(int irq, void *dev_id);*/
/** Perform callbacks registered by #scc_monitor_security_failure().
*
* Make sure callbacks only happen once... Since there may be some reason why
* the interrupt isn't generated, this routine could be called from base(task)
* level.
*
* One at a time, go through #scc_callbacks[] and call any non-null pointers.
*/
static void scc_perform_callbacks(void);
/*static uint32_t copy_to_scc(const uint8_t* from, uint32_t to, unsigned long count_bytes, uint16_t* crc);
static uint32_t copy_from_scc(const uint32_t from, uint8_t* to,unsigned long count_bytes, uint16_t* crc);
static scc_return_t scc_strip_padding(uint8_t* from,unsigned* count_bytes_stripped);*/
static uint32_t scc_update_state(void);
static void scc_init_ccitt_crc(void);
static uint32_t scc_grab_config_values(void);
static int setup_interrupt_handling(void);
/**
* Perform an encryption on the input. If @c verify_crc is true, a CRC must be
* calculated on the plaintext, and appended, with padding, before computing
* the ciphertext.
*
* @param[in] count_in_bytes Count of bytes of plaintext
* @param[in] data_in Pointer to the plaintext
* @param[in] scm_control Bit values for the SCM_CONTROL register
* @param[in,out] data_out Pointer for storing ciphertext
* @param[in] add_crc Flag for computing CRC - 0 no, else yes
* @param[in,out] count_out_bytes Number of bytes available at @c data_out
*/
/*static scc_return_t scc_encrypt(uint32_t count_in_bytes, uint8_t* data_in, uint32_t scm_control, uint8_t* data_out,int add_crc, unsigned long* count_out_bytes);*/
/**
* Perform a decryption on the input. If @c verify_crc is true, the last block
* (maybe the two last blocks) is special - it should contain a CRC and
* padding. These must be stripped and verified.
*
* @param[in] count_in_bytes Count of bytes of ciphertext
* @param[in] data_in Pointer to the ciphertext
* @param[in] scm_control Bit values for the SCM_CONTROL register
* @param[in,out] data_out Pointer for storing plaintext
* @param[in] verify_crc Flag for running CRC - 0 no, else yes
* @param[in,out] count_out_bytes Number of bytes available at @c data_out
*/
/*static scc_return_t scc_decrypt(uint32_t count_in_bytes, uint8_t* data_in, uint32_t scm_control, uint8_t* data_out, int verify_crc, unsigned long* count_out_bytes);*/
static uint32_t host_owns_partition(uint32_t part_no);
static uint32_t partition_engaged(uint32_t part_no);
static scc_return_t scc_wait_completion(uint32_t* scm_status);
static int is_cipher_done(uint32_t* scm_status);
static scc_return_t check_register_accessible (uint32_t offset,
uint32_t smn_status,
uint32_t scm_status);
static scc_return_t check_register_offset(uint32_t offset);
/*uint8_t make_vpu_partition(void);*/
#ifdef SCC_REGISTER_DEBUG
static uint32_t dbg_scc_read_register(uint32_t offset);
static void dbg_scc_write_register(uint32_t offset, uint32_t value);
#endif
/* For Linux kernel, export the API functions to other kernel modules */
EXPORT_SYMBOL(scc_get_configuration);
EXPORT_SYMBOL(scc_zeroize_memories);
/*EXPORT_SYMBOL(scc_crypt);*/
EXPORT_SYMBOL(scc_set_sw_alarm);
EXPORT_SYMBOL(scc_monitor_security_failure);
EXPORT_SYMBOL(scc_stop_monitoring_security_failure);
EXPORT_SYMBOL(scc_read_register);
EXPORT_SYMBOL(scc_write_register);
EXPORT_SYMBOL(scc_allocate_partition);
EXPORT_SYMBOL(scc_engage_partition);
EXPORT_SYMBOL(scc_release_partition);
EXPORT_SYMBOL(scc_diminish_permissions);
EXPORT_SYMBOL(scc_encrypt_region);
EXPORT_SYMBOL(scc_decrypt_region);
/*EXPORT_SYMBOL(make_vpu_partition);*/
/* Tell Linux this is not GPL code */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Freescale Semiconductor, Inc.");
MODULE_DESCRIPTION("Device Driver for SCC (SMN/SCM)");
#endif /* SCC_INTERNALS_H */