| /* | |
| * \file km_efuse_key.c | |
| * \brief efuse key ops for key manage | |
| * | |
| * \version 1.0.0 | |
| * \date 15/06/30 | |
| * \author Sam.Wu <yihui.wu@amlgic.com> | |
| * | |
| * Copyright (c) 2015 Amlogic. All Rights Reserved. | |
| * | |
| */ | |
| #include "key_manage_i.h" | |
| #include <asm/arch/secure_apb.h> | |
| #include <asm/io.h> | |
| #define SECURE_BOOT_KEY_NAME "secure_boot_set" | |
| extern int efuse_usr_api_init_dtb(const char* dt_addr); | |
| extern int efuse_usr_api_get_cfg_key_size(const char* keyname, unsigned* pSz); | |
| extern int efuse_usr_api_write_key(const char* keyname, const void* keydata, const unsigned dataSz); | |
| extern int efuse_usr_api_read_key(const char* keyname, void* databuf, const unsigned bufSz); | |
| int keymanage_efuse_init(const char *buf, int len) | |
| { | |
| char ver; | |
| int ret = 0; | |
| const char* dtbLoadAddr = getenv("dtb_mem_addr"); | |
| if (!dtbLoadAddr) { | |
| setenv("dtb_mem_addr", simple_itoa(CONFIG_SYS_SDRAM_BASE + (16U<<20))); | |
| } | |
| dtbLoadAddr = (char*)simple_strtoul(dtbLoadAddr, NULL, 0); | |
| ret = efuse_usr_api_init_dtb(dtbLoadAddr); | |
| if (ret) { | |
| KM_ERR("efuse init failed\n"); | |
| return __LINE__; | |
| } | |
| ver = unifykey_get_efuse_version(); | |
| if (ver == 0) { | |
| KM_DBG("efuse version not cfg\n"); | |
| return 0; | |
| } | |
| //TODO: program the efuse version | |
| return ret; | |
| } | |
| int keymange_efuse_exit(void) | |
| { | |
| return 0; | |
| } | |
| //must be hexdata if stored in efuse | |
| int keymanage_efuse_write(const char *keyname, const void* keydata, unsigned int datalen) | |
| { | |
| int ret = 0; | |
| if (!strcmp(SECURE_BOOT_KEY_NAME, keyname)) | |
| { | |
| char _cmdbuf[96]; | |
| sprintf(_cmdbuf, "efuse %s %p", keyname, keydata); | |
| ret = run_command(_cmdbuf, 0);; | |
| } | |
| else | |
| { | |
| ret = efuse_usr_api_write_key(keyname, keydata, datalen); | |
| } | |
| return ret; | |
| } | |
| ssize_t keymanage_efuse_size(const char* keyname) | |
| { | |
| int ret = 0; | |
| unsigned cfgSz = 0; | |
| ret = efuse_usr_api_get_cfg_key_size(keyname, &cfgSz); | |
| if (ret || !cfgSz) { | |
| KM_ERR("Fail at get cfg size for efuse key[%s]\n", keyname); | |
| return 0; | |
| } | |
| return cfgSz; | |
| } | |
| int keymanage_efuse_exist(const char* keyname) | |
| { | |
| if (!strcmp(SECURE_BOOT_KEY_NAME, keyname)) | |
| { | |
| const unsigned long cfg10 = readl(AO_SEC_SD_CFG10); | |
| KM_MSG("cfg10=0x%lX\n", cfg10); | |
| return ( cfg10 & (0x1<< 4) ); | |
| } | |
| else | |
| { | |
| int ret = 0; | |
| const ssize_t cfgSz = keymanage_efuse_size(keyname); | |
| char* databuf = NULL; | |
| int isEmpty = 1; | |
| int i = 0; | |
| databuf = (char*)malloc(cfgSz); | |
| if (!databuf) { | |
| KM_ERR("Fail to alloc bufsz 0x%x for key %s\n", (unsigned)cfgSz, keyname); | |
| return 0; | |
| } | |
| ret = keymanage_efuse_read(keyname, databuf, cfgSz); | |
| if (ret) { | |
| KM_ERR("Fail at read key[%s]\n", keyname); | |
| goto _exit; | |
| } | |
| for (i = 0; i < cfgSz && isEmpty; ++i) { | |
| isEmpty = !databuf[i]; | |
| } | |
| _exit: | |
| free(databuf); | |
| return !isEmpty; | |
| } | |
| return __LINE__; | |
| } | |
| int keymanage_efuse_query_can_read(const char* keyname) | |
| { | |
| if (!strcmp(SECURE_BOOT_KEY_NAME, keyname)) | |
| { | |
| return 0; | |
| } | |
| else | |
| { | |
| return 1;//user space always can be read | |
| } | |
| } | |
| //data format is hexdata | |
| int keymanage_efuse_read(const char *keyname, void* databuf, const unsigned bufSz) | |
| { | |
| int ret = 0; | |
| unsigned cfgSz = 0; | |
| cfgSz = keymanage_efuse_size(keyname); | |
| if (cfgSz > bufSz) { | |
| KM_ERR("buf sz 0x%x < dts cfg sz 0x%x\n", bufSz, cfgSz); | |
| return __LINE__; | |
| } | |
| ret = efuse_usr_api_read_key(keyname, databuf, cfgSz); | |
| return ret; | |
| } | |