xref: /aosp_15_r20/external/openthread/examples/platforms/simulation/flash.c (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
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