Files
test/drivers/source/crypto/sdrv_crypto_init.c
2025-11-07 20:19:23 +08:00

734 lines
19 KiB
C

/**
* @file sdrv_crypto_init.c
* @brief Semidrive CRYPTO init source file.
*
* @copyright Copyright (c) 2021 Semidrive Semiconductor.
* All rights reserved.
*/
#include <sdrv_crypto_init.h>
#include <sdrv_crypto_mailbox_soc_seip_reg.h>
#include <sdrv_crypto_utility.h>
#include <regs_base.h>
#include <reg.h>
#include <scr_hw.h>
#include <sdrv_scr.h>
#include <sdrv_rstgen.h>
#include <reset_ip.h>
#include <part.h>
#include <udelay/udelay.h>
#define EFUSEC_EHSM_CFG_OFFSET 0x1300
#define EFUSEC_SEIP_SECSTORAGE_SEL_OFFSET 0x12c9
#define RSTGEN_POLLs 0x10000
#define INIT_EFUSE_FOR_TEST 0
uint32_t sdrv_crypto_type = 0;
void init_efuse_for_test(void)
{
unsigned int data;
/*Step1 wati efuse init done (not busy)*/
printf("[seip test] Polling for efusec busy released\n");
/*bit[10] busy*/
data = readl(APB_EFUSEC_BASE + 0x0);
if ((data & (1 << 10)) == 0) {
printf("efusec is ready\n");
} else {
printf("[seip test] Efusec still busy, check delay time or efusec "
"behavior\n");
return;
}
/*Step2 write otp*/
printf("[seip test] Initializing OTP...\n");
/*Self_Ctrl_For_Boot*/
/*seip_control field, seip_mode_sel = 10 CACC mode 00 MAILBOX mode
* 0x3F000000*/
#if CONFIG_OSR_CRYPTO_TEST_CACC
writel(0x3F020000, APB_EFUSEC_BASE + 0x1300);
printf("[seip test] CACC MODE SELECT...\n");
#else
writel(0x00000000, APB_EFUSEC_BASE + 0x1300);
printf("[seip test] MIALBOX MODE SELECT...\n");
#endif
/*life cycle mode*/
writel(0x57C1EC96, APB_EFUSEC_BASE + 0x1304);
/*analog timming 1*/
writel(0x00000000, APB_EFUSEC_BASE + 0x1308);
writel(0x00000000, APB_EFUSEC_BASE + 0x130C);
/*secure flag*/
writel(0xFFFFFFFF, APB_EFUSEC_BASE + 0x1310);
/*PKD Public Key Digest 8x32*/
writel(0x5C4CE1B2, APB_EFUSEC_BASE + 0x1080);
writel(0x5BDFC679, APB_EFUSEC_BASE + 0x1084);
writel(0x7EFEF485, APB_EFUSEC_BASE + 0x1088);
writel(0x267ADBD8, APB_EFUSEC_BASE + 0x108c);
writel(0xE0A79D2B, APB_EFUSEC_BASE + 0x1090);
writel(0xA90ECB7C, APB_EFUSEC_BASE + 0x1094);
writel(0x8C7B74F4, APB_EFUSEC_BASE + 0x1098);
writel(0xF3A4A8CD, APB_EFUSEC_BASE + 0x109c);
/*SSK CTRL0 CTRL1*/
writel(0x20009100, APB_EFUSEC_BASE + 0x1318);
writel(0x81910000, APB_EFUSEC_BASE + 0x131C);
/*analog timming 2*/
writel(0x00000000, APB_EFUSEC_BASE + 0x1314);
/*FSRK*/
writel(0x01cca048, APB_EFUSEC_BASE + 0x10c0);
writel(0x13e16fc6, APB_EFUSEC_BASE + 0x10c4);
writel(0x468c8fc3, APB_EFUSEC_BASE + 0x10c8);
writel(0x9b33e294, APB_EFUSEC_BASE + 0x10cc);
/*Debug Passphrase(DPK)*/
writel(0x555a8f01, APB_EFUSEC_BASE + 0x10E0);
writel(0x97445894, APB_EFUSEC_BASE + 0x10E4);
writel(0xe4f7ffc0, APB_EFUSEC_BASE + 0x10E8);
writel(0xfc163902, APB_EFUSEC_BASE + 0x10EC);
writel(0x69bffe04, APB_EFUSEC_BASE + 0x10F0);
writel(0x6afaab9f, APB_EFUSEC_BASE + 0x10F4);
writel(0xb2909223, APB_EFUSEC_BASE + 0x10F8);
writel(0x605c925b, APB_EFUSEC_BASE + 0x10FC);
/*SSRK*/
writel(0x6f5a1159, APB_EFUSEC_BASE + 0x10d0);
writel(0xc4c128be, APB_EFUSEC_BASE + 0x10d4);
writel(0x51d3ab6d, APB_EFUSEC_BASE + 0x10d8);
writel(0x79dfe324, APB_EFUSEC_BASE + 0x10dc);
/*Firmware Update Key(fuk)*/
writel(0xe526a831, APB_EFUSEC_BASE + 0x1100);
writel(0x91d949bb, APB_EFUSEC_BASE + 0x1104);
writel(0xe981ea4b, APB_EFUSEC_BASE + 0x1108);
writel(0x482b906c, APB_EFUSEC_BASE + 0x110c);
writel(0x51422e72, APB_EFUSEC_BASE + 0x1110);
writel(0x84e87752, APB_EFUSEC_BASE + 0x1114);
writel(0x38da4eec, APB_EFUSEC_BASE + 0x1118);
writel(0x588dfa57, APB_EFUSEC_BASE + 0x111c);
/*Flash Decryption Key(fdk)*/
writel(0x045ade7e, APB_EFUSEC_BASE + 0x1120);
writel(0xc994f43a, APB_EFUSEC_BASE + 0x1124);
writel(0xefaeeaea, APB_EFUSEC_BASE + 0x1128);
writel(0xb0a913c3, APB_EFUSEC_BASE + 0x112c);
writel(0x51422e72, APB_EFUSEC_BASE + 0x1130);
writel(0x84e87752, APB_EFUSEC_BASE + 0x1134);
writel(0x38da4eec, APB_EFUSEC_BASE + 0x1138);
writel(0x588dfa57, APB_EFUSEC_BASE + 0x113c);
/*SSK2 (GP_KEY0)*/
writel(0xb7125e26, APB_EFUSEC_BASE + 0x1140);
writel(0xdc6dea26, APB_EFUSEC_BASE + 0x1144);
writel(0x67aadb08, APB_EFUSEC_BASE + 0x1148);
writel(0x7f5d3ac6, APB_EFUSEC_BASE + 0x114c);
writel(0x84b3ba9b, APB_EFUSEC_BASE + 0x1150);
writel(0x9407ff29, APB_EFUSEC_BASE + 0x1154);
writel(0x9bc6c26d, APB_EFUSEC_BASE + 0x1158);
writel(0x93da36b5, APB_EFUSEC_BASE + 0x115c);
/*SSK3 (GD_KEY1)*/
writel(0xc2c6cf73, APB_EFUSEC_BASE + 0x1160);
writel(0x3a6a7aee, APB_EFUSEC_BASE + 0x1164);
writel(0x6419d405, APB_EFUSEC_BASE + 0x1168);
writel(0x098bea55, APB_EFUSEC_BASE + 0x116c);
writel(0x51422e72, APB_EFUSEC_BASE + 0x1170);
writel(0x84e87752, APB_EFUSEC_BASE + 0x1174);
writel(0x38da4eec, APB_EFUSEC_BASE + 0x1178);
writel(0x588dfa57, APB_EFUSEC_BASE + 0x117c);
/*SSK4 (GD_KEY2)*/
writel(0x512fdc13, APB_EFUSEC_BASE + 0x1180);
writel(0x5f9dd394, APB_EFUSEC_BASE + 0x1184);
writel(0xcd43a99b, APB_EFUSEC_BASE + 0x1188);
writel(0x3364117f, APB_EFUSEC_BASE + 0x118c);
writel(0x7f3b7c37, APB_EFUSEC_BASE + 0x1190);
writel(0x2f59b8c8, APB_EFUSEC_BASE + 0x1194);
writel(0xa5487ae8, APB_EFUSEC_BASE + 0x1198);
writel(0x1b9cc114, APB_EFUSEC_BASE + 0x119c);
/*CRC (KCRC)*/
writel(0xD274ED53, APB_EFUSEC_BASE + 0x12a0);
writel(0x7C1985E9, APB_EFUSEC_BASE + 0x12a4);
writel(0xDF4C8867, APB_EFUSEC_BASE + 0x12a8);
writel(0xB05F2E42, APB_EFUSEC_BASE + 0x12ac);
writel(0x8F6AF678, APB_EFUSEC_BASE + 0x12b0);
writel(0x179935B0, APB_EFUSEC_BASE + 0x12b4);
writel(0x17797D10, APB_EFUSEC_BASE + 0x12b8);
writel(0x4EE0CBE3, APB_EFUSEC_BASE + 0x12bc);
writeb(0x01, APB_EFUSEC_BASE + 0x12c9);
printf("[seip test] init_efuse_shadow_register_default completed\n");
}
/*write i_kbuf_ctrl*/
void write_kbuf_ctrl(unsigned int data)
{
int reg = 0;
int rdata = 0;
rdata = readl(APB_EFUSEC_BASE + 0x12C8);
reg = (rdata & 0xFFFF) | (data << 16);
writel(reg, APB_EFUSEC_BASE + 0x12C8);
}
/*write keys with default algorithm*/
void check_efuse_shadow_register_for_test(void)
{
int rdata;
printf("AHB Reading and Checking Key..........\n");
/*read key through AHB*/
/*FSRT READY KEY*/
write_kbuf_ctrl(0xe78a);
/*sys_tb_ctrl_delay_us_for_sim_only(2);*/
rdata = readl(0x021de800);
if (rdata != 0x107119e7) {
printf("FISRT KEY ERROR! 1rdata =0x%x\n", rdata);
}
rdata = readl(0x021de804);
if (rdata != 0x5fe88b1e) {
printf("FISRT KEY ERROR! 2rdata =0x%x\n", rdata);
}
rdata = readl(0x021de808);
if (rdata != 0x8922e4ae) {
printf("FISRT KEY ERROR! 3rdata =0x%x\n", rdata);
}
rdata = readl(0x021de80c);
if (rdata != 0xceae16cf) {
printf("FISRT KEY ERROR! 4rdata =0x%x\n", rdata);
}
rdata = readl(0x021de810);
if (rdata != 0x00000000) {
printf("FISRT KEY ERROR! 5rdata =0x%x\n", rdata);
}
rdata = readl(0x021de814);
if (rdata != 0x00000000) {
printf("FISRT KEY ERROR! 6rdata =0x%x\n", rdata);
}
rdata = readl(0x021de818);
if (rdata != 0x00000000) {
printf("FISRT KEY ERROR! 7rdata =0x%x\n", rdata);
}
rdata = readl(0x021de81c);
if (rdata != 0x00000000) {
printf("FISRT KEY ERROR! 8rdata =0x%x\n", rdata);
}
/*DEBUG PASSPHRASE KEY*/
write_kbuf_ctrl(0x5d4);
rdata = readl(0x021de820);
if (rdata != 0x0ee9f560) {
printf("DEBUG PASSPHRASE ERROR!1rdata =0x%x\n", rdata);
}
rdata = readl(0x021de824);
if (rdata != 0x9a22ecba) {
printf("DEBUG PASSPHRASE ERROR!2rdata =0x%x\n", rdata);
}
rdata = readl(0x021de828);
if (rdata != 0xa3a43744) {
printf("DEBUG PASSPHRASE ERROR!3rdata =0x%x\n", rdata);
}
rdata = readl(0x021de82c);
if (rdata != 0x8a9d9b8d) {
printf("DEBUG PASSPHRASE ERROR!4rdata =0x%x\n", rdata);
}
rdata = readl(0x021de830);
if (rdata != 0x00000000) {
printf("DEBUG PASSPHRASE ERROR!5rdata =0x%x\n", rdata);
}
rdata = readl(0x021de834);
if (rdata != 0x00000000) {
printf("DEBUG PASSPHRASE ERROR!6rdata =0x%x\n", rdata);
}
rdata = readl(0x021de838);
if (rdata != 0x00000000) {
printf("DEBUG PASSPHRASE ERROR!7rdata =0x%x\n", rdata);
}
rdata = readl(0x021de83c);
if (rdata != 0x00000000) {
printf("DEBUG PASSPHRASE ERROR!8rdata =0x%x\n", rdata);
}
/*SSRK*/
write_kbuf_ctrl(0x2355);
rdata = readl(0x021de840);
if (rdata != 0xf30e2676) {
printf("SECOND KEY ERROR!1rdata =0x%x\n", rdata);
}
rdata = readl(0x021de844);
if (rdata != 0xeac1222c) {
printf("SECOND KEY ERROR!2rdata =0x%x\n", rdata);
}
rdata = readl(0x021de848);
if (rdata != 0x02e596c5) {
printf("SECOND KEY ERROR!3rdata =0x%x\n", rdata);
}
rdata = readl(0x021de84c);
if (rdata != 0x79a8eb9f) {
printf("SECOND KEY ERROR!4rdata =0x%x\n", rdata);
}
rdata = readl(0x021de850);
if (rdata != 0x00000000) {
printf("SECOND KEY ERROR!5rdata =0x%x\n", rdata);
}
rdata = readl(0x021de854);
if (rdata != 0x00000000) {
printf("SECOND KEY ERROR!6rdata =0x%x\n", rdata);
}
rdata = readl(0x021de858);
if (rdata != 0x00000000) {
printf("SECOND KEY ERROR!7rdata =0x%x\n", rdata);
}
rdata = readl(0x021de85c);
if (rdata != 0x00000000) {
printf("SECOND KEY ERROR!8rdata =0x%x\n", rdata);
}
/*FIRMWARE UPDATE KEY*/
write_kbuf_ctrl(0xa55a);
rdata = readl(0x021de860);
if (rdata != 0x45a4079f) {
printf("FIREMWARE UPDATE KEY ERROR!1rdata =0x%x\n", rdata);
}
rdata = readl(0x021de864);
if (rdata != 0x92fcde09) {
printf("FIREMWARE UPDATE KEY ERROR!2rdata =0x%x\n", rdata);
}
rdata = readl(0x021de868);
if (rdata != 0x2a553d1f) {
printf("FIREMWARE UPDATE KEY ERROR!3rdata =0x%x\n", rdata);
}
rdata = readl(0x021de86c);
if (rdata != 0x8e06c0cb) {
printf("FIREMWARE UPDATE KEY ERROR!4rdata =0x%x\n", rdata);
}
rdata = readl(0x021de870);
if (rdata != 0x00000000) {
printf("FIREMWARE UPDATE KEY ERROR!5rdata =0x%x\n", rdata);
}
rdata = readl(0x021de874);
if (rdata != 0x00000000) {
printf("FIREMWARE UPDATE KEY ERROR!6rdata =0x%x\n", rdata);
}
rdata = readl(0x021de878);
if (rdata != 0x00000000) {
printf("FIREMWARE UPDATE KEY ERROR!7rdata =0x%x\n", rdata);
}
rdata = readl(0x021de87c);
if (rdata != 0x00000000) {
printf("FIREMWARE UPDATE KEY ERROR!8rdata =0x%x\n", rdata);
}
/*FLASH DECRYPTION KEY*/
write_kbuf_ctrl(0x2ca1);
rdata = readl(0x021de880);
if (rdata != 0x104bab38) {
printf("FLASH DECRYPTION KEY ERROR!1rdata =0x%x\n", rdata);
}
rdata = readl(0x021de884);
if (rdata != 0xebe73c79) {
printf("FLASH DECRYPTION KEY ERROR!2rdata =0x%x\n", rdata);
}
rdata = readl(0x021de888);
if (rdata != 0x1cb5491c) {
printf("FLASH DECRYPTION KEY ERROR!3rdata =0x%x\n", rdata);
}
rdata = readl(0x021de88c);
if (rdata != 0x52e8dc31) {
printf("FLASH DECRYPTION KEY ERROR!4rdata =0x%x\n", rdata);
}
rdata = readl(0x021de890);
if (rdata != 0x00000000) {
printf("FLASH DECRYPTION KEY ERROR!5rdata =0x%x\n", rdata);
}
rdata = readl(0x021de894);
if (rdata != 0x00000000) {
printf("FLASH DECRYPTION KEY ERROR!6rdata =0x%x\n", rdata);
}
rdata = readl(0x021de898);
if (rdata != 0x00000000) {
printf("FLASH DECRYPTION KEY ERROR!7rdata =0x%x\n", rdata);
}
rdata = readl(0x021de89c);
if (rdata != 0x00000000) {
printf("FLASH DECRYPTION KEY ERROR!8rdata =0x%x\n", rdata);
}
/*SSK2*/
write_kbuf_ctrl(0xcb5b);
rdata = readl(0x021de8a0);
if (rdata != 0x8d7972b0) {
printf("SSK2 ERROR!1rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8a4);
if (rdata != 0xcccb6db2) {
printf("SSK2 ERROR!2rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8a8);
if (rdata != 0x36948442) {
printf("SSK2 ERROR!3rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8ac);
if (rdata != 0xc4f5b5f0) {
printf("SSK2 ERROR!4rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8b0);
if (rdata != 0x697770aa) {
printf("SSK2 ERROR!5rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8b4);
if (rdata != 0x08a35e00) {
printf("SSK2 ERROR!6rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8b8);
if (rdata != 0xbc9c08b3) {
printf("SSK2 ERROR!7rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8bc);
if (rdata != 0x362d70f8) {
printf("SSK2 ERROR!8rdata =0x%x\n", rdata);
}
/*SSK3*/
write_kbuf_ctrl(0x38d1);
rdata = readl(0x021de8c0);
if (rdata != 0x95d63843) {
printf("SSK3 ERROR!1rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8c4);
if (rdata != 0xc1698e12) {
printf("SSK3 ERROR!2rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8c8);
if (rdata != 0x5d6dec1b) {
printf("SSK3 ERROR!3rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8cc);
if (rdata != 0x1cf9cfe3) {
printf("SSK3 ERROR!4rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8d0);
if (rdata != 0x00000000) {
printf("SSK3 ERROR!5rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8d4);
if (rdata != 0x00000000) {
printf("SSK3 ERROR!6rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8d8);
if (rdata != 0x00000000) {
printf("SSK3 ERROR!7rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8dc);
if (rdata != 0x00000000) {
printf("SSK3 ERROR!8rdata =0x%x\n", rdata);
}
/*SSK4*/
write_kbuf_ctrl(0x7841);
rdata = readl(0x021de8e0);
if (rdata != 0x3cacc647) {
printf("SSK4 ERROR!1rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8e4);
if (rdata != 0xec7f7074) {
printf("SSK4 ERROR!2rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8e8);
if (rdata != 0xfa2d7f2f) {
printf("SSK4 ERROR!3rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8ec);
if (rdata != 0x55b12764) {
printf("SSK4 ERROR!4rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8f0);
if (rdata != 0x51c6c3f2) {
printf("SSK4 ERROR!5rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8f4);
if (rdata != 0x7e542a12) {
printf("SSK4 ERROR!6rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8f8);
if (rdata != 0x922d9146) {
printf("SSK4 ERROR!7rdata =0x%x\n", rdata);
}
rdata = readl(0x021de8fc);
if (rdata != 0x55711916) {
printf("SSK4 ERROR!8rdata =0x%x\n", rdata);
}
rdata = readl(0x021def00);
printf("SSK_CTRL0 rdata =0x%x\n", rdata);
rdata = readl(0x021def04);
printf("SSK_CTRL1 rdata =0x%x\n", rdata);
printf("[seip test] KEY CHECK DONE!\n");
}
void sdrv_crypto_set_type(uint32_t crypto_type)
{
sdrv_crypto_type = crypto_type;
}
/**
* @brief Get the type of CRYPTO type.
*
* This function return crypto type
*
* @return The result of CRYPTO type.
*/
uint32_t sdrv_crypto_get_type(void) { return sdrv_crypto_type; }
static void set_sec_storage(void)
{
uint32_t rdata = 0;
#ifdef CONFIG_E3L
scr_signal_t signal = SCR_SF_SEIP_KEY_SEC_STORAGE_SCR_1_0;
#else
scr_signal_t signal = SCR_AP_SEIP_KEY_SEC_STORAGE_SCR_1_0;
#endif
sdrv_scr_t g_scr_ctrl = {
#ifdef CONFIG_E3L
.base = APB_SCR_SF_BASE,
#else
.base = APB_SCR_AP_BASE,
#endif
};
/* before reset seip, must set fuse and scr config */
/* if fuse config ssk4 from sec storage, set */
rdata = readb(APB_EFUSEC_BASE + EFUSEC_SEIP_SECSTORAGE_SEL_OFFSET);
if ((rdata & 0x1) == 0) {
scr_set(&g_scr_ctrl, &signal, 2);
}
}
static uint32_t hsm_init(void)
{
Crypto_HsmInitReturnType ret = CRYPTO_HSM_INIT_OK;
uint32_t rdata = 0;
uint32_t rdata_lifecycle = 0;
uint32_t tms = 0;
#if INIT_EFUSE_FOR_TEST
init_efuse_for_test();
#endif
/* add return value */
rdata = readl(APB_EFUSEC_BASE+ EFUSEC_EHSM_CFG_OFFSET);
rdata |= 0x80000000;
writel(rdata, APB_EFUSEC_BASE+ EFUSEC_EHSM_CFG_OFFSET);
set_sec_storage();
sdrv_rstgen_reset(&rstsig_seip);
udelay(10);
/*polling status seip boot_done*/
tms = 0;
do {
rdata = readl(APB_SEIP_BASE + 0x14);
if (tms >= RSTGEN_POLLs) {
return CRYPTO_HSM_INIT_BOOT_TIMEOUT;
}
} while ((rdata & 0x100) == 0 && (tms++ < RSTGEN_POLLs));
/* if fuse config offset 16, seip_mode_sel = 10 CACC mode, 00 MAILBOX mode */
rdata = readl(APB_EFUSEC_BASE + EFUSEC_EHSM_CFG_OFFSET);
/*get hsm life cycle value*/
rdata_lifecycle = readl(APB_EFUSEC_BASE + 0x1304);
/* wait for seip ready for mailbox */
if ((rdata & 0x30000) == 0x0) {
if(rdata_lifecycle == 0x0){
/*test mode not rsp value*/
}else{
while (rSOCMBOX_RSP_D0 == 0x0) {
}
rSOCMBOX_INT_STA = 0x02;
if (rSOCMBOX_RSP_D0 == SEIP_FW_VER_SUCCESS) {
} else {
ret = CRYPTO_HSM_INIT_BOOT_FAIL;
}
}
sdrv_crypto_set_type(SDRV_CRYPTO_TYPE_MAILBOX);
} else {
sdrv_crypto_set_type(SDRV_CRYPTO_TYPE_CACC);
}
return ret;
}
/**
* @brief Sdrv CRYPTO initialization.
*
* This function init hsm
*
* @return E_OK or error code.
*/
sdrv_crypto_error_status_e sdrv_crypto_init(void)
{
uint32_t hsm_init_sta = 0;
sdrv_crypto_error_status_e ret;
uint8_t count;
count = RETRY_COUNT;
do {
hsm_init_sta = hsm_init();
if (hsm_init_sta == CRYPTO_HSM_INIT_OK) {
ret = E_OK;
break;
} else if (hsm_init_sta == CRYPTO_HSM_INIT_BOOT_FAIL) {
ret = E_NOT_OK;
} else {
ret = E_NOT_OK;
break;
}
count--;
} while (count);
return ret;
}