/* * Copyright (C) 2016 Samsung Electronics Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #ifndef _EXYNOS_FMP_H_ #define _EXYNOS_FMP_H_ #include #include #define FMP_KEY_SIZE_16 16 #define FMP_KEY_SIZE_32 32 #define FMP_IV_SIZE_16 16 #define FMP_CBC_MAX_KEY_SIZE FMP_KEY_SIZE_16 #define FMP_XTS_MAX_KEY_SIZE ((FMP_KEY_SIZE_32) * (2)) #define FMP_MAX_KEY_SIZE FMP_XTS_MAX_KEY_SIZE #define FMP_HOST_TYPE_NAME_LEN 8 #define FMP_BLOCK_TYPE_NAME_LEN 8 #define FMP_SECTOR_SIZE 0x1000 #define FMP_MIN_SECTOR_SIZE 0x200 #define NUM_SECTOR_UNIT ((FMP_SECTOR_SIZE)/(FMP_MIN_SECTOR_SIZE)) #define MAX_AES_XTS_TRANSFER_SIZE 0x1000 #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #if defined(CONFIG_MMC_DW_EXYNOS_FMP) #define TRANS_DESC_LEN_MULTIPLIER 4 #else #define TRANS_DESC_LEN_MULTIPLIER 1 #endif enum fmp_id { FMP_EMBEDDED = 0, FMP_UFSCARD = 1, FMP_SDCARD = 2, }; enum fmp_crypto_algo_mode { EXYNOS_FMP_BYPASS_MODE = 0, EXYNOS_FMP_ALGO_MODE_AES_CBC = 1, EXYNOS_FMP_ALGO_MODE_AES_XTS = 2, }; enum fmp_crypto_key_size { EXYNOS_FMP_KEY_SIZE_16 = 16, EXYNOS_FMP_KEY_SIZE_32 = 32, }; enum fmp_crypto_enc_mode { EXYNOS_FMP_DISK_ENC = 1, EXYNOS_FMP_FILE_ENC = 2, }; enum fmp_disk_key_status { KEY_STORED = 0, KEY_SET = 1, KEY_CLEAR = 2, KEY_ERROR = -1, }; struct fmp_crypto_setting { enum fmp_crypto_algo_mode algo_mode; enum fmp_crypto_enc_mode enc_mode; enum fmp_crypto_key_size key_size; uint32_t index; sector_t sector; unsigned char key[FMP_MAX_KEY_SIZE]; uint8_t iv[FMP_IV_SIZE_16]; }; struct fmp_table_setting { __le32 des0; #define GET_CMDQ_LENGTH(d) \ (((d)->des0 & 0xffff0000) >> 16) __le32 des1; __le32 des2; /* Legacy Operation */ #define FKL BIT(26) #define DKL BIT(27) #define SET_FAS(d, v) \ ((d)->des2 = ((d)->des2 & 0xcfffffff) | v << 28) #define SET_DAS(d, v) \ ((d)->des2 = ((d)->des2 & 0x3fffffff) | v << 30) #define GET_FAS(d) ((d)->des2 & 0x30000000) #define GET_DAS(d) ((d)->des2 & 0xc0000000) #define GET_LENGTH(d) \ ((d)->des2 & 0x3ffffff) __le32 des3; /* CMDQ Operation */ #define FKL_CMDQ BIT(0) #define DKL_CMDQ BIT(1) #define SET_CMDQ_FAS(d, v) \ ((d)->des3 = ((d)->des3 & 0xfffffff3) | v << 2) #define SET_CMDQ_DAS(d, v) \ ((d)->des3 = ((d)->des3 & 0xffffffcf) | v << 4) #define GET_CMDQ_FAS(d) ((d)->des3 & 0x0000000c) #define GET_CMDQ_DAS(d) ((d)->des3 & 0x00000030) __le32 des4; __le32 des5; __le32 des6; __le32 des7; __le32 file_iv0; __le32 file_iv1; __le32 file_iv2; __le32 file_iv3; __le32 file_enckey0; __le32 file_enckey1; __le32 file_enckey2; __le32 file_enckey3; __le32 file_enckey4; __le32 file_enckey5; __le32 file_enckey6; __le32 file_enckey7; __le32 file_twkey0; __le32 file_twkey1; __le32 file_twkey2; __le32 file_twkey3; __le32 file_twkey4; __le32 file_twkey5; __le32 file_twkey6; __le32 file_twkey7; __le32 disk_iv0; __le32 disk_iv1; __le32 disk_iv2; __le32 disk_iv3; }; struct fmp_data_setting { struct fmp_crypto_setting disk; struct fmp_crypto_setting file; struct fmp_table_setting *table; struct address_space *mapping; bool cmdq_enabled; }; struct exynos_fmp_variant_ops { const char *name; int (*config)(struct platform_device *, struct fmp_data_setting *); int (*set_disk_key)(struct platform_device *, struct fmp_data_setting *); int (*clear_disk_key)(struct platform_device *); int (*clear)(struct platform_device *, struct fmp_data_setting *); }; struct fmp_fips_data { char block_type[FMP_BLOCK_TYPE_NAME_LEN]; struct block_device *bdev; sector_t sector; dev_t devt; struct fmp_crypto_setting *crypto; uint32_t test_block_offset; }; struct exynos_fmp { struct list_head list; int id; int command; struct device *dev; char host_type[FMP_HOST_TYPE_NAME_LEN]; struct miscdevice miscdev; struct fmp_fips_data *fips_data; struct platform_device *host_pdev; int test_mode; struct buffer_head *test_bh; bool fips_result; int status_disk_key; }; struct exynos_fmp_variant_ops *exynos_fmp_get_variant_ops(struct device_node *node); struct platform_device *exynos_fmp_get_pdevice(struct device_node *node); #endif