1 /*
2 * Copyright (c) 2020, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "platform-simulation.h"
30
31 #include <assert.h>
32 #include <fcntl.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/stat.h>
37 #include <unistd.h>
38
39 #include <openthread/config.h>
40 #include <openthread/logging.h>
41 #include <openthread/platform/flash.h>
42
43 #include "lib/platform/exit_code.h"
44
45 static int sFlashFd = -1;
46
47 enum
48 {
49 SWAP_SIZE = 2048,
50 SWAP_NUM = 2,
51 };
52
otPlatFlashInit(otInstance * aInstance)53 void otPlatFlashInit(otInstance *aInstance)
54 {
55 const char *path = OPENTHREAD_CONFIG_POSIX_SETTINGS_PATH;
56 char fileName[sizeof(OPENTHREAD_CONFIG_POSIX_SETTINGS_PATH) + 32];
57 struct stat st;
58 bool create = false;
59 const char *offset = getenv("PORT_OFFSET");
60
61 memset(&st, 0, sizeof(st));
62
63 if (stat(path, &st) == -1)
64 {
65 mkdir(path, 0777);
66 }
67
68 if (offset == NULL)
69 {
70 offset = "0";
71 }
72
73 snprintf(fileName, sizeof(fileName), "%s/%s_%d.flash", path, offset, gNodeId);
74
75 if (access(fileName, 0))
76 {
77 create = true;
78 }
79
80 sFlashFd = open(fileName, O_RDWR | O_CREAT | O_CLOEXEC, 0600);
81 VerifyOrDie(sFlashFd >= 0, OT_EXIT_ERROR_ERRNO);
82
83 lseek(sFlashFd, 0, SEEK_SET);
84
85 if (create)
86 {
87 for (uint8_t index = 0; index < (uint8_t)SWAP_NUM; index++)
88 {
89 otPlatFlashErase(aInstance, index);
90 }
91 }
92 }
93
otPlatFlashGetSwapSize(otInstance * aInstance)94 uint32_t otPlatFlashGetSwapSize(otInstance *aInstance)
95 {
96 OT_UNUSED_VARIABLE(aInstance);
97
98 return SWAP_SIZE;
99 }
100
otPlatFlashErase(otInstance * aInstance,uint8_t aSwapIndex)101 void otPlatFlashErase(otInstance *aInstance, uint8_t aSwapIndex)
102 {
103 OT_UNUSED_VARIABLE(aInstance);
104
105 uint8_t buffer[SWAP_SIZE];
106 uint32_t address;
107 ssize_t rval;
108
109 assert((sFlashFd >= 0) && (aSwapIndex < SWAP_NUM));
110
111 address = aSwapIndex ? SWAP_SIZE : 0;
112 memset(buffer, 0xff, sizeof(buffer));
113
114 rval = pwrite(sFlashFd, buffer, sizeof(buffer), (off_t)address);
115 VerifyOrDie(rval == SWAP_SIZE, OT_EXIT_ERROR_ERRNO);
116 }
117
otPlatFlashRead(otInstance * aInstance,uint8_t aSwapIndex,uint32_t aOffset,void * aData,uint32_t aSize)118 void otPlatFlashRead(otInstance *aInstance, uint8_t aSwapIndex, uint32_t aOffset, void *aData, uint32_t aSize)
119 {
120 OT_UNUSED_VARIABLE(aInstance);
121
122 uint32_t address;
123 ssize_t rval;
124
125 assert((sFlashFd >= 0) && (aSwapIndex < SWAP_NUM) && (aSize <= SWAP_SIZE) && (aOffset <= (SWAP_SIZE - aSize)));
126
127 address = aSwapIndex ? SWAP_SIZE : 0;
128
129 rval = pread(sFlashFd, aData, aSize, (off_t)(address + aOffset));
130 VerifyOrDie((uint32_t)rval == aSize, OT_EXIT_ERROR_ERRNO);
131 }
132
otPlatFlashWrite(otInstance * aInstance,uint8_t aSwapIndex,uint32_t aOffset,const void * aData,uint32_t aSize)133 void otPlatFlashWrite(otInstance *aInstance, uint8_t aSwapIndex, uint32_t aOffset, const void *aData, uint32_t aSize)
134 {
135 OT_UNUSED_VARIABLE(aInstance);
136
137 uint32_t address;
138 uint8_t byte;
139 ssize_t rval;
140
141 assert((sFlashFd >= 0) && (aSwapIndex < SWAP_NUM) && (aSize <= SWAP_SIZE) && (aOffset <= (SWAP_SIZE - aSize)));
142
143 address = aSwapIndex ? SWAP_SIZE : 0;
144 address += aOffset;
145
146 for (uint32_t offset = 0; offset < aSize; offset++)
147 {
148 rval = pread(sFlashFd, &byte, sizeof(byte), (off_t)(address + offset));
149 VerifyOrDie(rval == sizeof(byte), OT_EXIT_ERROR_ERRNO);
150
151 // Use bitwise AND to emulate the behavior of flash memory
152 byte &= ((uint8_t *)aData)[offset];
153
154 rval = pwrite(sFlashFd, &byte, sizeof(byte), (off_t)(address + offset));
155 VerifyOrDie(rval == sizeof(byte), OT_EXIT_ERROR_ERRNO);
156 }
157 }
158