blob: ceb24aa4b5c0766606e8524be710b568166d3931 [file] [log] [blame]
Ratan Gupta2407f152017-05-31 16:01:01 +05301/*
2 * MBox Daemon Test File
3 *
4 * Copyright 2017 IBM
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20#include "config.h"
21#include "mboxd_pnor_partition_table.h"
22
23extern "C" {
24#include "mbox.h"
25#include "test/tmpf.h"
26#include "mboxd_flash.h"
27}
28
29#include <assert.h>
30#include <unistd.h>
31
32#include <fstream>
33#include <experimental/filesystem>
34
35#include <sys/mman.h>
36#include <sys/syslog.h>
37#include <sys/ioctl.h>
38#include <fcntl.h>
39
40
41uint8_t data[8] = { 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7 };
42
43#define BLOCK_SIZE 4096
44#define OFFSET BLOCK_SIZE
45#define MEM_SIZE (BLOCK_SIZE *2)
46#define DATA_SIZE sizeof(data)
47#define ERASE_SIZE BLOCK_SIZE
48#define BLOCK_SIZE_SHIFT 12
49
50
51void init(struct mbox_context* ctx)
52{
53
54 namespace fs = std::experimental::filesystem;
55 using namespace std::string_literals;
56
57 std::string tocData = "partition01=TEST1,00000000,00000400,ECC,READONLY\n"s
58 + "partition02=TEST2,00000000,00000008,ECC,READWRITE\n"s
59 + "partition03=TEST3,00000000,00000400,ECC,PRESERVED"s;
60
61 std::vector<std::string> templatePaths = { "/tmp/ro.XXXXXX",
62 "/tmp/rw.XXXXXX" ,
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050063 "/tmp/prsv.XXXXXX",
64 "/tmp/patch.XXXXXX"
Ratan Gupta2407f152017-05-31 16:01:01 +053065 };
66
67 std::vector<std::string>partitions = { "TEST1", "TEST2", "TEST3" };
68
69
70 // create various partition directory
71
72 std::string tmpROdir = mkdtemp(const_cast<char*>(templatePaths[0].c_str()));
73 assert(tmpROdir.length() != 0);
74
75 std::string tmpRWdir = mkdtemp(const_cast<char*>(templatePaths[1].c_str()));
76 assert(tmpRWdir.length() != 0);
77
78 std::string tmpPRSVdir = mkdtemp(const_cast<char*>(templatePaths[2].c_str()));
79 assert(tmpPRSVdir.length() != 0);
80
Adriana Kobylakc71dfd72017-07-22 11:10:43 -050081 std::string tmpPATCHdir = mkdtemp(const_cast<char*>(templatePaths[3].c_str()));
82 assert(tmpPATCHdir.length() != 0);
83
Ratan Gupta2407f152017-05-31 16:01:01 +053084 // create the toc file
85 fs::path tocFilePath = tmpROdir;
86
87 tocFilePath /= PARTITION_TOC_FILE;
88 std::ofstream tocFile(tocFilePath.c_str());
89 tocFile.write(tocData.c_str(), static_cast<int>(tocData.length()));
90 tocFile.close();
91
92 // create the partition files in the ro directory
93 for (auto partition : partitions)
94 {
95 fs::path partitionFilePath {tmpROdir};
96 partitionFilePath /= partition;
97 std::ofstream partitionFile(partitionFilePath.c_str());
98 partitionFile.write(reinterpret_cast<char*>(data), sizeof(data));
99 partitionFile.close();
100
101 }
102
103 // copy partition2 file from ro to rw
104 std::string roFile = tmpROdir + "/" + "TEST2";
105 std::string rwFile = tmpRWdir + "/" + "TEST2";
106 assert(fs::copy_file(roFile, rwFile) == true);
107
108 mbox_vlog = &mbox_log_console;
109 verbosity = (verbose)2;
110
111 // setting context parameters
112 ctx->erase_size_shift = BLOCK_SIZE_SHIFT;
113 ctx->block_size_shift = BLOCK_SIZE_SHIFT;
114 ctx->flash_bmap = reinterpret_cast<uint8_t*>(
115 calloc(MEM_SIZE >> ctx->erase_size_shift,
116 sizeof(*ctx->flash_bmap)));
117
118 strcpy(ctx->paths.ro_loc, tmpROdir.c_str());
119 strcpy(ctx->paths.rw_loc, tmpRWdir.c_str());
120 strcpy(ctx->paths.prsv_loc, tmpPRSVdir.c_str());
Adriana Kobylakc71dfd72017-07-22 11:10:43 -0500121 strcpy(ctx->paths.patch_loc, tmpPATCHdir.c_str());
Ratan Gupta2407f152017-05-31 16:01:01 +0530122
123}
124
125
126int main(void)
127{
128 namespace fs = std::experimental::filesystem;
129
130 int rc {};
131 char src[DATA_SIZE] {0};
132 struct mbox_context context;
133 struct mbox_context* ctx = &context;
134 memset(ctx, 0, sizeof(mbox_context));
135
136 //Initialize the context before running the test case.
137 init(ctx);
138
139 std::string tmpROdir = ctx->paths.ro_loc;
140 std::string tmpRWdir = ctx->paths.rw_loc;
141 std::string tmpPRSVdir = ctx->paths.prsv_loc;
Adriana Kobylakc71dfd72017-07-22 11:10:43 -0500142 std::string tmpPATCHdir = ctx->paths.patch_loc;
Ratan Gupta2407f152017-05-31 16:01:01 +0530143
144 // create the partition table
145 vpnor_create_partition_table_from_path(ctx, tmpROdir.c_str());
146
147 // Write to psrv partition
148
149 // As file doesn't exist there, so it copies
150 // the file from RO to PRSV and write the file in PRSV partition.
151
152 memset(src, 0xaa, sizeof(src));
153
154 rc = write_flash(ctx, (OFFSET * 3) , src, sizeof(src));
155 assert(rc == 0);
156
157 auto fd = open((tmpPRSVdir + "/" + "TEST3").c_str(), O_RDONLY);
158 auto map = mmap(NULL, MEM_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
159 assert(map != MAP_FAILED);
160
161 // verify it is written
162 rc = memcmp(src, map, sizeof(src));
163 assert(rc == 0);
164 munmap(map, MEM_SIZE);
165 close(fd);
166
167 // Write to the RO partition
168 memset(src, 0x55, sizeof(src));
169 fd = open((tmpROdir + "/" + "TEST1").c_str(), O_RDONLY);
170 map = mmap(NULL, MEM_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
171 assert(map != MAP_FAILED);
172 rc = write_flash(ctx, (OFFSET), src, sizeof(src));
173 // Should not be allowed to write on RO
174 assert(rc != 0);
175
176 munmap(map, MEM_SIZE);
177 close(fd);
178
179 // Write to the RW partition
180 memset(src, 0xbb, sizeof(src));
181 fd = open((tmpRWdir + "/" + "TEST2").c_str(), O_RDONLY);
182 map = mmap(NULL, MEM_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
183 assert(map != MAP_FAILED);
184 rc = write_flash(ctx, (OFFSET * 2), src, sizeof(src));
185 assert(rc == 0);
186 rc = memcmp(src, map, sizeof(src));
187 assert(rc == 0);
188
189 // write beyond the partition length as the partition
190 // file length is 8 byte(TEST2).
191 rc = write_flash(ctx, (OFFSET * 2 + 3), src, sizeof(src) + 20);
192 assert(rc == -1);
193
194 memset(src, 0xcc, sizeof(src));
195 rc = write_flash(ctx, (OFFSET * 2), src, sizeof(src));
196 assert(rc == 0);
197 rc = memcmp(src, map, sizeof(src));
198 assert(rc == 0);
199
200 src[0] = 0xff;
201 rc = write_flash(ctx, (OFFSET * 2), src, 1);
202 assert(rc == 0);
203 rc = memcmp(src, map, sizeof(src));
204 assert(rc == 0);
205
206 src[1] = 0xff;
207 rc = write_flash(ctx, (OFFSET * 2) + 1, &src[1], 1);
208 assert(rc == 0);
209 rc = memcmp(src, map, sizeof(src));
210 assert(rc == 0);
211
212 src[2] = 0xff;
213 rc = write_flash(ctx, (OFFSET * 2) + 2, &src[2], 1);
214 assert(rc == 0);
215 rc = memcmp(src, map, sizeof(src));
216 assert(rc == 0);
217
Adriana Kobylakc71dfd72017-07-22 11:10:43 -0500218 munmap(map, MEM_SIZE);
219 close(fd);
220
221 // START Test patch location - Patch dir has preference over other locations
222 // Copy partition2 file from ro to patch to simulate a patch file that is
223 // different from the one in rw (partition2 in rw was modified with the
224 // previous write test)
225 fs::path roFile(tmpROdir);
226 roFile /= "TEST2";
227 fs::path patchFile(tmpPATCHdir);
228 patchFile /= "TEST2";
229 assert(fs::copy_file(roFile, patchFile) == true);
230
231 // Write arbitrary data
232 char srcPatch[DATA_SIZE] {0};
233 memset(srcPatch, 0x33, sizeof(srcPatch));
234 rc = write_flash(ctx, (OFFSET * 2), srcPatch, sizeof(srcPatch));
235 assert(rc == 0);
236
237 // Check that partition file in RW location still contains the original data
238 fs::path rwFile(tmpRWdir);
239 rwFile /= "TEST2";
240 fd = open(rwFile.c_str(), O_RDONLY);
241 map = mmap(NULL, MEM_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
242 assert(map != MAP_FAILED);
243 rc = memcmp(src, map, sizeof(src));
244 assert(rc == 0);
245 munmap(map, MEM_SIZE);
246 close(fd);
247
248 // Check that partition file in PATCH location was written with the new data
249 fd = open(patchFile.c_str(), O_RDONLY);
250 map = mmap(NULL, MEM_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
251 assert(map != MAP_FAILED);
252 rc = memcmp(srcPatch, map, sizeof(srcPatch));
253 assert(rc == 0);
254 munmap(map, MEM_SIZE);
255 close(fd);
256
257 // Remove patch file so that subsequent tests don't use it
258 fs::remove(patchFile);
259 // END Test patch location
260
Ratan Gupta2407f152017-05-31 16:01:01 +0530261 fs::remove_all(fs::path {tmpROdir});
262 fs::remove_all(fs::path {tmpRWdir});
263 fs::remove_all(fs::path {tmpPRSVdir});
Adriana Kobylakc71dfd72017-07-22 11:10:43 -0500264 fs::remove_all(fs::path {tmpPATCHdir});
Ratan Gupta2407f152017-05-31 16:01:01 +0530265
266 return rc;
267}