AJ_Status OnboardingReadInfo(AJOBS_Info* info) { AJ_Status status = AJ_OK; size_t size = sizeof(AJOBS_Info); AJ_NV_DATASET* nvramHandle; int sizeRead; if (NULL == info) { return AJ_ERR_NULL; } memset(info, 0, size); if (!AJ_NVRAM_Exist(AJ_OBS_OBINFO_NV_ID)) { return AJ_ERR_INVALID; } nvramHandle = AJ_NVRAM_Open(AJ_OBS_OBINFO_NV_ID, "r", 0); if (nvramHandle != NULL) { sizeRead = AJ_NVRAM_Read(info, size, nvramHandle); status = AJ_NVRAM_Close(nvramHandle); if (sizeRead != sizeRead) { status = AJ_ERR_READ; } else { AJ_AlwaysPrintf(("Read Info values: state=%d, ssid=%s authType=%d pc=%s\n", info->state, info->ssid, info->authType, info->pc)); } } return status; }
static AJ_Status PropertyStore_WriteConfig(uint16_t index, void* ptr, uint16_t size, char* mode) { AJ_Status status = AJ_OK; uint16_t sizeWritten = 0; AJ_NV_DATASET* nvramHandle = AJ_NVRAM_Open(index, mode, size); if (nvramHandle != NULL) { sizeWritten = AJ_NVRAM_Write(ptr, size, nvramHandle); status = AJ_NVRAM_Close(nvramHandle); if (sizeWritten != size) { status = AJ_ERR_WRITE; } } return status; }
static AJ_Status PropertyStore_ReadConfig(uint16_t index, void* ptr, uint16_t size) { AJ_Status status = AJ_OK; uint16_t sizeRead = 0; AJ_NV_DATASET* nvramHandle = AJ_NVRAM_Open(index, "r", 0); if (nvramHandle != NULL) { sizeRead = AJ_NVRAM_Read(ptr, size, nvramHandle); status = AJ_NVRAM_Close(nvramHandle); if (sizeRead != sizeRead) { status = AJ_ERR_WRITE; } } return status; }
AJ_Status OnboardingWriteInfo(AJOBS_Info* info) { AJ_Status status = AJ_OK; size_t size = sizeof(AJOBS_Info); AJ_NV_DATASET* nvramHandle; int sizeWritten; if (NULL == info) { return AJ_ERR_NULL; } AJ_AlwaysPrintf(("Going to write Info values: state=%d, ssid=%s authType=%d pc=%s\n", info->state, info->ssid, info->authType, info->pc)); nvramHandle = AJ_NVRAM_Open(AJ_OBS_OBINFO_NV_ID, "w", size); if (nvramHandle != NULL) { sizeWritten = AJ_NVRAM_Write(info, size, nvramHandle); status = AJ_NVRAM_Close(nvramHandle); if (sizeWritten != size) { status = AJ_ERR_WRITE; } } return status; }
AJ_Status TestNVRAM() { uint16_t id = 16; AJ_NV_DATASET* handle = NULL; int i = 0; size_t bytes = 0; AJ_Status status = AJ_OK; AJ_NVRAM_Layout_Print(); { handle = AJ_NVRAM_Open(id, "w", 40 + 5); AJ_NVRAM_Layout_Print(); AJ_ASSERT(handle); for (i = 0; i < 10; i++) { bytes = AJ_NVRAM_Write(&i, sizeof(i), handle); if (bytes != sizeof(i)) { status = AJ_ERR_FAILURE; goto _TEST_NVRAM_EXIT; } } { uint8_t buf[3] = { 11, 22, 33 }; uint8_t buf2[2] = { 44, 55 }; bytes = AJ_NVRAM_Write(buf, sizeof(buf), handle); if (bytes != sizeof(buf)) { status = AJ_ERR_FAILURE; goto _TEST_NVRAM_EXIT; } bytes = AJ_NVRAM_Write(buf2, sizeof(buf2), handle); if (bytes != sizeof(buf2)) { status = AJ_ERR_FAILURE; goto _TEST_NVRAM_EXIT; } } AJ_NVRAM_Close(handle); AJ_InfoPrintf(("TestNVRAM() Layout Print\n")); AJ_NVRAM_Layout_Print(); handle = AJ_NVRAM_Open(id, "r", 0); AJ_ASSERT(handle); for (i = 0; i < 10; i++) { int data = 0; bytes = AJ_NVRAM_Read(&data, sizeof(data), handle); if (bytes != sizeof(data) || data != i) { status = AJ_ERR_FAILURE; goto _TEST_NVRAM_EXIT; } } for (i = 1; i < 6; i++) { uint8_t data = 0; AJ_NVRAM_Read(&data, 1, handle); if (data != i * 11) { status = AJ_ERR_FAILURE; goto _TEST_NVRAM_EXIT; } } AJ_NVRAM_Close(handle); } if (AJ_NVRAM_Exist(id + 1)) { AJ_ASSERT(AJ_NVRAM_Delete(id + 1) == AJ_OK); } // Force storage compaction for (i = 0; i < 12; i++) { if (i == 6) { handle = AJ_NVRAM_Open(id + 2, "w", 100); AJ_ASSERT(handle); status = AJ_NVRAM_Close(handle); if (AJ_OK != status) { goto _TEST_NVRAM_EXIT; } continue; } handle = AJ_NVRAM_Open(id + 1, "w", 200); AJ_ASSERT(handle); status = AJ_NVRAM_Close(handle); if (AJ_OK != status) { goto _TEST_NVRAM_EXIT; } } AJ_InfoPrintf(("Compaction Layout Print\n")); AJ_NVRAM_Layout_Print(); _TEST_NVRAM_EXIT: //AJ_NVRAM_Close(handle); return status; }
AJ_Status TestNvramDelete() { AJ_Status status = AJ_OK; AJ_NV_DATASET* nvramHandle; if (tid1 % 2 == 1) { #ifndef OBS_ONLY if (AJ_NVRAM_Exist(tid1)) { AJ_ASSERT(AJ_NVRAM_Delete(tid1) == AJ_OK); } AJ_InfoPrintf(("LAYOUT AFTER DELETE 1\n")); AJ_NVRAM_Layout_Print(); if (AJ_NVRAM_Exist(tid2)) { AJ_ASSERT(AJ_NVRAM_Delete(tid2) == AJ_OK); } AJ_InfoPrintf(("LAYOUT AFTER DELETE 2\n")); AJ_NVRAM_Layout_Print(); if (AJ_NVRAM_Exist(tid3)) { AJ_ASSERT(AJ_NVRAM_Delete(tid3) == AJ_OK); } AJ_InfoPrintf(("LAYOUT AFTER DELETE 3\n")); AJ_NVRAM_Layout_Print(); if (AJ_NVRAM_Exist(tid4)) { AJ_ASSERT(AJ_NVRAM_Delete(tid4) == AJ_OK); } AJ_InfoPrintf(("LAYOUT AFTER DELETE 4\n")); AJ_NVRAM_Layout_Print(); #endif if (AJ_NVRAM_Exist(AJ_NVRAM_ID_FOR_APPS)) { AJOBS_Info_Test emptyInfo; AJ_Status status = AJ_OK; size_t size = sizeof(AJOBS_Info_Test); memset(&emptyInfo, 0, sizeof(emptyInfo)); AJ_AlwaysPrintf(("Going to write Info values: state=%d, ssid=%s authType=%d pc=%s\n", emptyInfo.state, emptyInfo.ssid, emptyInfo.authType, emptyInfo.pc)); //AJ_NV_DATASET* nvramHandle = AJ_NVRAM_Open(AJ_NVRAM_ID_CREDS_MAX + 1, "w", size); //PROPERTY STORE DEVICE ID nvramHandle = AJ_NVRAM_Open(AJ_NVRAM_ID_FOR_APPS, "w", size); if (nvramHandle != NULL) { int sizeWritten = AJ_NVRAM_Write(&emptyInfo, size, nvramHandle); status = AJ_NVRAM_Close(nvramHandle); if (sizeWritten != size) { status = AJ_ERR_WRITE; goto _TEST_NVRAM_DELETE_EXIT; } } //nvramHandle = AJ_NVRAM_Open(AJ_NVRAM_ID_CREDS_MAX + 1, "r", 0); //PROPERTY STORE DEVICE ID nvramHandle = AJ_NVRAM_Open(AJ_NVRAM_ID_FOR_APPS, "r", 0); if (nvramHandle != NULL) { int sizeRead = AJ_NVRAM_Read(&emptyInfo, size, nvramHandle); status = AJ_NVRAM_Close(nvramHandle); if (sizeRead != sizeRead) { status = AJ_ERR_READ; } else { AJ_AlwaysPrintf(("Read Info values: state=%d, ssid=%s authType=%d pc=%s\n", emptyInfo.state, emptyInfo.ssid, emptyInfo.authType, emptyInfo.pc)); } } } AJ_InfoPrintf(("LAYOUT AFTER DELETE OBS\n")); AJ_NVRAM_Layout_Print(); } else { AJ_NVRAM_Clear(); AJ_InfoPrintf(("LAYOUT AFTER CLEAR ALL\n")); AJ_NVRAM_Layout_Print(); } return status; _TEST_NVRAM_DELETE_EXIT: AJ_NVRAM_Close(nvramHandle); return status; }
AJ_Status TestNvramRead() { //uint16_t id = 0; AJ_NV_DATASET* d1 = NULL; AJ_NV_DATASET* d2 = NULL; AJ_NV_DATASET* d3 = NULL; AJ_NV_DATASET* d4 = NULL; int i = 0; size_t bytes1, bytes2, bytes3, bytes4 = 0; AJ_Status status = AJ_OK; AJ_NVRAM_Layout_Print(); #ifdef READ_STRESS while (TRUE) { #endif //AJ_InfoPrintf(("LAYOUT AFTER OPEN - READ MODE\n")); //AJ_NVRAM_Layout_Print(); d1 = AJ_NVRAM_Open(tid1, "r", 0); //d1 = AJ_NVRAM_Open(66, "r", 0); //NEGATIVE READ TEST AJ_ASSERT(d1); for (i = 0; i < d1->capacity / 4; i++) { int data1 = 0; bytes1 = AJ_NVRAM_Read(&data1, sizeof(data1), d1); if (bytes1 != sizeof(data1) || data1 != i) { return AJ_ERR_FAILURE; } #ifdef SHOW_READ if (i % 10 == 0) { AJ_InfoPrintf(("Dataset 1 capacity %u curPos %u flash value: %u\n", d1->capacity, d1->curPos, data1)); } #endif } if (d1 != NULL) { AJ_NVRAM_Close(d1); AJ_ASSERT(d1); } d2 = AJ_NVRAM_Open(tid2, "r", 0); AJ_ASSERT(d2); for (i = 0; i < d2->capacity / 4; i++) { int data2 = 0; bytes2 = AJ_NVRAM_Read(&data2, sizeof(data2), d2); if (bytes2 != sizeof(data2) || data2 != i) { return AJ_ERR_FAILURE; } #ifdef SHOW_READ if (i % 10 == 0) { AJ_InfoPrintf(("Dataset 2 capacity %u curPos %u flash value: %u\n", d2->capacity, d2->curPos, data2)); } #endif } if (d2 != NULL) { AJ_NVRAM_Close(d2); AJ_ASSERT(d2); } d3 = AJ_NVRAM_Open(tid3, "r", 0); AJ_ASSERT(d3); for (i = 0; i < d3->capacity / 4; i++) { int data3 = 0; bytes3 = AJ_NVRAM_Read(&data3, sizeof(data3), d3); if (bytes3 != sizeof(data3) || data3 != i) { return AJ_ERR_FAILURE; } #ifdef SHOW_READ if (i % 10 == 0) { AJ_InfoPrintf(("Dataset 3 capacity %u curPos %u flash value: %u\n", d3->capacity, d3->curPos, data3)); } #endif } if (d3 != NULL) { AJ_NVRAM_Close(d3); AJ_ASSERT(d3); } d4 = AJ_NVRAM_Open(tid4, "r", 0); AJ_ASSERT(d4); for (i = 0; i < d4->capacity / 4; i++) { int data4 = 0; bytes4 = AJ_NVRAM_Read(&data4, sizeof(data4), d4); if (bytes4 != sizeof(data4) || data4 != i) { return AJ_ERR_FAILURE; } #ifdef SHOW_READ if (i % 10 == 0) { AJ_InfoPrintf(("Dataset 4 capacity %u curPos %u flash value: %u\n", d4->capacity, d4->curPos, data4)); } #endif } if (d4 != NULL) { AJ_NVRAM_Close(d4); AJ_ASSERT(d4); } AJ_InfoPrintf(("LAYOUT AFTER READ --- END capacity %u curPos %u\n", d4->capacity, d4->curPos)); AJ_NVRAM_Layout_Print(); #ifdef READ_STRESS } #endif return status; }
AJ_Status TestNvramWrite() { AJ_NV_DATASET* d1 = NULL; AJ_NV_DATASET* d2 = NULL; AJ_NV_DATASET* d3 = NULL; AJ_NV_DATASET* d4 = NULL; int i = 0; uint16_t cap1, cap2, cap3, cap4 = 0; size_t bytes1, bytes2, bytes3, bytes4 = 0; AJ_Status status = AJ_OK; #ifdef WRITE_STRESS while (TRUE) { #endif cap1 = (tid1 % ((AJ_NVRAM_REQUESTED / 4) - 100)) + 1; cap2 = (tid2 % ((AJ_NVRAM_REQUESTED / 4) - 100)) + 1; cap3 = (tid3 % ((AJ_NVRAM_REQUESTED / 4) - 100)) + 1; cap4 = (tid4 % ((AJ_NVRAM_REQUESTED / 4) - 100)) + 1; d1 = AJ_NVRAM_Open(tid1, "w", cap1); for (i = 0; i < AJ_NVRAM_REQUESTED / 4; i++) { if ((d1->capacity - d1->curPos) >= sizeof(i)) { bytes1 = AJ_NVRAM_Write(&i, sizeof(i), d1); if (bytes1 != sizeof(i)) { return AJ_ERR_FAILURE; } } } AJ_InfoPrintf(("Dataset1 bytes: %u i: %u sizeof(i): %u capacity %u curPos %u\n", bytes1, i, sizeof(i), d1->capacity, d1->curPos)); AJ_InfoPrintf(("LAYOUT AFTER WRITE\n")); AJ_NVRAM_Layout_Print(); if (d1 != NULL) { AJ_NVRAM_Close(d1); AJ_ASSERT(d1); } d2 = AJ_NVRAM_Open(tid2, "w", cap2); AJ_ASSERT(d2); for (i = 0; i < AJ_NVRAM_REQUESTED / 4; i++) { if ((d2->capacity - d2->curPos) >= sizeof(i)) { bytes2 = AJ_NVRAM_Write(&i, sizeof(i), d2); if (bytes2 != sizeof(i)) { return AJ_ERR_FAILURE; } } } AJ_InfoPrintf(("Dataset2 bytes: %u i: %u sizeof(i): %u capacity %u curPos %u\n", bytes2, i, sizeof(i), d2->capacity, d2->curPos)); AJ_InfoPrintf(("LAYOUT AFTER WRITE\n")); AJ_NVRAM_Layout_Print(); if (d2 != NULL) { AJ_NVRAM_Close(d2); AJ_ASSERT(d2); } d3 = AJ_NVRAM_Open(tid3, "w", cap3); AJ_ASSERT(d3); for (i = 0; i < AJ_NVRAM_REQUESTED / 4; i++) { if ((d3->capacity - d3->curPos) >= sizeof(i)) { bytes3 = AJ_NVRAM_Write(&i, sizeof(i), d3); if (bytes3 != sizeof(i)) { return AJ_ERR_FAILURE; } } } AJ_InfoPrintf(("Dataset3 bytes: %u i: %u sizeof(i): %u capacity %u curPos %u\n", bytes2, i, sizeof(i), d2->capacity, d2->curPos)); AJ_InfoPrintf(("LAYOUT AFTER WRITE\n")); AJ_NVRAM_Layout_Print(); if (d3 != NULL) { AJ_NVRAM_Close(d3); AJ_ASSERT(d3); } d4 = AJ_NVRAM_Open(tid4, "w", cap4); AJ_ASSERT(d4); for (i = 0; i < AJ_NVRAM_REQUESTED / 4; i++) { if ((d4->capacity - d4->curPos) >= sizeof(i)) { bytes4 = AJ_NVRAM_Write(&i, sizeof(i), d4); if (bytes4 != sizeof(i)) { return AJ_ERR_FAILURE; } } } AJ_InfoPrintf(("Dataset4 bytes: %u i: %u sizeof(i): %u capacity %u curPos %u\n", bytes2, i, sizeof(i), d2->capacity, d2->curPos)); AJ_InfoPrintf(("LAYOUT AFTER WRITE\n")); AJ_NVRAM_Layout_Print(); if (d4 != NULL) { AJ_NVRAM_Close(d4); AJ_ASSERT(d4); } AJ_InfoPrintf(("LAYOUT AFTER CLOSE - WRITE MODE\n")); AJ_NVRAM_Layout_Print(); #ifdef WRITE_STRESS } #endif return status; }
AJ_Status TestObsWrite() { AJ_Status status = AJ_OK; AJ_NV_DATASET* nvramHandle; AJOBS_Info_Test info; int nTest; size_t size = sizeof(info); char* ssid[] = { "abcdefghABCDEFGH", "aaaaaaaa", "bbbbbbbb", "cccccccc", "dddddddd", "eeeeeeee", "ffffffff", "gggggggg", "hhhhhhhh", "iiiiiiii", "jjjjjjjj", "kkkkkkkk", "llllllll", "mmmmmmmm", "nnnnnnnn", "oooooooo", "pppppppp", "qqqqqqqq", "rrrrrrrr", "ssssssss", "", "tttttttt", "uuuuuuuu", "vvvvvvvv", "wwwwwwww", "xxxxxxxx", "yyyyyyyy", "zzzzzzzz", "11111111", "22222222", "33333333", "44444444", "55555555", "66666666", "77777777", "888888888888888888888888888888", "99999999", "aaaa1111", "bbbb2222", "cccc3333", "dddd4444", "TRTESTING123", "eeee5555", "", "TR-TESTING-43" }; char pc[] = "aaaaabbbbbcccccAAAAABBBBBCCCCCzzzzzZZZZZ1111122222"; size_t i; AJ_NVRAM_Layout_Print(); //if( AJ_NVRAM_Exist(AJ_NVRAM_ID_CREDS_MAX + 100)){ //NEGATIVE TEST, ID DOESN'T EXIST //if( AJ_NVRAM_Exist(AJ_NVRAM_ID_CREDS_MAX + 1)){ //PROPERTY STORE DEVICE ID if (AJ_NVRAM_Exist(AJ_NVRAM_ID_FOR_APPS)) { //nvramHandle = AJ_NVRAM_Open(100, "r", 0); //NEGATIVE TEST, OPEN INVALID ID //nvramHandle = AJ_NVRAM_Open(AJ_NVRAM_ID_CREDS_MAX + 1, "r", 0); //PROPERTY STORE DEVICE ID nvramHandle = AJ_NVRAM_Open(AJ_NVRAM_ID_FOR_APPS, "r", 0); if (nvramHandle != NULL) { int sizeRead = AJ_NVRAM_Read(&info, size, nvramHandle); status = AJ_NVRAM_Close(nvramHandle); AJ_InfoPrintf(("sizeRead: %u, size: %u\n", sizeRead, size)); if (sizeRead != size) { status = AJ_ERR_READ; } else { AJ_InfoPrintf(("Read Info values: state=%d, ssid=%s authType=%d pc=%s\n", info.state, info.ssid, info.authType, info.pc)); } } } //nTest = AJ_NVRAM_Read(&info, size, nvramHandle); //NEGATIVE TEST, READ NULL HANDLE //nTest = AJ_NVRAM_Write(&info, size, nvramHandle); //NEGATIVE TEST, WRITE TO NULL HANDLE for (i = 0; i < ArraySize(ssid); i++) { strncpy(info.ssid, ssid[i], sizeof(info.ssid)); strncpy(info.pc, pc, sizeof(info.pc)); info.authType = 0; info.state = 0; #ifdef OBS_STRESS while (TRUE) { #endif #ifdef SHOW_REWRITES AJ_AlwaysPrintf(("Going to write Info values: state=%d, ssid=%s authType=%d pc=%s\n", info.state, info.ssid, info.authType, info.pc)); #endif //nvramHandle = AJ_NVRAM_Open(AJ_NVRAM_ID_CREDS_MAX + 1, "w", 0); //NEGATIVE TEST, OPEN 0 SIZE //nvramHandle = AJ_NVRAM_Open(AJ_NVRAM_ID_CREDS_MAX + 1, "t", size); //NEGATIVE TEST, INVALID MODE //nvramHandle = AJ_NVRAM_Open(0, "w", size); //NEGATIVE TEST, OPEN 0 ID //nvramHandle = AJ_NVRAM_Open(AJ_NVRAM_ID_CREDS_MAX + 1, "w", size); //PROPERTY STORE DEVICE ID nvramHandle = AJ_NVRAM_Open(AJ_NVRAM_ID_FOR_APPS, "w", size); if (nvramHandle != NULL) { int sizeWritten = AJ_NVRAM_Write(&info, size, nvramHandle); status = AJ_NVRAM_Close(nvramHandle); if (sizeWritten != size) { status = AJ_ERR_WRITE; } } //nvramHandle = AJ_NVRAM_Open(AJ_NVRAM_ID_CREDS_MAX + 1, "r", 0); //PROPERTY STORE DEVICE ID nvramHandle = AJ_NVRAM_Open(AJ_NVRAM_ID_FOR_APPS, "r", 0); if (nvramHandle != NULL) { int sizeRead = AJ_NVRAM_Read(&info, size, nvramHandle); status = AJ_NVRAM_Close(nvramHandle); if (sizeRead != sizeRead) { status = AJ_ERR_READ; } #ifdef SHOW_REWRITES else { AJ_InfoPrintf(("Read Info values: state=%d, ssid=%s authType=%d pc=%s\n", info.state, info.ssid, info.authType, info.pc)); } #endif } #ifdef NEGATIVE_OPEN nvramHandle = AJ_NVRAM_Open(66, "r", 0); status = AJ_NVRAM_Close(nvramHandle); #endif //AJ_NVRAM_Layout_Print(); #ifdef OBS_STRESS AJ_Sleep(2000); } #endif } AJ_NVRAM_Layout_Print(); return status; }
AJ_Status CreateTrailOfBreadcrumbs(void) { uint16_t minNvramSpaceNeeded; uint16_t currentAvailableNvramSpace; uint16_t someNvramId = 0; AJ_NV_DATASET* someDataHandle = NULL; uint8_t sizeOfEachSlice; uint16_t i; size_t numBytesExpectingToWrite; size_t numBytesActuallyWritten; /* * Test program would write (place breadcrumbs) over the NVRAM, anyway. */ AJ_NVRAM_Clear(); currentAvailableNvramSpace = AJ_NVRAM_GetSizeRemaining(); /* * At minimum, the test needs to store: * a. The message itself * b. The number of breadcrumbs in the trail (the mininum value is 1) * (this is essentially the value held by lengthOfBreadcrumbTrail) */ minNvramSpaceNeeded = (estimatedOverheadPerNvramItem + sizeof(sensumManifestum)) + (estimatedOverheadPerNvramItem + sizeof(lengthOfBreadcrumbTrail)); if (currentAvailableNvramSpace < minNvramSpaceNeeded) { AJ_Printf("ERROR: Available NVRAM space (%u bytes) is less than needed (%u bytes).\n", currentAvailableNvramSpace, minNvramSpaceNeeded); return AJ_ERR_RESOURCES; } /* * Any remaining space can be used to add more breadcrumbs. * max_num_bread_crumbs = nvram_size_available / size_occupied_by_each_crumb * * size_occupied_by_each_crumb = estimatedOverheadPerNvramItem + sizeof(id) */ lengthOfBreadcrumbTrail = (currentAvailableNvramSpace - minNvramSpaceNeeded) / (estimatedOverheadPerNvramItem + sizeof(someNvramId)); /* * Create the trail of bread crumbs starting at smId * * Generate a random list of nvram ids, lengthOfBreadcrumbTrail number of * elements. The list should not have any duplicates and should not include * marker ids viz. smId and countId. * * This is necessary to ensure that the trail of breadcrumbs is without * any loops. The simplest way to generate a list of unique nvram ids * would be to divide the available space into equal slices and generate * one id from each slice. * * The starting id is AJ_NVRAM_ID_APPS_BEGIN and the ending id is 0xFFFF. * * There are a total of (lengthOfBreadcrumbTrail + 1) items to * go through, including the starting point smId. */ sizeOfEachSlice = (0xFFFF - AJ_NVRAM_ID_APPS_BEGIN) / lengthOfBreadcrumbTrail; /* The starting point has to be the constant marker, smId */ someNvramId = smId; for (i = 0; i < lengthOfBreadcrumbTrail + 1; i++) { uint8_t randByte; uint16_t startId; uint16_t nextId; void* pointerToData; AJ_RandBytes(&randByte, sizeof(randByte)); startId = AJ_NVRAM_ID_APPS_BEGIN + sizeOfEachSlice * i; nextId = startId + randByte % sizeOfEachSlice; /* Ensure uniqueness of id - no conflicts with well-known markers */ if (smId == nextId || countId == nextId) { nextId += (0 == i % 2) ? -1 : 1; } numBytesExpectingToWrite = (lengthOfBreadcrumbTrail != i) ? sizeof(nextId) : sizeof(sensumManifestum); currentAvailableNvramSpace = AJ_NVRAM_GetSizeRemaining(); someDataHandle = AJ_NVRAM_Open(someNvramId, AJTestWriteMode, numBytesExpectingToWrite); if (NULL == someDataHandle) { /* Cannot proceed any further due to failed breadcrumb access */ return AJ_ERR_NVRAM_WRITE; } pointerToData = (lengthOfBreadcrumbTrail != i) ? (void*) (&nextId) : (void*) sensumManifestum; numBytesActuallyWritten = AJ_NVRAM_Write(pointerToData, numBytesExpectingToWrite, someDataHandle); /* done writing the data, can close the handle */ if (AJ_OK != AJ_NVRAM_Close(someDataHandle)) { AJ_Printf("WARN: For id: %u, AJ_NVRAM_Close did NOT return %s (code: %u)\n", someNvramId, AJ_StatusText(AJ_OK), AJ_OK); } if (AJTestNvramWriteFailure == numBytesActuallyWritten || numBytesExpectingToWrite != numBytesActuallyWritten) { /* Cannot proceed any further due to breadcrumb write failure */ return AJ_ERR_NVRAM_WRITE; } /* * The write has been successful. * * Check whether estimatedOverheadPerNvramItem (rough estimate) is * accurate. Overestimating estimatedOverheadPerNvramItem is fine * (erring on the side on caution). */ if (estimatedOverheadPerNvramItem < currentAvailableNvramSpace - AJ_NVRAM_GetSizeRemaining() - numBytesExpectingToWrite) { AJ_Printf("ERROR: The estimated overhead per NVRAM item (%u bytes) is not accurate. It needs to be increased.\n", estimatedOverheadPerNvramItem); return AJ_ERR_FAILURE; } /* Move to the next breadcrumb */ someNvramId = nextId; } /* * All the items are written. * Write the value of lengthOfBreadcrumbTrail */ someDataHandle = AJ_NVRAM_Open(countId, AJTestWriteMode, sizeof(lengthOfBreadcrumbTrail)); if (NULL == someDataHandle) { return AJ_ERR_NVRAM_WRITE; } numBytesExpectingToWrite = sizeof(lengthOfBreadcrumbTrail); numBytesActuallyWritten = AJ_NVRAM_Write((void*)&lengthOfBreadcrumbTrail, numBytesExpectingToWrite, someDataHandle); /* done writing the data, can close the handle */ if (AJ_OK != AJ_NVRAM_Close(someDataHandle)) { AJ_Printf("WARN: For id: %u, AJ_NVRAM_Close did NOT return %s (code: %u)\n", countId, AJ_StatusText(AJ_OK), AJ_OK); } if (AJTestNvramWriteFailure == numBytesActuallyWritten || numBytesExpectingToWrite != numBytesActuallyWritten) { return AJ_ERR_NVRAM_WRITE; } return AJ_OK; }
AJ_Status FollowTrailOfBreadcrumbs(void) { static char scratchPad[sizeof(sensumManifestum)]; uint16_t someNvramId = 0; AJ_NV_DATASET* someDataHandle = NULL; size_t numBytesExpectingToRead; size_t numBytesActuallyRead; uint16_t i; /* * As long as NVRAM wasn't cleared between two successive runs of * the test, it should be possible to read the known data written at * the very end of the test by the previous run. * * The first item to read is the number of breadcrumbs. */ if (1 != AJ_NVRAM_Exist(countId)) { /* cannot find the marker countId */ return AJ_ERR_NVRAM_READ; } someDataHandle = AJ_NVRAM_Open(countId, AJTestReadMode, 0); if (NULL == someDataHandle) { /* cannot open the marker countId */ return AJ_ERR_NVRAM_READ; } numBytesExpectingToRead = sizeof(lengthOfBreadcrumbTrail); numBytesActuallyRead = AJ_NVRAM_Read((void*)&lengthOfBreadcrumbTrail, numBytesExpectingToRead, someDataHandle); if (AJ_OK != AJ_NVRAM_Close(someDataHandle)) { AJ_Printf("WARN: For id: %u, AJ_NVRAM_Close did NOT return %s (code: %u)\n", countId, AJ_StatusText(AJ_OK), AJ_OK); } if (AJTestNvramReadFailure == numBytesActuallyRead || numBytesExpectingToRead != numBytesActuallyRead) { /* could not read from the marker countId */ return AJ_ERR_NVRAM_READ; } /* * Follow the trail of bread crumbs starting at smId */ someNvramId = smId; for (i = 0; i < lengthOfBreadcrumbTrail + 1; i++) { uint8_t isIdPresent = AJ_NVRAM_Exist(someNvramId); void* pointerToData = (lengthOfBreadcrumbTrail != i) ? (void*) &someNvramId : (void*) scratchPad; someDataHandle = (1 == isIdPresent) ? AJ_NVRAM_Open(someNvramId, AJTestReadMode, 0) : NULL; if (NULL == someDataHandle) { /* Cannot proceed any further due to failed breadcrumb access */ return AJ_ERR_NVRAM_READ; } numBytesExpectingToRead = (lengthOfBreadcrumbTrail != i) ? sizeof(someNvramId) : sizeof(sensumManifestum); numBytesActuallyRead = AJ_NVRAM_Read(pointerToData, numBytesExpectingToRead, someDataHandle); /* done reading the data, can close the handle */ if (AJ_OK != AJ_NVRAM_Close(someDataHandle)) { AJ_Printf("WARN: For id: %u, AJ_NVRAM_Close did NOT return %s (code: %u)\n", someNvramId, AJ_StatusText(AJ_OK), AJ_OK); } if (AJTestNvramReadFailure == numBytesActuallyRead || numBytesExpectingToRead != numBytesActuallyRead) { /* Cannot proceed any further due to breadcrumb read failure */ return AJ_ERR_NVRAM_READ; } if (lengthOfBreadcrumbTrail == i) { /* Final crumb where message has been retrieved */ return (0 == strcmp(scratchPad, sensumManifestum)) ? AJ_OK : AJ_ERR_NVRAM_READ; } } return AJ_OK; }