libdisplaymodule: fix compilation
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos7580.git] / mobicore / Daemon / src / FSD2.cpp
1 /*
2 * Copyright (c) 2013-2015 TRUSTONIC LIMITED
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 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the TRUSTONIC LIMITED nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /**
33 * Filesystem v2 delegate.
34 *
35 * Handles incoming storage requests from TA through STH
36 */
37
38 #include <unistd.h>
39 #include <string>
40 #include <cstring>
41 #include <errno.h>
42 #include <stdlib.h>
43 #include <signal.h>
44 #include <memory>
45 #include <stdio.h>
46 #include <assert.h>
47 #include <pthread.h>
48 #include <sys/stat.h>
49
50 #undef LOG_TAG
51 #define LOG_TAG "TeeFilesystem"
52 #include <log.h>
53 #include "tee_client_api.h" /* TEEC_Result */
54 #include "MobiCoreDriverApi.h" /* MC session */
55 #include "sth2ProxyApi.h"
56 #include "sfs_error.h"
57 #include "FSD2.h"
58
59 #define MAX_SECTOR_SIZE 4096
60 #define SECTOR_NUM 8
61 #define SFS_L2_CACHE_SLOT_SPACE 12 // Hard coded size, cf. sfs_internal.h
62 #define DEFAULT_WORKSPACE_SIZE (SECTOR_NUM * (MAX_SECTOR_SIZE + SFS_L2_CACHE_SLOT_SPACE))
63
64 extern const std::string& getTbStoragePath();
65
66 /*----------------------------------------------------------------------------
67 * Utilities functions
68 *----------------------------------------------------------------------------*/
69 static TEEC_Result errno2serror() {
70 switch (errno) {
71 case EINVAL:
72 return S_ERROR_BAD_PARAMETERS;
73 case EMFILE:
74 return S_ERROR_NO_MORE_HANDLES;
75 case ENOENT:
76 return S_ERROR_ITEM_NOT_FOUND;
77 case EEXIST:
78 return S_ERROR_ITEM_EXISTS;
79 case ENOSPC:
80 return S_ERROR_STORAGE_NO_SPACE;
81 case ENOMEM:
82 return S_ERROR_OUT_OF_MEMORY;
83 case EBADF:
84 case EACCES:
85 default:
86 return S_ERROR_STORAGE_UNREACHABLE;
87 }
88 }
89
90 class Partition {
91 std::string name_;
92 FILE* fd_;
93 off_t size_;
94 public:
95 Partition(std::string name): name_(name), fd_(NULL), size_(0) {}
96 const char* name() const {
97 return name_.c_str();
98 }
99 off_t size() {
100 if (size_ == 0) {
101 struct stat st;
102 if (::stat(name(), &st)) {
103 return -1;
104 }
105 size_ = st.st_size;
106 }
107 return size_;
108 }
109 TEEC_Result create() {
110 LOG_I("%s: Create storage file \"%s\"", __func__, name());
111 fd_ = ::fopen(name(), "w+b");
112 if (!fd_) {
113 LOG_E("%s: %s creating storage file \"%s\"", __func__,
114 strerror(errno), name());
115 return errno2serror();
116 }
117 return S_SUCCESS;
118 }
119 TEEC_Result destroy() {
120 if (!fd_) {
121 /* The partition is not open */
122 return S_ERROR_BAD_STATE;
123 }
124
125 /* Try to erase the file */
126 if (::unlink(name())) {
127 /* File in use or OS didn't allow the operation */
128 return errno2serror();
129 }
130
131 return S_SUCCESS;
132 }
133 TEEC_Result open() {
134 /* Open the file */
135 LOG_I("%s: Open storage file \"%s\"", __func__, name());
136 fd_ = ::fopen(name(), "r+b");
137 if (!fd_) {
138 LOG_E("%s: %s opening storage file \"%s\"", __func__,
139 strerror(errno), name());
140 return errno2serror();
141 }
142 LOG_I("%s: storage file \"%s\" successfully open (size: %ld KB / %ld B))",
143 __func__, name(), size() / 1024, size());
144 return S_SUCCESS;
145 }
146 TEEC_Result close() {
147 if (!fd_) {
148 /* The partition is not open */
149 return S_ERROR_BAD_STATE;
150 }
151
152 ::fclose(fd_);
153 fd_ = NULL;
154
155 return S_SUCCESS;
156 }
157 TEEC_Result read(uint8_t* buf, uint32_t length, uint32_t offset) {
158 if (!fd_) {
159 /* The partition is not open */
160 return S_ERROR_BAD_STATE;
161 }
162
163 if (::fseek(fd_, offset, SEEK_SET)) {
164 LOG_E("%s: fseek error: %s", __func__, strerror(errno));
165 return errno2serror();
166 }
167
168 if (::fread(buf, length, 1, fd_) != 1) {
169 if (feof(fd_)) {
170 LOG_E("%s: fread error: End-Of-File detected", __func__);
171 return S_ERROR_ITEM_NOT_FOUND;
172 }
173 LOG_E("%s: fread error: %s", __func__, strerror(errno));
174 return errno2serror();
175 }
176
177 return S_SUCCESS;
178 }
179 TEEC_Result write(const uint8_t* buf, uint32_t length, uint32_t offset) {
180 if (!fd_) {
181 /* The partition is not open */
182 return S_ERROR_BAD_STATE;
183 }
184
185 if (::fseek(fd_, offset, SEEK_SET)) {
186 LOG_E("%s: fseek error: %s", __func__, strerror(errno));
187 return errno2serror();
188 }
189
190 if (::fwrite(buf, length, 1, fd_) != 1) {
191 LOG_E("%s: fwrite error: %s", __func__, strerror(errno));
192 return errno2serror();
193 }
194 return S_SUCCESS;
195 }
196 TEEC_Result sync() {
197 if (!fd_) {
198 /* The partition is not open */
199 return S_ERROR_BAD_STATE;
200 }
201
202 /*
203 * First make sure that the data in the stdio buffers is flushed to the
204 * file descriptor
205 */
206 if (::fflush(fd_)) {
207 return errno2serror();
208 }
209
210 /* Then synchronize the file descriptor with the file-system */
211 if (::fdatasync(fileno(fd_))) {
212 return errno2serror();
213 }
214
215 return S_SUCCESS;
216 }
217 TEEC_Result resize(off_t new_size) {
218 if (!fd_) {
219 /* The partition is not open */
220 return S_ERROR_BAD_STATE;
221 }
222
223 if (new_size == size()) {
224 return S_SUCCESS;
225 }
226
227 if (new_size > size()) {
228 /*
229 * Enlarge the partition file. Make sure we actually write some
230 * non-zero data into the new sectors. Otherwise, some file-system
231 * might not really reserve the storage space but use a sparse
232 * representation. In this case, a subsequent write instruction
233 * could fail due to out-of-space, which we want to avoid.
234 */
235 if (::fseek(fd_, 0, SEEK_END)) {
236 LOG_E("%s: fseek error: %s", __func__, strerror(errno));
237 return errno2serror();
238 }
239
240 off_t count = new_size - size();
241 while (count) {
242 if (::fputc(0xA5, fd_) != 0xA5) {
243 LOG_E("%s: fputc error: %s", __func__, strerror(errno));
244 return errno2serror();
245 }
246 count--;
247 }
248 } else {
249 /* Truncate the partition file */
250 if (::ftruncate(fileno(fd_), new_size)) {
251 return errno2serror();
252 }
253 }
254 // Update size
255 size_ = new_size;
256 return S_SUCCESS;
257 }
258 };
259
260 struct FileSystem::Impl {
261 pthread_t thread;
262
263 /*
264 * Communication buffer, includes the workspace
265 */
266 struct {
267 STH2_delegation_exchange_buffer_t exchange_buffer;
268 uint8_t workspace[DEFAULT_WORKSPACE_SIZE];
269 } dci;
270
271 /*
272 * Provided by the SWd
273 */
274 uint32_t sector_size;
275
276 /*
277 * The 16 possible partitions
278 */
279 Partition* partitions[16];
280
281 // thread value does not matter, only initialised for code checkers
282 Impl(): thread(pthread_self()) {
283 ::memset(&dci, 0, sizeof(dci));
284 sector_size = 0;
285 for (int i = 0; i < 16; i++) {
286 partitions[i] = NULL;
287 }
288 }
289 void run();
290 int executeCommand();
291 const char* getCommandtypeString(uint32_t nInstructionID);
292 };
293
294 FileSystem::FileSystem(): pimpl_(new Impl) {}
295
296 FileSystem::~FileSystem() {
297 delete pimpl_;
298 }
299
300 void* FileSystem::run(void* arg) {
301 FileSystem::Impl* pimpl = static_cast<FileSystem::Impl*>(arg);
302 pimpl->run();
303 return NULL;
304 }
305
306 int FileSystem::open() {
307 const std::string storage_dir_name = getTbStoragePath();
308
309 // Create Tbase storage directory if necessary, parent is assumed to exist
310 if (::mkdir(storage_dir_name.c_str(), 0700) && (errno != EEXIST)) {
311 LOG_ERRNO("creating storage folder");
312 // Do not return any error and block deamon boot flow or stop FSD thread.
313 // Just print a "warning/not critical error message".
314 // Directory could also be created by platform at initialization time.
315 // return -1;
316 }
317
318 // Create partitions with default names
319 for (int i = 0; i < 16; i++) {
320 char file_name[16];
321 snprintf(file_name, sizeof(file_name), "/Store_%1X.tf", i);
322 pimpl_->partitions[i] = new Partition(storage_dir_name + file_name);
323 }
324
325 /* Prepare DCI message buffer */
326 pimpl_->dci.exchange_buffer.nWorkspaceLength = DEFAULT_WORKSPACE_SIZE;
327
328 // Create listening thread
329 int ret = pthread_create(&pimpl_->thread, NULL, run, pimpl_);
330 if (ret) {
331 LOG_E("pthread_create failed with error code %d", ret);
332 return -1;
333 }
334
335 pthread_setname_np(pimpl_->thread, "McDaemon.FileSystem");
336 return 0;
337 }
338
339 int FileSystem::close() {
340 // Stop listening thread
341 pthread_kill(pimpl_->thread, SIGUSR1);
342 pthread_join(pimpl_->thread, NULL);
343
344 /* Clear DCI message buffer */
345 ::memset(&pimpl_->dci, 0, sizeof(pimpl_->dci));
346 return 0;
347 }
348
349 /*
350 * main
351 */
352 void FileSystem::Impl::run() {
353 // Only accept USR1, to give up
354 sigset_t sigmask;
355 sigemptyset(&sigmask);
356 sigaddset(&sigmask, SIGUSR1);
357 pthread_sigmask(SIG_UNBLOCK, &sigmask, (sigset_t*)0);
358
359 mcResult_t mc_ret = mcOpenDevice(MC_DEVICE_ID_DEFAULT);
360 if (MC_DRV_OK != mc_ret) {
361 LOG_E("%s: mcOpenDevice returned: 0x%08X\n", __func__, mc_ret);
362 return;
363 }
364
365 const mcUuid_t uuid = SERVICE_DELEGATION_UUID;
366 mcSessionHandle_t session_handle;
367 session_handle.deviceId = MC_DEVICE_ID_DEFAULT;
368 mc_ret = mcOpenSession(&session_handle, &uuid, reinterpret_cast<uint8_t*>(&dci),
369 sizeof(dci));
370 if (MC_DRV_OK != mc_ret) {
371 LOG_E("%s: mcOpenSession returned: 0x%08X\n", __func__, mc_ret);
372 mcCloseDevice(MC_DEVICE_ID_DEFAULT);
373 return;
374 }
375
376 LOG_I("%s: Start listening for request from STH2", __func__);
377 while (true) {
378 /* Wait for notification from SWd */
379 LOG_D("%s: Waiting for notification\n", __func__);
380 mc_ret = mcWaitNotification(&session_handle, MC_INFINITE_TIMEOUT_INTERRUPTIBLE);
381 if (mc_ret != MC_DRV_OK) {
382 LOG_E("%s: mcWaitNotification failed, error=0x%08X\n", __func__, mc_ret);
383 break;
384 }
385
386 /* Read sector size */
387 if (sector_size == 0) {
388 sector_size = dci.exchange_buffer.nSectorSize;
389 LOG_D("%s: Sector Size: %d bytes", __func__, sector_size);
390
391 /* Check sector size */
392 if (!(sector_size == 512 || sector_size == 1024 ||
393 sector_size == 2048 || sector_size == 4096)) {
394 LOG_E("%s: Incorrect sector size: terminating...", __func__);
395 break;
396 }
397 }
398
399 LOG_D("%s: Received Command from STH2\n", __func__);
400 if (executeCommand()) {
401 break;
402 }
403
404 /* Set "listening" flag before notifying SPT2 */
405 dci.exchange_buffer.nDaemonState = STH2_DAEMON_LISTENING;
406 mc_ret = mcNotify(&session_handle);
407 if (mc_ret != MC_DRV_OK) {
408 LOG_E("%s: mcNotify() returned: 0x%08X\n", __func__, mc_ret);
409 break;
410 }
411 }
412
413 mc_ret = mcCloseSession(&session_handle);
414 if (MC_DRV_OK != mc_ret) {
415 LOG_E("%s: mcCloseSession returned: 0x%08X\n", __func__, mc_ret);
416 }
417
418 mc_ret = mcCloseDevice(MC_DEVICE_ID_DEFAULT);
419 if (MC_DRV_OK != mc_ret) {
420 LOG_E("%s: mcCloseDevice returned: 0x%08X\n", __func__, mc_ret);
421 }
422
423 LOG_W("%s: Exiting Filesystem thread", __func__);
424 }
425
426 /*----------------------------------------------------------------------------
427 * Instructions
428 *----------------------------------------------------------------------------*/
429
430 /*----------------------------------------------------------------------------
431 * Command dispatcher function
432 *----------------------------------------------------------------------------*/
433 /* Debug function to show the command name */
434 const char* FileSystem::Impl::getCommandtypeString(uint32_t nInstructionID) {
435 switch (nInstructionID) {
436 case DELEGATION_INSTRUCTION_PARTITION_CREATE:
437 return "PARTITION_CREATE";
438 case DELEGATION_INSTRUCTION_PARTITION_OPEN:
439 return "PARTITION_OPEN";
440 case DELEGATION_INSTRUCTION_PARTITION_READ:
441 return "PARTITION_READ";
442 case DELEGATION_INSTRUCTION_PARTITION_WRITE:
443 return "PARTITION_WRITE";
444 case DELEGATION_INSTRUCTION_PARTITION_SET_SIZE:
445 return "PARTITION_SET_SIZE";
446 case DELEGATION_INSTRUCTION_PARTITION_SYNC:
447 return "PARTITION_SYNC";
448 case DELEGATION_INSTRUCTION_PARTITION_CLOSE:
449 return "PARTITION_CLOSE";
450 case DELEGATION_INSTRUCTION_PARTITION_DESTROY:
451 return "PARTITION_DESTROY";
452 case DELEGATION_INSTRUCTION_SHUTDOWN:
453 return "SHUTDOWN";
454 case DELEGATION_INSTRUCTION_NOTIFY:
455 return "NOTIFY";
456 default:
457 return "UNKNOWN";
458 }
459 }
460
461 int FileSystem::Impl::executeCommand() {
462 TEEC_Result nError;
463 uint32_t nInstructionsIndex;
464 uint32_t nInstructionsBufferSize =
465 dci.exchange_buffer.nInstructionsBufferSize;
466
467
468 LOG_D("%s: nInstructionsBufferSize=%d", __func__, nInstructionsBufferSize);
469
470 /* Reset the operation results */
471 nError = TEEC_SUCCESS;
472 dci.exchange_buffer.sAdministrativeData.nSyncExecuted = 0;
473 ::memset(dci.exchange_buffer.sAdministrativeData.nPartitionErrorStates, 0,
474 sizeof(dci.exchange_buffer.sAdministrativeData.nPartitionErrorStates));
475 ::memset(dci.exchange_buffer.sAdministrativeData.nPartitionOpenSizes, 0,
476 sizeof(dci.exchange_buffer.sAdministrativeData.nPartitionOpenSizes));
477
478 /* Execute the instructions */
479 nInstructionsIndex = 0;
480 while (true) {
481 DELEGATION_INSTRUCTION* pInstruction;
482 uint32_t nInstructionID;
483 pInstruction = (DELEGATION_INSTRUCTION*)(
484 &dci.exchange_buffer.sInstructions[nInstructionsIndex/4]);
485 if (nInstructionsIndex + 4 > nInstructionsBufferSize) {
486 LOG_D("%s: Instruction buffer end, size = %i", __func__,
487 nInstructionsBufferSize);
488 return 0;
489 }
490
491 nInstructionID = pInstruction->sGeneric.nInstructionID;
492 nInstructionsIndex += 4;
493
494 LOG_D("%s: nInstructionID=0x%02X [%s], nInstructionsIndex=%d", __func__,
495 nInstructionID, getCommandtypeString(nInstructionID), nInstructionsIndex);
496
497 if ((nInstructionID & 0x0F) == 0) {
498 /* Partition-independent instruction */
499 switch (nInstructionID) {
500 case DELEGATION_INSTRUCTION_SHUTDOWN: {
501 return 1;
502 }
503 case DELEGATION_INSTRUCTION_NOTIFY: {
504 /* Parse the instruction parameters */
505 wchar_t pMessage[100];
506 uint32_t nMessageType;
507 uint32_t nMessageSize;
508 ::memset(pMessage, 0, 100*sizeof(wchar_t));
509
510 if (nInstructionsIndex + 8 > nInstructionsBufferSize) {
511 return 0;
512 }
513
514 nMessageType = pInstruction->sNotify.nMessageType;
515 nMessageSize = pInstruction->sNotify.nMessageSize;
516 nInstructionsIndex += 8;
517 if (nMessageSize > (99)*sizeof(wchar_t)) {
518 /* How to handle the error correctly in this case ? */
519 return 0;
520 }
521
522 if (nInstructionsIndex + nMessageSize > nInstructionsBufferSize) {
523 return 0;
524 }
525
526 ::memcpy(pMessage, &pInstruction->sNotify.nMessage[0], nMessageSize);
527 nInstructionsIndex += nMessageSize;
528 /* Align the pInstructionsIndex on 4 bytes */
529 nInstructionsIndex = (nInstructionsIndex + 3)&~3;
530 switch (nMessageType) {
531 case DELEGATION_NOTIFY_TYPE_ERROR:
532 LOG_E("%s: %ls", __func__, pMessage);
533 break;
534 case DELEGATION_NOTIFY_TYPE_WARNING:
535 LOG_W("%s: %ls", __func__, pMessage);
536 break;
537 case DELEGATION_NOTIFY_TYPE_DEBUG:
538 LOG_D("%s: DEBUG: %ls", __func__, pMessage);
539 break;
540 default:
541 LOG_D("%s: %ls", __func__, pMessage);
542 }
543 break;
544 }
545 default: {
546 LOG_E("%s: Unknown instruction identifier: %02X", __func__, nInstructionID);
547 nError = S_ERROR_BAD_PARAMETERS;
548 break;
549 }
550 }
551 } else {
552 /* Partition-specific instruction */
553 uint32_t nPartitionID = (nInstructionID & 0xF0) >> 4;
554 Partition* partition = partitions[nPartitionID];
555 if (dci.exchange_buffer.sAdministrativeData.nPartitionErrorStates[nPartitionID]
556 == S_SUCCESS) {
557 /* Execute the instruction only if there is currently no error on the partition */
558 switch (nInstructionID & 0x0F) {
559 case DELEGATION_INSTRUCTION_PARTITION_CREATE: {
560 nError = partition->create();
561 LOG_D("%s: INSTRUCTION: ID=0x%x pid=%d err=0x%08X", __func__,
562 (nInstructionID & 0x0F), nPartitionID, nError);
563 break;
564 }
565 case DELEGATION_INSTRUCTION_PARTITION_OPEN: {
566 nError = partition->open();
567 LOG_D("%s: INSTRUCTION: ID=0x%x pid=%d pSize=%ld err=0x%08X", __func__,
568 (nInstructionID & 0x0F), nPartitionID, partition->size() / sector_size,
569 nError);
570 if (nError == S_SUCCESS) {
571 dci.exchange_buffer.sAdministrativeData.nPartitionOpenSizes[nPartitionID] =
572 static_cast<unsigned int>(partition->size() / sector_size);
573 }
574 break;
575 }
576 case DELEGATION_INSTRUCTION_PARTITION_READ: {
577 /* Parse parameters */
578 uint32_t nSectorID;
579 uint32_t nWorkspaceOffset;
580 if (nInstructionsIndex + 8 > nInstructionsBufferSize) {
581 return 0;
582 }
583
584 nSectorID = pInstruction->sReadWrite.nSectorID;
585 nWorkspaceOffset = pInstruction->sReadWrite.nWorkspaceOffset;
586 nInstructionsIndex += 8;
587 LOG_D("%s: >Partition %1X: read sector 0x%08X into workspace at offset 0x%08X",
588 __func__, nPartitionID, nSectorID, nWorkspaceOffset);
589 nError = partition->read(dci.exchange_buffer.sWorkspace + nWorkspaceOffset,
590 sector_size, nSectorID * sector_size);
591 LOG_D("%s: INSTRUCTION: ID=0x%x pid=%d sid=%d woff=%d err=0x%08X", __func__,
592 (nInstructionID & 0x0F), nPartitionID, nSectorID, nWorkspaceOffset, nError);
593 break;
594 }
595 case DELEGATION_INSTRUCTION_PARTITION_WRITE: {
596 /* Parse parameters */
597 uint32_t nSectorID;
598 uint32_t nWorkspaceOffset;
599 if (nInstructionsIndex + 8 > nInstructionsBufferSize) {
600 return 0;
601 }
602
603 nSectorID = pInstruction->sReadWrite.nSectorID;
604 nWorkspaceOffset = pInstruction->sReadWrite.nWorkspaceOffset;
605 nInstructionsIndex += 8;
606 LOG_D("%s: >Partition %1X: write sector 0x%X from workspace at offset 0x%X",
607 __func__, nPartitionID, nSectorID, nWorkspaceOffset);
608 nError = partition->write(dci.exchange_buffer.sWorkspace + nWorkspaceOffset,
609 sector_size, nSectorID * sector_size);
610 LOG_D("%s: INSTRUCTION: ID=0x%x pid=%d sid=%d woff=%d err=0x%08X", __func__,
611 (nInstructionID & 0x0F), nPartitionID, nSectorID, nWorkspaceOffset, nError);
612 break;
613 }
614 case DELEGATION_INSTRUCTION_PARTITION_SYNC: {
615 nError = partition->sync();
616 LOG_D("%s: INSTRUCTION: ID=0x%x pid=%d err=0x%08X", __func__,
617 (nInstructionID & 0x0F), nPartitionID, nError);
618 if (nError == S_SUCCESS) {
619 dci.exchange_buffer.sAdministrativeData.nSyncExecuted++;
620 }
621 break;
622 }
623 case DELEGATION_INSTRUCTION_PARTITION_SET_SIZE: {
624 // nNewSize is a number of sectors
625 uint32_t nNewSize;
626 if (nInstructionsIndex + 4 > nInstructionsBufferSize) {
627 return 0;
628 }
629
630 nNewSize = pInstruction->sSetSize.nNewSize;
631 nInstructionsIndex += 4;
632 nError = partition->resize(nNewSize * sector_size);
633 LOG_D("%s: INSTRUCTION: ID=0x%x pid=%d nNewSize=%d err=0x%08X", __func__,
634 (nInstructionID & 0x0F), nPartitionID, nNewSize, nError);
635 break;
636 }
637 case DELEGATION_INSTRUCTION_PARTITION_CLOSE: {
638 nError = partition->close();
639 LOG_D("%s: INSTRUCTION: ID=0x%x pid=%d err=0x%08X", __func__,
640 (nInstructionID & 0x0F), nPartitionID, nError);
641 break;
642 }
643 case DELEGATION_INSTRUCTION_PARTITION_DESTROY: {
644 nError = partition->destroy();
645 LOG_D("%s: INSTRUCTION: ID=0x%x pid=%d err=0x%08X", __func__,
646 (nInstructionID & 0x0F), nPartitionID, nError);
647 break;
648 }
649 default: {
650 LOG_E("%s: Unknown instruction identifier: %02X", __func__, nInstructionID);
651 nError = S_ERROR_BAD_PARAMETERS;
652 break;
653 }
654 }
655 dci.exchange_buffer.sAdministrativeData.nPartitionErrorStates[nPartitionID] =
656 nError;
657 } else {
658 /* Skip the instruction if there is currently error on the partition */
659 switch (nInstructionID & 0x0F) {
660 case DELEGATION_INSTRUCTION_PARTITION_CREATE:
661 case DELEGATION_INSTRUCTION_PARTITION_OPEN:
662 case DELEGATION_INSTRUCTION_PARTITION_SYNC:
663 case DELEGATION_INSTRUCTION_PARTITION_CLOSE:
664 case DELEGATION_INSTRUCTION_PARTITION_DESTROY:
665 break;
666 case DELEGATION_INSTRUCTION_PARTITION_READ:
667 case DELEGATION_INSTRUCTION_PARTITION_WRITE: {
668 if (nInstructionsIndex + 8 > nInstructionsBufferSize) {
669 return 0;
670 }
671 nInstructionsIndex += 8;
672 break;
673 }
674 case DELEGATION_INSTRUCTION_PARTITION_SET_SIZE: {
675 if (nInstructionsIndex + 4 > nInstructionsBufferSize) {
676 return 0;
677 }
678 nInstructionsIndex += 4;
679 break;
680 }
681 default: {
682 LOG_E("%s: Unknown instruction identifier: %02X", __func__, nInstructionID);
683 /* OMS: update partition error with BAD PARAM ? */
684 break;
685 }
686 }
687 }
688 }
689 }
690 return 0;
691 }